Implementar cambio de sprite dinámico con hot-swap (Tecla N)
Sistema de múltiples texturas: - Carga ball.png (10x10) y ball_small.png (6x6) al inicio - Variable current_ball_size_ obtiene tamaño desde texture->getWidth() - Eliminar constante BALL_SIZE hardcoded Cambio de tamaño con ajuste de posiciones: - updateBallSizes() ajusta pos según gravedad y superficie - DOWN: mueve Y hacia abajo si crece - UP: mueve Y hacia arriba si crece - LEFT/RIGHT: mueve X correspondiente - Solo ajusta pelotas en superficie (isOnSurface()) Ball class actualizada: - Constructor recibe ball_size como parámetro - updateSize(new_size): actualiza hitbox y sprite - setTexture(texture): cambia textura del sprite - setPosition() usa setRotoBallScreenPosition() Sprite class: - Añadido setTexture() inline para hot-swap Tecla N: - Cicla entre texturas disponibles - Actualiza todas las pelotas sin reiniciar física - Texto informativo "SPRITE: NORMAL" / "SPRITE: SMALL" Fix bug initBalls(): - Ahora usa current_ball_size_ en constructor - Pelotas nuevas tienen tamaño correcto según textura activa 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <cmath> // for fabs
|
#include <cmath> // for fabs
|
||||||
|
|
||||||
#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE
|
#include "defines.h" // for Color, SCREEN_HEIGHT, GRAVITY_FORCE
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Función auxiliar para generar pérdida aleatoria en rebotes
|
// Función auxiliar para generar pérdida aleatoria en rebotes
|
||||||
@@ -22,15 +22,15 @@ float generateLateralLoss() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture, int screen_width, int screen_height, GravityDirection gravity_dir, float mass_factor)
|
Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture, int screen_width, int screen_height, int ball_size, GravityDirection gravity_dir, float mass_factor)
|
||||||
: sprite_(std::make_unique<Sprite>(texture)),
|
: sprite_(std::make_unique<Sprite>(texture)),
|
||||||
pos_({x, 0.0f, BALL_SIZE, BALL_SIZE}) {
|
pos_({x, 0.0f, static_cast<float>(ball_size), static_cast<float>(ball_size)}) {
|
||||||
// Convertir velocidades de píxeles/frame a píxeles/segundo (multiplicar por 60)
|
// Convertir velocidades de píxeles/frame a píxeles/segundo (multiplicar por 60)
|
||||||
vx_ = vx * 60.0f;
|
vx_ = vx * 60.0f;
|
||||||
vy_ = vy * 60.0f;
|
vy_ = vy * 60.0f;
|
||||||
sprite_->setPos({pos_.x, pos_.y});
|
sprite_->setPos({pos_.x, pos_.y});
|
||||||
sprite_->setSize(BALL_SIZE, BALL_SIZE);
|
sprite_->setSize(ball_size, ball_size);
|
||||||
sprite_->setClip({0, 0, BALL_SIZE, BALL_SIZE});
|
sprite_->setClip({0.0f, 0.0f, static_cast<float>(ball_size), static_cast<float>(ball_size)});
|
||||||
color_ = color;
|
color_ = color;
|
||||||
// Convertir gravedad de píxeles/frame² a píxeles/segundo² (multiplicar por 60²)
|
// Convertir gravedad de píxeles/frame² a píxeles/segundo² (multiplicar por 60²)
|
||||||
gravity_force_ = GRAVITY_FORCE * 60.0f * 60.0f;
|
gravity_force_ = GRAVITY_FORCE * 60.0f * 60.0f;
|
||||||
@@ -378,4 +378,20 @@ void Ball::applyRotoBallForce(float target_x, float target_y, float sphere_radiu
|
|||||||
|
|
||||||
// Actualizar sprite para renderizado
|
// Actualizar sprite para renderizado
|
||||||
sprite_->setPos({pos_.x, pos_.y});
|
sprite_->setPos({pos_.x, pos_.y});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sistema de cambio de sprite dinámico
|
||||||
|
void Ball::updateSize(int new_size) {
|
||||||
|
// Actualizar tamaño del hitbox
|
||||||
|
pos_.w = static_cast<float>(new_size);
|
||||||
|
pos_.h = static_cast<float>(new_size);
|
||||||
|
|
||||||
|
// Actualizar sprite
|
||||||
|
sprite_->setSize(new_size, new_size);
|
||||||
|
sprite_->setClip({0.0f, 0.0f, static_cast<float>(new_size), static_cast<float>(new_size)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ball::setTexture(std::shared_ptr<Texture> texture) {
|
||||||
|
// Actualizar textura del sprite
|
||||||
|
sprite_->setTexture(texture);
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ class Ball {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture, int screen_width, int screen_height, GravityDirection gravity_dir = GravityDirection::DOWN, float mass_factor = 1.0f);
|
Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture, int screen_width, int screen_height, int ball_size, GravityDirection gravity_dir = GravityDirection::DOWN, float mass_factor = 1.0f);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Ball() = default;
|
~Ball() = default;
|
||||||
@@ -78,6 +78,10 @@ class Ball {
|
|||||||
Color getColor() const { return color_; }
|
Color getColor() const { return color_; }
|
||||||
void setColor(const Color& color) { color_ = color; }
|
void setColor(const Color& color) { color_ = color; }
|
||||||
|
|
||||||
|
// Sistema de cambio de sprite dinámico
|
||||||
|
void updateSize(int new_size); // Actualizar tamaño de hitbox
|
||||||
|
void setTexture(std::shared_ptr<Texture> texture); // Cambiar textura del sprite
|
||||||
|
|
||||||
// Funciones para modo RotoBall
|
// Funciones para modo RotoBall
|
||||||
void setRotoBallPosition3D(float x, float y, float z);
|
void setRotoBallPosition3D(float x, float y, float z);
|
||||||
void setRotoBallTarget2D(float x, float y);
|
void setRotoBallTarget2D(float x, float y);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ constexpr char WINDOW_CAPTION[] = "vibe3_physics";
|
|||||||
constexpr int SCREEN_WIDTH = 320; // Ancho de la pantalla lógica (píxeles)
|
constexpr int SCREEN_WIDTH = 320; // Ancho de la pantalla lógica (píxeles)
|
||||||
constexpr int SCREEN_HEIGHT = 240; // Alto de la pantalla lógica (píxeles)
|
constexpr int SCREEN_HEIGHT = 240; // Alto de la pantalla lógica (píxeles)
|
||||||
constexpr int WINDOW_ZOOM = 3; // Zoom inicial de la ventana
|
constexpr int WINDOW_ZOOM = 3; // Zoom inicial de la ventana
|
||||||
constexpr int BALL_SIZE = 10; // Tamaño de las pelotas (píxeles)
|
// BALL_SIZE eliminado: ahora se obtiene dinámicamente desde texture_->getWidth()
|
||||||
|
|
||||||
// Configuración de zoom dinámico de ventana
|
// Configuración de zoom dinámico de ventana
|
||||||
constexpr int WINDOW_ZOOM_MIN = 1; // Zoom mínimo (320x240)
|
constexpr int WINDOW_ZOOM_MIN = 1; // Zoom mínimo (320x240)
|
||||||
|
|||||||
@@ -80,10 +80,22 @@ bool Engine::initialize() {
|
|||||||
|
|
||||||
// Inicializar otros componentes si SDL se inicializó correctamente
|
// Inicializar otros componentes si SDL se inicializó correctamente
|
||||||
if (success) {
|
if (success) {
|
||||||
// Construir ruta absoluta a la imagen
|
// Cargar todas las texturas disponibles
|
||||||
std::string exe_dir = getExecutableDirectory();
|
std::string exe_dir = getExecutableDirectory();
|
||||||
std::string texture_path = exe_dir + "/data/ball.png";
|
|
||||||
texture_ = std::make_shared<Texture>(renderer_, texture_path);
|
// Textura 0: ball.png (10x10)
|
||||||
|
std::string texture_path_normal = exe_dir + "/data/ball.png";
|
||||||
|
textures_.push_back(std::make_shared<Texture>(renderer_, texture_path_normal));
|
||||||
|
|
||||||
|
// Textura 1: ball_small.png (6x6)
|
||||||
|
std::string texture_path_small = exe_dir + "/data/ball_small.png";
|
||||||
|
textures_.push_back(std::make_shared<Texture>(renderer_, texture_path_small));
|
||||||
|
|
||||||
|
// Establecer textura inicial (índice 0)
|
||||||
|
current_texture_index_ = 0;
|
||||||
|
texture_ = textures_[current_texture_index_];
|
||||||
|
current_ball_size_ = texture_->getWidth(); // Obtener tamaño dinámicamente
|
||||||
|
|
||||||
srand(static_cast<unsigned>(time(nullptr)));
|
srand(static_cast<unsigned>(time(nullptr)));
|
||||||
dbg_init(renderer_);
|
dbg_init(renderer_);
|
||||||
initializeThemes();
|
initializeThemes();
|
||||||
@@ -337,6 +349,11 @@ void Engine::handleEvents() {
|
|||||||
startThemeTransition(ColorTheme::MONOCHROME);
|
startThemeTransition(ColorTheme::MONOCHROME);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Cambio de sprite/textura dinámico
|
||||||
|
case SDLK_N:
|
||||||
|
switchTexture();
|
||||||
|
break;
|
||||||
|
|
||||||
// Control de escala de figura (solo en modo SHAPE)
|
// Control de escala de figura (solo en modo SHAPE)
|
||||||
case SDLK_KP_PLUS:
|
case SDLK_KP_PLUS:
|
||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
@@ -609,7 +626,7 @@ void Engine::initBalls(int value) {
|
|||||||
const Color COLOR = theme.ball_colors[color_index];
|
const Color COLOR = theme.ball_colors[color_index];
|
||||||
// Generar factor de masa aleatorio (0.7 = ligera, 1.3 = pesada)
|
// Generar factor de masa aleatorio (0.7 = ligera, 1.3 = pesada)
|
||||||
float mass_factor = GRAVITY_MASS_MIN + (rand() % 1000) / 1000.0f * (GRAVITY_MASS_MAX - GRAVITY_MASS_MIN);
|
float mass_factor = GRAVITY_MASS_MIN + (rand() % 1000) / 1000.0f * (GRAVITY_MASS_MAX - GRAVITY_MASS_MIN);
|
||||||
balls_.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture_, current_screen_width_, current_screen_height_, current_gravity_, mass_factor));
|
balls_.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture_, current_screen_width_, current_screen_height_, current_ball_size_, current_gravity_, mass_factor));
|
||||||
}
|
}
|
||||||
setText(); // Actualiza el texto
|
setText(); // Actualiza el texto
|
||||||
}
|
}
|
||||||
@@ -1113,6 +1130,80 @@ void Engine::performRandomRestart() {
|
|||||||
all_balls_stopped_start_time_ = 0;
|
all_balls_stopped_start_time_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sistema de cambio de sprites dinámico
|
||||||
|
void Engine::updateBallSizes(int old_size, int new_size) {
|
||||||
|
float delta_size = static_cast<float>(new_size - old_size);
|
||||||
|
|
||||||
|
for (auto& ball : balls_) {
|
||||||
|
SDL_FRect pos = ball->getPosition();
|
||||||
|
|
||||||
|
// Solo ajustar posición si la pelota está en superficie
|
||||||
|
if (ball->isOnSurface()) {
|
||||||
|
GravityDirection grav_dir = ball->getGravityDirection();
|
||||||
|
|
||||||
|
switch (grav_dir) {
|
||||||
|
case GravityDirection::DOWN:
|
||||||
|
// Superficie inferior: ajustar Y hacia abajo si crece
|
||||||
|
pos.y += delta_size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GravityDirection::UP:
|
||||||
|
// Superficie superior: ajustar Y hacia arriba si crece
|
||||||
|
pos.y -= delta_size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GravityDirection::LEFT:
|
||||||
|
// Superficie izquierda: ajustar X hacia izquierda si crece
|
||||||
|
pos.x -= delta_size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GravityDirection::RIGHT:
|
||||||
|
// Superficie derecha: ajustar X hacia derecha si crece
|
||||||
|
pos.x += delta_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar tamaño del hitbox
|
||||||
|
ball->updateSize(new_size);
|
||||||
|
|
||||||
|
// Si ajustamos posición, aplicarla ahora
|
||||||
|
if (ball->isOnSurface()) {
|
||||||
|
ball->setRotoBallScreenPosition(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::switchTexture() {
|
||||||
|
if (textures_.empty()) return;
|
||||||
|
|
||||||
|
// Guardar tamaño antiguo
|
||||||
|
int old_size = current_ball_size_;
|
||||||
|
|
||||||
|
// Cambiar a siguiente textura (ciclar)
|
||||||
|
current_texture_index_ = (current_texture_index_ + 1) % textures_.size();
|
||||||
|
texture_ = textures_[current_texture_index_];
|
||||||
|
|
||||||
|
// Obtener nuevo tamaño de la textura
|
||||||
|
int new_size = texture_->getWidth();
|
||||||
|
current_ball_size_ = new_size;
|
||||||
|
|
||||||
|
// Actualizar texturas y tamaños de todas las pelotas
|
||||||
|
for (auto& ball : balls_) {
|
||||||
|
ball->setTexture(texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajustar posiciones según el cambio de tamaño
|
||||||
|
updateBallSizes(old_size, new_size);
|
||||||
|
|
||||||
|
// Mostrar texto informativo
|
||||||
|
std::string texture_name = (current_texture_index_ == 0) ? "NORMAL" : "SMALL";
|
||||||
|
text_ = "SPRITE: " + texture_name;
|
||||||
|
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2;
|
||||||
|
show_text_ = true;
|
||||||
|
text_init_time_ = SDL_GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
// Sistema de Figuras 3D - Alternar entre modo física y última figura (Toggle con tecla F)
|
// Sistema de Figuras 3D - Alternar entre modo física y última figura (Toggle con tecla F)
|
||||||
void Engine::toggleShapeMode(bool force_gravity_on_exit) {
|
void Engine::toggleShapeMode(bool force_gravity_on_exit) {
|
||||||
if (current_mode_ == SimulationMode::PHYSICS) {
|
if (current_mode_ == SimulationMode::PHYSICS) {
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ private:
|
|||||||
// Recursos SDL
|
// Recursos SDL
|
||||||
SDL_Window* window_ = nullptr;
|
SDL_Window* window_ = nullptr;
|
||||||
SDL_Renderer* renderer_ = nullptr;
|
SDL_Renderer* renderer_ = nullptr;
|
||||||
std::shared_ptr<Texture> texture_ = nullptr;
|
std::shared_ptr<Texture> texture_ = nullptr; // Textura activa actual
|
||||||
|
std::vector<std::shared_ptr<Texture>> textures_; // Todas las texturas disponibles
|
||||||
|
size_t current_texture_index_ = 0; // Índice de textura activa
|
||||||
|
int current_ball_size_ = 10; // Tamaño actual de pelotas (dinámico, se actualiza desde texture)
|
||||||
|
|
||||||
// Estado del simulador
|
// Estado del simulador
|
||||||
std::vector<std::unique_ptr<Ball>> balls_;
|
std::vector<std::unique_ptr<Ball>> balls_;
|
||||||
@@ -128,6 +131,10 @@ private:
|
|||||||
Color getInterpolatedColor(size_t ball_index) const; // Obtener color interpolado durante transición
|
Color getInterpolatedColor(size_t ball_index) const; // Obtener color interpolado durante transición
|
||||||
void startThemeTransition(ColorTheme new_theme);
|
void startThemeTransition(ColorTheme new_theme);
|
||||||
|
|
||||||
|
// Sistema de cambio de sprites dinámico
|
||||||
|
void switchTexture(); // Cambia a siguiente textura disponible
|
||||||
|
void updateBallSizes(int old_size, int new_size); // Ajusta posiciones al cambiar tamaño
|
||||||
|
|
||||||
// Sistema de zoom dinámico
|
// Sistema de zoom dinámico
|
||||||
int calculateMaxWindowZoom() const;
|
int calculateMaxWindowZoom() const;
|
||||||
void setWindowZoom(int new_zoom);
|
void setWindowZoom(int new_zoom);
|
||||||
|
|||||||
3
source/external/sprite.h
vendored
3
source/external/sprite.h
vendored
@@ -32,4 +32,7 @@ class Sprite {
|
|||||||
|
|
||||||
// Modulación de color
|
// Modulación de color
|
||||||
void setColor(int r, int g, int b);
|
void setColor(int r, int g, int b);
|
||||||
|
|
||||||
|
// Cambio de textura dinámico
|
||||||
|
void setTexture(std::shared_ptr<Texture> texture) { texture_ = texture; }
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user