diff --git a/source/ball.cpp b/source/ball.cpp index 2d4b448..128f8c7 100644 --- a/source/ball.cpp +++ b/source/ball.cpp @@ -1,14 +1,16 @@ #include "ball.h" + #include // for rand -#include // for fabs -#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE + +#include // for fabs + +#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE class Texture; // Constructor Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr texture) : sprite_(std::make_unique(texture)), - pos_({x, 0.0f, BALL_SIZE, BALL_SIZE}) -{ + pos_({x, 0.0f, BALL_SIZE, BALL_SIZE}) { // Convertir velocidades de píxeles/frame a píxeles/segundo (multiplicar por 60) vx_ = vx * 60.0f; vy_ = vy * 60.0f; @@ -24,58 +26,48 @@ Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr te } // Actualiza la lógica de la clase -void Ball::update(float deltaTime) -{ - if (stopped_) - { +void Ball::update(float deltaTime) { + if (stopped_) { return; } // Aplica la gravedad a la velocidad (píxeles/segundo²) - if (!on_floor_) - { + if (!on_floor_) { vy_ += gravity_force_ * deltaTime; } // Actualiza la posición en función de la velocidad (píxeles/segundo) pos_.x += vx_ * deltaTime; - if (!on_floor_) - { + if (!on_floor_) { pos_.y += vy_ * deltaTime; - } - else - { + } else { // Si está en el suelo, mantenerla ahí pos_.y = SCREEN_HEIGHT - pos_.h; } // Comprueba las colisiones con el lateral izquierdo - if (pos_.x < 0) - { + if (pos_.x < 0) { pos_.x = 0; vx_ = -vx_; } // Comprueba las colisiones con el lateral derecho - if (pos_.x + pos_.w > SCREEN_WIDTH) - { + if (pos_.x + pos_.w > SCREEN_WIDTH) { pos_.x = SCREEN_WIDTH - pos_.w; vx_ = -vx_; } // Comprueba las colisiones con la parte superior - if (pos_.y < 0) - { + if (pos_.y < 0) { pos_.y = 0; vy_ = -vy_; } // Comprueba las colisiones con la parte inferior - if (pos_.y + pos_.h > SCREEN_HEIGHT) - { + if (pos_.y + pos_.h > SCREEN_HEIGHT) { pos_.y = SCREEN_HEIGHT - pos_.h; vy_ = -vy_ * loss_; - if (std::fabs(vy_) < 6.0f) // Convertir 0.1f frame-based a 6.0f time-based + if (std::fabs(vy_) < 6.0f) // Convertir 0.1f frame-based a 6.0f time-based { vy_ = 0.0f; on_floor_ = true; @@ -83,15 +75,14 @@ void Ball::update(float deltaTime) } // Aplica rozamiento al rodar por el suelo - if (on_floor_) - { + if (on_floor_) { // Convertir rozamiento de frame-based a time-based // 0.97f por frame equivale a pow(0.97f, 60 * deltaTime) float friction_factor = pow(0.97f, 60.0f * deltaTime); vx_ = vx_ * friction_factor; // Umbral de parada ajustado para velocidades en píxeles/segundo - if (std::fabs(vx_) < 6.0f) // ~0.1f * 60 para time-based + if (std::fabs(vx_) < 6.0f) // ~0.1f * 60 para time-based { vx_ = 0.0f; stopped_ = true; @@ -103,26 +94,22 @@ void Ball::update(float deltaTime) } // Pinta la clase -void Ball::render() -{ +void Ball::render() { sprite_->setColor(color_.r, color_.g, color_.b); sprite_->render(); } // Modifica la velocidad (convierte de frame-based a time-based) -void Ball::modVel(float vx, float vy) -{ - if (stopped_) - { - vx_ = vx_ + (vx * 60.0f); // Convertir a píxeles/segundo +void Ball::modVel(float vx, float vy) { + if (stopped_) { + vx_ = vx_ + (vx * 60.0f); // Convertir a píxeles/segundo } - vy_ = vy_ + (vy * 60.0f); // Convertir a píxeles/segundo + vy_ = vy_ + (vy * 60.0f); // Convertir a píxeles/segundo on_floor_ = false; stopped_ = false; } // Cambia la gravedad (usa la versión convertida) -void Ball::switchGravity() -{ +void Ball::switchGravity() { gravity_force_ = gravity_force_ == 0.0f ? (GRAVITY_FORCE * 60.0f * 60.0f) : 0.0f; } \ No newline at end of file diff --git a/source/ball.h b/source/ball.h index ebf1c6c..5ce9ab2 100644 --- a/source/ball.h +++ b/source/ball.h @@ -1,48 +1,49 @@ #pragma once #include // for SDL_FRect -#include // for shared_ptr, unique_ptr -#include "defines.h" // for Color -#include "external/sprite.h" // for Sprite + +#include // for shared_ptr, unique_ptr + +#include "defines.h" // for Color +#include "external/sprite.h" // for Sprite class Texture; -class Ball -{ -private: - std::unique_ptr sprite_; // Sprite para pintar la clase - SDL_FRect pos_; // Posición y tamaño de la pelota - float vx_, vy_; // Velocidad - float gravity_force_; // Gravedad - Color color_; // Color de la pelota - bool on_floor_; // Indica si la pelota está ya en el suelo - bool stopped_; // Indica si la pelota ha terminado de moverse; - float loss_; // Coeficiente de rebote. Pérdida de energía en cada rebote +class Ball { + private: + std::unique_ptr sprite_; // Sprite para pintar la clase + SDL_FRect pos_; // Posición y tamaño de la pelota + float vx_, vy_; // Velocidad + float gravity_force_; // Gravedad + Color color_; // Color de la pelota + bool on_floor_; // Indica si la pelota está ya en el suelo + bool stopped_; // Indica si la pelota ha terminado de moverse; + float loss_; // Coeficiente de rebote. Pérdida de energía en cada rebote -public: - // Constructor - Ball(float x, float vx, float vy, Color color, std::shared_ptr texture); + public: + // Constructor + Ball(float x, float vx, float vy, Color color, std::shared_ptr texture); - // Destructor - ~Ball() = default; + // Destructor + ~Ball() = default; - // Actualiza la lógica de la clase - void update(float deltaTime); + // Actualiza la lógica de la clase + void update(float deltaTime); - // Pinta la clase - void render(); + // Pinta la clase + void render(); - // Modifica la velocidad - void modVel(float vx, float vy); + // Modifica la velocidad + void modVel(float vx, float vy); - // Cambia la gravedad - void switchGravity(); + // Cambia la gravedad + void switchGravity(); - // Getters para debug - float getVelocityY() const { return vy_; } - float getGravityForce() const { return gravity_force_; } - bool isOnFloor() const { return on_floor_; } + // Getters para debug + float getVelocityY() const { return vy_; } + float getGravityForce() const { return gravity_force_; } + bool isOnFloor() const { return on_floor_; } - // Getters para batch rendering - SDL_FRect getPosition() const { return pos_; } - Color getColor() const { return color_; } + // Getters para batch rendering + SDL_FRect getPosition() const { return pos_; } + Color getColor() const { return color_; } }; \ No newline at end of file diff --git a/source/defines.h b/source/defines.h index b113d73..5f2ff95 100644 --- a/source/defines.h +++ b/source/defines.h @@ -11,7 +11,6 @@ constexpr float GRAVITY_FORCE = 0.2f; // DEMO_SPEED eliminado - ya no se usa con delta time constexpr Uint64 TEXT_DURATION = 2000; -struct Color -{ - int r, g, b; +struct Color { + int r, g, b; }; \ No newline at end of file diff --git a/source/external/dbgtxt.h b/source/external/dbgtxt.h index b9efa2c..a583ee2 100644 --- a/source/external/dbgtxt.h +++ b/source/external/dbgtxt.h @@ -1,24 +1,20 @@ #pragma once -namespace -{ - SDL_Texture *dbg_tex = nullptr; - SDL_Renderer *dbg_ren = nullptr; -} +namespace { +SDL_Texture* dbg_tex = nullptr; +SDL_Renderer* dbg_ren = nullptr; +} // namespace -void dbg_init(SDL_Renderer *renderer) -{ +void dbg_init(SDL_Renderer* renderer) { dbg_ren = renderer; Uint8 font[448] = {0x42, 0x4D, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0xF3, 0x83, 0x83, 0xCF, 0x83, 0x87, 0x00, 0x00, 0xF3, 0x39, 0x39, 0xCF, 0x79, 0xF3, 0x00, 0x00, 0x01, 0xF9, 0x39, 0xCF, 0x61, 0xF9, 0x00, 0x00, 0x33, 0xF9, 0x03, 0xE7, 0x87, 0x81, 0x00, 0x00, 0x93, 0x03, 0x3F, 0xF3, 0x1B, 0x39, 0x00, 0x00, 0xC3, 0x3F, 0x9F, 0x39, 0x3B, 0x39, 0x00, 0x41, 0xE3, 0x03, 0xC3, 0x01, 0x87, 0x83, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0x01, 0xC7, 0x81, 0x01, 0x83, 0x00, 0x00, 0xE7, 0x1F, 0x9B, 0xE7, 0x1F, 0x39, 0x00, 0x00, 0xE7, 0x8F, 0x39, 0xE7, 0x87, 0xF9, 0x00, 0x00, 0xC3, 0xC7, 0x39, 0xE7, 0xC3, 0xC3, 0x00, 0x00, 0x99, 0xE3, 0x39, 0xE7, 0xF1, 0xE7, 0x00, 0x00, 0x99, 0xF1, 0xB3, 0xC7, 0x39, 0xF3, 0x00, 0x00, 0x99, 0x01, 0xC7, 0xE7, 0x83, 0x81, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x83, 0xE7, 0x83, 0xEF, 0x39, 0x39, 0x00, 0x00, 0x39, 0xE7, 0x39, 0xC7, 0x11, 0x11, 0x00, 0x00, 0xF9, 0xE7, 0x39, 0x83, 0x01, 0x83, 0x00, 0x00, 0x83, 0xE7, 0x39, 0x11, 0x01, 0xC7, 0x00, 0x00, 0x3F, 0xE7, 0x39, 0x39, 0x29, 0x83, 0x00, 0x00, 0x33, 0xE7, 0x39, 0x39, 0x39, 0x11, 0x00, 0x00, 0x87, 0x81, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x39, 0x83, 0x3F, 0x85, 0x31, 0x00, 0x00, 0x39, 0x31, 0x39, 0x3F, 0x33, 0x23, 0x00, 0x00, 0x29, 0x21, 0x39, 0x03, 0x21, 0x07, 0x00, 0x00, 0x01, 0x01, 0x39, 0x39, 0x39, 0x31, 0x00, 0x00, 0x01, 0x09, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x11, 0x19, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x39, 0x39, 0x83, 0x03, 0x83, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xC1, 0x39, 0x81, 0x83, 0x31, 0x01, 0x00, 0x00, 0x99, 0x39, 0xE7, 0x39, 0x23, 0x3F, 0x00, 0x00, 0x39, 0x39, 0xE7, 0xF9, 0x07, 0x3F, 0x00, 0x00, 0x31, 0x01, 0xE7, 0xF9, 0x0F, 0x3F, 0x00, 0x00, 0x3F, 0x39, 0xE7, 0xF9, 0x27, 0x3F, 0x00, 0x00, 0x9F, 0x39, 0xE7, 0xF9, 0x33, 0x3F, 0x00, 0x00, 0xC1, 0x39, 0x81, 0xF9, 0x39, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x03, 0xC3, 0x07, 0x01, 0x3F, 0x00, 0x00, 0x39, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x39, 0x03, 0x3F, 0x39, 0x03, 0x03, 0x00, 0x00, 0x39, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x93, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0xC7, 0x03, 0xC3, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}; // Cargar surface del bitmap font SDL_Surface* font_surface = SDL_LoadBMP_IO(SDL_IOFromMem(font, 448), 1); - if (font_surface != nullptr) - { + if (font_surface != nullptr) { // Crear una nueva surface de 32 bits con canal alpha SDL_Surface* rgba_surface = SDL_CreateSurface(font_surface->w, font_surface->h, SDL_PIXELFORMAT_RGBA8888); - if (rgba_surface != nullptr) - { + if (rgba_surface != nullptr) { // Obtener píxeles de ambas surfaces Uint8* src_pixels = (Uint8*)font_surface->pixels; Uint32* dst_pixels = (Uint32*)rgba_surface->pixels; @@ -27,23 +23,20 @@ void dbg_init(SDL_Renderer *renderer) int height = font_surface->h; // Procesar cada píxel - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { int byte_index = y * font_surface->pitch + (x / 8); int bit_index = 7 - (x % 8); // Extraer bit del bitmap monocromo bool is_white = (src_pixels[byte_index] >> bit_index) & 1; - if (is_white) // Fondo blanco original -> transparente + if (is_white) // Fondo blanco original -> transparente { - dst_pixels[y * width + x] = 0x00000000; // Transparente - } - else // Texto negro original -> blanco opaco + dst_pixels[y * width + x] = 0x00000000; // Transparente + } else // Texto negro original -> blanco opaco { - dst_pixels[y * width + x] = 0xFFFFFFFF; // Blanco opaco + dst_pixels[y * width + x] = 0xFFFFFFFF; // Blanco opaco } } } @@ -55,31 +48,24 @@ void dbg_init(SDL_Renderer *renderer) } // Configurar filtro nearest neighbor para píxel perfect del texto - if (dbg_tex != nullptr) - { + if (dbg_tex != nullptr) { SDL_SetTextureScaleMode(dbg_tex, SDL_SCALEMODE_NEAREST); // Configurar blend mode para transparencia normal SDL_SetTextureBlendMode(dbg_tex, SDL_BLENDMODE_BLEND); } } -void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b) -{ +void dbg_print(int x, int y, const char* text, Uint8 r, Uint8 g, Uint8 b) { int cc = 0; SDL_SetTextureColorMod(dbg_tex, r, g, b); SDL_FRect src = {0, 0, 8, 8}; SDL_FRect dst = {static_cast(x), static_cast(y), 8, 8}; - while (text[cc] != 0) - { - if (text[cc] != 32) - { - if (text[cc] >= 65) - { + while (text[cc] != 0) { + if (text[cc] != 32) { + if (text[cc] >= 65) { src.x = ((text[cc] - 65) % 6) * 8; src.y = ((text[cc] - 65) / 6) * 8; - } - else - { + } else { src.x = ((text[cc] - 22) % 6) * 8; src.y = ((text[cc] - 22) / 6) * 8; } diff --git a/source/external/sprite.cpp b/source/external/sprite.cpp index e269f9f..9964225 100644 --- a/source/external/sprite.cpp +++ b/source/external/sprite.cpp @@ -1,4 +1,5 @@ #include "sprite.h" + #include "texture.h" // for Texture // Constructor @@ -8,33 +9,28 @@ Sprite::Sprite(std::shared_ptr texture) clip_{0.0f, 0.0f, 0.0f, 0.0f} {} // Establece la posición del sprite -void Sprite::setPos(SDL_FPoint pos) -{ +void Sprite::setPos(SDL_FPoint pos) { pos_.x = pos.x; pos_.y = pos.y; } // Pinta el sprite -void Sprite::render() -{ +void Sprite::render() { texture_->render(&clip_, &pos_); } // Establece el rectangulo de la textura que se va a pintar -void Sprite::setClip(SDL_FRect clip) -{ +void Sprite::setClip(SDL_FRect clip) { clip_ = clip; } // Establece el tamaño del sprite -void Sprite::setSize(float w, float h) -{ +void Sprite::setSize(float w, float h) { pos_.w = w; pos_.h = h; } // Modulación de color -void Sprite::setColor(int r, int g, int b) -{ +void Sprite::setColor(int r, int g, int b) { texture_->setColor(r, g, b); } \ No newline at end of file diff --git a/source/external/sprite.h b/source/external/sprite.h index 1caeeff..d6938ef 100644 --- a/source/external/sprite.h +++ b/source/external/sprite.h @@ -1,35 +1,35 @@ #pragma once #include // for SDL_FRect, SDL_FPoint -#include // for shared_ptr + +#include // for shared_ptr class Texture; -class Sprite -{ -private: - std::shared_ptr texture_; // Textura con los gráficos del sprite - SDL_FRect pos_; // Posición y tamaño del sprite - SDL_FRect clip_; // Parte de la textura que se va a dibujar +class Sprite { + private: + std::shared_ptr texture_; // Textura con los gráficos del sprite + SDL_FRect pos_; // Posición y tamaño del sprite + SDL_FRect clip_; // Parte de la textura que se va a dibujar -public: - // Constructor - explicit Sprite(std::shared_ptr texture); + public: + // Constructor + explicit Sprite(std::shared_ptr texture); - // Destructor - ~Sprite() = default; + // Destructor + ~Sprite() = default; - // Establece la posición del sprite - void setPos(SDL_FPoint pos); + // Establece la posición del sprite + void setPos(SDL_FPoint pos); - // Pinta el sprite - void render(); + // Pinta el sprite + void render(); - // Establece el rectangulo de la textura que se va a pintar - void setClip(SDL_FRect clip); + // Establece el rectangulo de la textura que se va a pintar + void setClip(SDL_FRect clip); - // Establece el tamaño del sprite - void setSize(float w, float h); + // Establece el tamaño del sprite + void setSize(float w, float h); - // Modulación de color - void setColor(int r, int g, int b); + // Modulación de color + void setColor(int r, int g, int b); }; \ No newline at end of file diff --git a/source/external/texture.cpp b/source/external/texture.cpp index 2e7cc41..d333480 100644 --- a/source/external/texture.cpp +++ b/source/external/texture.cpp @@ -1,55 +1,55 @@ #define STB_IMAGE_IMPLEMENTATION #include "texture.h" + #include // Para SDL_GetError #include // Para SDL_Log #include // Para SDL_PixelFormat #include // Para SDL_CreateSurfaceFrom, SDL_DestroySurface #include // Para NULL #include // Para exit -#include // Para basic_ostream, char_traits, operator<< -#include // Para operator<<, string -#include "stb_image.h" // Para stbi_failure_reason, stbi_image_free + +#include // Para basic_ostream, char_traits, operator<< +#include // Para operator<<, string + +#include "stb_image.h" // Para stbi_failure_reason, stbi_image_free Texture::Texture(SDL_Renderer *renderer) - : renderer_(renderer), texture_(nullptr), width_(0), height_(0) {} + : renderer_(renderer), + texture_(nullptr), + width_(0), + height_(0) {} Texture::Texture(SDL_Renderer *renderer, const std::string &file_path) - : renderer_(renderer), texture_(nullptr), width_(0), height_(0) -{ + : renderer_(renderer), + texture_(nullptr), + width_(0), + height_(0) { loadFromFile(file_path); } -Texture::~Texture() -{ +Texture::~Texture() { free(); } // Carga la imagen desde una ruta especificada -bool Texture::loadFromFile(const std::string &file_path) -{ +bool Texture::loadFromFile(const std::string &file_path) { const std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1); int req_format = STBI_rgb_alpha; int width, height, orig_format; unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format); - if (data == nullptr) - { + if (data == nullptr) { SDL_Log("Error al cargar la imagen: %s", stbi_failure_reason()); exit(1); - } - else - { + } else { std::cout << "Imagen cargada: " << filename.c_str() << std::endl; } int pitch; SDL_PixelFormat pixel_format; - if (req_format == STBI_rgb) - { - pitch = 3 * width; // 3 bytes por pixel * pixels por línea + if (req_format == STBI_rgb) { + pitch = 3 * width; // 3 bytes por pixel * pixels por línea pixel_format = SDL_PIXELFORMAT_RGB24; - } - else - { // STBI_rgb_alpha (RGBA) + } else { // STBI_rgb_alpha (RGBA) pitch = 4 * width; pixel_format = SDL_PIXELFORMAT_RGBA32; } @@ -62,20 +62,14 @@ bool Texture::loadFromFile(const std::string &file_path) // Crea la superficie de la imagen desde los datos cargados SDL_Surface *loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, (void *)data, pitch); - if (loaded_surface == nullptr) - { + if (loaded_surface == nullptr) { std::cout << "No se pudo cargar la imagen " << file_path << std::endl; - } - else - { + } else { // Crea la textura desde los píxeles de la superficie new_texture = SDL_CreateTextureFromSurface(renderer_, loaded_surface); - if (new_texture == nullptr) - { + if (new_texture == nullptr) { std::cout << "No se pudo crear la textura desde " << file_path << "! Error de SDL: " << SDL_GetError() << std::endl; - } - else - { + } else { // Obtiene las dimensiones de la imagen width_ = loaded_surface->w; height_ = loaded_surface->h; @@ -95,10 +89,8 @@ bool Texture::loadFromFile(const std::string &file_path) } // Libera la textura si existe -void Texture::free() -{ - if (texture_ != nullptr) - { +void Texture::free() { + if (texture_ != nullptr) { SDL_DestroyTexture(texture_); texture_ = nullptr; width_ = 0; @@ -107,25 +99,21 @@ void Texture::free() } // Renderiza la textura en pantalla -void Texture::render(SDL_FRect *src, SDL_FRect *dst) -{ +void Texture::render(SDL_FRect *src, SDL_FRect *dst) { SDL_RenderTexture(renderer_, texture_, src, dst); } // Obtiene el ancho de la imagen -int Texture::getWidth() -{ +int Texture::getWidth() { return width_; } // Obtiene la altura de la imagen -int Texture::getHeight() -{ +int Texture::getHeight() { return height_; } // Modula el color de la textura -void Texture::setColor(int r, int g, int b) -{ +void Texture::setColor(int r, int g, int b) { SDL_SetTextureColorMod(texture_, r, g, b); } diff --git a/source/external/texture.h b/source/external/texture.h index 1209fdc..cb97d9f 100644 --- a/source/external/texture.h +++ b/source/external/texture.h @@ -2,42 +2,42 @@ #include // Para SDL_FRect #include // Para SDL_Renderer, SDL_Texture -#include // Para std::string -class Texture -{ -private: - SDL_Renderer *renderer_; - SDL_Texture *texture_; +#include // Para std::string - // Dimensiones de la imagen - int width_; - int height_; +class Texture { + private: + SDL_Renderer *renderer_; + SDL_Texture *texture_; -public: - // Inicializa las variables - explicit Texture(SDL_Renderer *renderer); - Texture(SDL_Renderer *renderer, const std::string &file_path); + // Dimensiones de la imagen + int width_; + int height_; - // Libera la memoria - ~Texture(); + public: + // Inicializa las variables + explicit Texture(SDL_Renderer *renderer); + Texture(SDL_Renderer *renderer, const std::string &file_path); - // Carga una imagen desde la ruta especificada - bool loadFromFile(const std::string &path); + // Libera la memoria + ~Texture(); - // Libera la textura - void free(); + // Carga una imagen desde la ruta especificada + bool loadFromFile(const std::string &path); - // Renderiza la textura en el punto especificado - void render(SDL_FRect *src = nullptr, SDL_FRect *dst = nullptr); + // Libera la textura + void free(); - // Obtiene las dimensiones de la imagen - int getWidth(); - int getHeight(); + // Renderiza la textura en el punto especificado + void render(SDL_FRect *src = nullptr, SDL_FRect *dst = nullptr); - // Modula el color de la textura - void setColor(int r, int g, int b); + // Obtiene las dimensiones de la imagen + int getWidth(); + int getHeight(); - // Getter para batch rendering - SDL_Texture* getSDLTexture() const { return texture_; } + // Modula el color de la textura + void setColor(int r, int g, int b); + + // Getter para batch rendering + SDL_Texture *getSDLTexture() const { return texture_; } }; diff --git a/source/main.cpp b/source/main.cpp index 9d66111..87a3197 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -6,17 +6,19 @@ #include // for Uint64 #include // for SDL_GetTicks #include // for SDL_CreateWindow, SDL_DestroyWindow -#include // for array -#include // for rand, srand -#include // for time -#include // for basic_ostream, char_traits, operator<< -#include // for unique_ptr, shared_ptr, make_shared -#include // for operator+, string, to_string -#include // for vector + +#include // for array +#include // for rand, srand +#include // for time +#include // for basic_ostream, char_traits, operator<< +#include // for unique_ptr, shared_ptr, make_shared +#include // for operator+, string, to_string +#include // for vector + #include "ball.h" // for Ball -#include "external/dbgtxt.h" // for dbg_init, dbg_print #include "defines.h" // for SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_SIZE -#include "external/texture.h" // for Texture +#include "external/dbgtxt.h" // for dbg_init, dbg_print +#include "external/texture.h" // for Texture // Variables globales SDL_Window *window = nullptr; @@ -27,28 +29,28 @@ std::array test = {1, 10, 100, 500, 1000, 10000, 50000, 100000}; bool should_exit = false; // Controla si la aplicación debe cerrarse // ticks eliminado - reemplazado por delta time system -int scenario = 0; // Escenario actual basado en el número de bolas -std::string text; // Texto a mostrar en pantalla -int text_pos = 0; // Posición del texto en la pantalla -bool show_text = true; // Determina si el texto se debe mostrar -Uint64 text_init_time = 0; // Temporizador para mostrar el texto +int scenario = 0; // Escenario actual basado en el número de bolas +std::string text; // Texto a mostrar en pantalla +int text_pos = 0; // Posición del texto en la pantalla +bool show_text = true; // Determina si el texto se debe mostrar +Uint64 text_init_time = 0; // Temporizador para mostrar el texto // Variables para contador de FPS -Uint64 fps_last_time = 0; // Último tiempo para cálculo de FPS -int fps_frame_count = 0; // Contador de frames -int fps_current = 0; // FPS actuales calculados -std::string fps_text = "FPS: 0"; // Texto del contador de FPS +Uint64 fps_last_time = 0; // Último tiempo para cálculo de FPS +int fps_frame_count = 0; // Contador de frames +int fps_current = 0; // FPS actuales calculados +std::string fps_text = "FPS: 0"; // Texto del contador de FPS // Variables para V-Sync -bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto) -std::string vsync_text = "VSYNC ON"; // Texto del estado V-Sync +bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto) +std::string vsync_text = "VSYNC ON"; // Texto del estado V-Sync // Variables para Delta Time -Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos -float delta_time = 0.0f; // Tiempo transcurrido desde el último frame en segundos +Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos +float delta_time = 0.0f; // Tiempo transcurrido desde el último frame en segundos // Variables para Debug Display -bool show_debug = false; // Debug display desactivado por defecto +bool show_debug = false; // Debug display desactivado por defecto // Sistema de temas de colores enum class ColorTheme { @@ -62,57 +64,51 @@ ColorTheme current_theme = ColorTheme::SUNSET; std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"}; struct ThemeColors { - // Colores de fondo (superior -> inferior) - float bg_top_r, bg_top_g, bg_top_b; - float bg_bottom_r, bg_bottom_g, bg_bottom_b; + // Colores de fondo (superior -> inferior) + float bg_top_r, bg_top_g, bg_top_b; + float bg_bottom_r, bg_bottom_g, bg_bottom_b; - // Paletas de colores para bolas (RGB 0-255) - int ball_colors[8][3]; // 8 colores por tema + // Paletas de colores para bolas (RGB 0-255) + int ball_colors[8][3]; // 8 colores por tema }; ThemeColors themes[4] = { // SUNSET: Naranjas, rojos, amarillos, rosas - { - 180.0f/255.0f, 140.0f/255.0f, 100.0f/255.0f, // Fondo superior (naranja suave) - 40.0f/255.0f, 20.0f/255.0f, 60.0f/255.0f, // Fondo inferior (púrpura oscuro) - {{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, // Bolas sunset - {255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}} - }, + {180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior (naranja suave) + 40.0f / 255.0f, + 20.0f / 255.0f, + 60.0f / 255.0f, // Fondo inferior (púrpura oscuro) + {{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, {255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}}}, // OCEAN: Azules, cianes, verdes agua, blancos - { - 100.0f/255.0f, 150.0f/255.0f, 200.0f/255.0f, // Fondo superior (azul cielo) - 20.0f/255.0f, 40.0f/255.0f, 80.0f/255.0f, // Fondo inferior (azul marino) - {{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, // Bolas ocean - {70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}} - }, + {100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior (azul cielo) + 20.0f / 255.0f, + 40.0f / 255.0f, + 80.0f / 255.0f, // Fondo inferior (azul marino) + {{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, {70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}}}, // NEON: Cian, magenta, verde lima, amarillo vibrante - { - 20.0f/255.0f, 20.0f/255.0f, 40.0f/255.0f, // Fondo superior (negro azulado) - 0.0f/255.0f, 0.0f/255.0f, 0.0f/255.0f, // Fondo inferior (negro) - {{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, // Bolas neon - {255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}} - }, + {20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior (negro azulado) + 0.0f / 255.0f, + 0.0f / 255.0f, + 0.0f / 255.0f, // Fondo inferior (negro) + {{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, {255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}}}, // FOREST: Verdes, marrones, amarillos otoño - { - 144.0f/255.0f, 238.0f/255.0f, 144.0f/255.0f, // Fondo superior (verde claro) - 101.0f/255.0f, 67.0f/255.0f, 33.0f/255.0f, // Fondo inferior (marrón tierra) - {{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, // Bolas forest - {210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}} - } -}; + {144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior (verde claro) + 101.0f / 255.0f, + 67.0f / 255.0f, + 33.0f / 255.0f, // Fondo inferior (marrón tierra) + {{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, {210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}}}}; // Variables para Batch Rendering std::vector batch_vertices; std::vector batch_indices; // Función para renderizar fondo degradado -void renderGradientBackground() -{ +void renderGradientBackground() { // Crear quad de pantalla completa con degradado SDL_Vertex bg_vertices[4]; // Obtener colores del tema actual - ThemeColors& theme = themes[static_cast(current_theme)]; + ThemeColors &theme = themes[static_cast(current_theme)]; float top_r = theme.bg_top_r; float top_g = theme.bg_top_g; @@ -150,8 +146,7 @@ void renderGradientBackground() } // Función para añadir un sprite al batch -void addSpriteToBatch(float x, float y, float w, float h, Uint8 r, Uint8 g, Uint8 b) -{ +void addSpriteToBatch(float x, float y, float w, float h, Uint8 r, Uint8 g, Uint8 b) { int vertex_index = static_cast(batch_vertices.size()); // Crear 4 vértices para el quad (2 triángulos) @@ -200,402 +195,359 @@ void addSpriteToBatch(float x, float y, float w, float h, Uint8 r, Uint8 g, Uint } // Establece el texto en pantalla mostrando el número de bolas actuales -void setText() -{ - const std::string TEXT_NUMBER = test[scenario] == 1 ? " PELOTA" : " PELOTAS"; - text = std::to_string(test[scenario]) + TEXT_NUMBER; - const int TEXT_SIZE = static_cast(text.size() * 8); - text_pos = SCREEN_WIDTH / 2 - TEXT_SIZE / 2; - text_init_time = SDL_GetTicks(); - show_text = true; +void setText() { + const std::string TEXT_NUMBER = test[scenario] == 1 ? " PELOTA" : " PELOTAS"; + text = std::to_string(test[scenario]) + TEXT_NUMBER; + const int TEXT_SIZE = static_cast(text.size() * 8); + text_pos = SCREEN_WIDTH / 2 - TEXT_SIZE / 2; + text_init_time = SDL_GetTicks(); + show_text = true; } // Inicializa las bolas según el escenario seleccionado -void initBalls(int value) -{ - balls.clear(); - for (int i = 0; i < test.at(value); ++i) - { - const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -) - const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X - const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X - const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y - // Seleccionar color de la paleta del tema actual - ThemeColors& theme = themes[static_cast(current_theme)]; - int color_index = rand() % 8; // 8 colores por tema - const Color COLOR = {theme.ball_colors[color_index][0], - theme.ball_colors[color_index][1], - theme.ball_colors[color_index][2]}; - balls.emplace_back(std::make_unique(X, VX, VY, COLOR, texture)); - } - setText(); // Actualiza el texto +void initBalls(int value) { + balls.clear(); + for (int i = 0; i < test.at(value); ++i) { + const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -) + const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X + const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X + const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y + // Seleccionar color de la paleta del tema actual + ThemeColors &theme = themes[static_cast(current_theme)]; + int color_index = rand() % 8; // 8 colores por tema + const Color COLOR = {theme.ball_colors[color_index][0], + theme.ball_colors[color_index][1], + theme.ball_colors[color_index][2]}; + balls.emplace_back(std::make_unique(X, VX, VY, COLOR, texture)); + } + setText(); // Actualiza el texto } // Aumenta la velocidad vertical de las bolas "hacia arriba" -void pushUpBalls() -{ - for (auto &ball : balls) - { - const int SIGNO = ((rand() % 2) * 2) - 1; - const float VX = (((rand() % 20) + 10) * 0.1f) * SIGNO; - const float VY = ((rand() % 40) * 0.1f) + 5; - ball->modVel(VX, -VY); // Modifica la velocidad de la bola - } +void pushUpBalls() { + for (auto &ball : balls) { + const int SIGNO = ((rand() % 2) * 2) - 1; + const float VX = (((rand() % 20) + 10) * 0.1f) * SIGNO; + const float VY = ((rand() % 40) * 0.1f) + 5; + ball->modVel(VX, -VY); // Modifica la velocidad de la bola + } } // Cambia la gravedad de todas las bolas -void switchBallsGravity() -{ - for (auto &ball : balls) - { - ball->switchGravity(); - } +void switchBallsGravity() { + for (auto &ball : balls) { + ball->switchGravity(); + } } // Alterna el estado del V-Sync -void toggleVSync() -{ - vsync_enabled = !vsync_enabled; - vsync_text = vsync_enabled ? "VSYNC ON" : "VSYNC OFF"; +void toggleVSync() { + vsync_enabled = !vsync_enabled; + vsync_text = vsync_enabled ? "VSYNC ON" : "VSYNC OFF"; - // Aplicar el cambio de V-Sync al renderizador - SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); + // Aplicar el cambio de V-Sync al renderizador + SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); } // Calcula el delta time entre frames -void calculateDeltaTime() -{ - Uint64 current_time = SDL_GetTicks(); +void calculateDeltaTime() { + Uint64 current_time = SDL_GetTicks(); - // En el primer frame, inicializar el tiempo anterior - if (last_frame_time == 0) - { - last_frame_time = current_time; - delta_time = 1.0f / 60.0f; // Asumir 60 FPS para el primer frame - return; - } + // En el primer frame, inicializar el tiempo anterior + if (last_frame_time == 0) { + last_frame_time = current_time; + delta_time = 1.0f / 60.0f; // Asumir 60 FPS para el primer frame + return; + } - // Calcular delta time en segundos - delta_time = (current_time - last_frame_time) / 1000.0f; - last_frame_time = current_time; + // Calcular delta time en segundos + delta_time = (current_time - last_frame_time) / 1000.0f; + last_frame_time = current_time; - // Limitar delta time para evitar saltos grandes (pausa larga, depuración, etc.) - if (delta_time > 0.05f) // Máximo 50ms (20 FPS mínimo) - { - delta_time = 1.0f / 60.0f; // Usar 60 FPS como fallback - } + // Limitar delta time para evitar saltos grandes (pausa larga, depuración, etc.) + if (delta_time > 0.05f) // Máximo 50ms (20 FPS mínimo) + { + delta_time = 1.0f / 60.0f; // Usar 60 FPS como fallback + } } // Inicializa SDL y configura los componentes principales -bool init() -{ - bool success = true; +bool init() { + bool success = true; - // Inicializa SDL - if (!SDL_Init(SDL_INIT_VIDEO)) - { - std::cout << "¡SDL no se pudo inicializar! Error de SDL: " << SDL_GetError() << std::endl; - success = false; - } - else - { - // Crear ventana principal - window = SDL_CreateWindow(WINDOW_CAPTION, SCREEN_WIDTH * WINDOW_SIZE, SCREEN_HEIGHT * WINDOW_SIZE, SDL_WINDOW_OPENGL); - if (window == nullptr) - { - std::cout << "¡No se pudo crear la ventana! Error de SDL: " << SDL_GetError() << std::endl; - success = false; - } - else - { - // Crear renderizador - renderer = SDL_CreateRenderer(window, nullptr); - if (renderer == nullptr) - { - std::cout << "¡No se pudo crear el renderizador! Error de SDL: " << SDL_GetError() << std::endl; - success = false; - } - else - { - // Establecer color inicial del renderizador - SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + // Inicializa SDL + if (!SDL_Init(SDL_INIT_VIDEO)) { + std::cout << "¡SDL no se pudo inicializar! Error de SDL: " << SDL_GetError() << std::endl; + success = false; + } else { + // Crear ventana principal + window = SDL_CreateWindow(WINDOW_CAPTION, SCREEN_WIDTH * WINDOW_SIZE, SCREEN_HEIGHT * WINDOW_SIZE, SDL_WINDOW_OPENGL); + if (window == nullptr) { + std::cout << "¡No se pudo crear la ventana! Error de SDL: " << SDL_GetError() << std::endl; + success = false; + } else { + // Crear renderizador + renderer = SDL_CreateRenderer(window, nullptr); + if (renderer == nullptr) { + std::cout << "¡No se pudo crear el renderizador! Error de SDL: " << SDL_GetError() << std::endl; + success = false; + } else { + // Establecer color inicial del renderizador + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); - // Establecer tamaño lógico para el renderizado - SDL_SetRenderLogicalPresentation(renderer, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); + // Establecer tamaño lógico para el renderizado + SDL_SetRenderLogicalPresentation(renderer, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); - // Configurar V-Sync inicial - SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); - } - } - } + // Configurar V-Sync inicial + SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); + } + } + } - // Inicializar otros componentes - texture = std::make_shared(renderer, "resources/ball.png"); - // ticks eliminado - delta time system se inicializa automáticamente - srand(static_cast(time(nullptr))); - dbg_init(renderer); - initBalls(scenario); + // Inicializar otros componentes + texture = std::make_shared(renderer, "resources/ball.png"); + // ticks eliminado - delta time system se inicializa automáticamente + srand(static_cast(time(nullptr))); + dbg_init(renderer); + initBalls(scenario); - return success; + return success; } // Limpia todos los recursos y cierra SDL -void close() -{ - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); +void close() { + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); } // Verifica los eventos en la cola -void checkEvents() -{ - SDL_Event event; - while (SDL_PollEvent(&event) != 0) - { - // Evento de salida - if (event.type == SDL_EVENT_QUIT) - { - should_exit = true; - break; - } +void checkEvents() { + SDL_Event event; + while (SDL_PollEvent(&event) != 0) { + // Evento de salida + if (event.type == SDL_EVENT_QUIT) { + should_exit = true; + break; + } - // Procesar eventos de teclado - if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) - { - switch (event.key.key) - { - case SDLK_ESCAPE: - should_exit = true; - break; + // Procesar eventos de teclado + if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) { + switch (event.key.key) { + case SDLK_ESCAPE: + should_exit = true; + break; - case SDLK_SPACE: - pushUpBalls(); - break; + case SDLK_SPACE: + pushUpBalls(); + break; - case SDLK_G: - switchBallsGravity(); - break; + case SDLK_G: + switchBallsGravity(); + break; - case SDLK_V: - toggleVSync(); - break; + case SDLK_V: + toggleVSync(); + break; - case SDLK_H: - show_debug = !show_debug; - break; + case SDLK_H: + show_debug = !show_debug; + break; - case SDLK_T: - // Ciclar al siguiente tema - current_theme = static_cast((static_cast(current_theme) + 1) % 4); - initBalls(scenario); // Regenerar bolas con nueva paleta - break; + case SDLK_T: + // Ciclar al siguiente tema + current_theme = static_cast((static_cast(current_theme) + 1) % 4); + initBalls(scenario); // Regenerar bolas con nueva paleta + break; - case SDLK_F1: - current_theme = ColorTheme::SUNSET; - initBalls(scenario); - break; + case SDLK_F1: + current_theme = ColorTheme::SUNSET; + initBalls(scenario); + break; - case SDLK_F2: - current_theme = ColorTheme::OCEAN; - initBalls(scenario); - break; + case SDLK_F2: + current_theme = ColorTheme::OCEAN; + initBalls(scenario); + break; - case SDLK_F3: - current_theme = ColorTheme::NEON; - initBalls(scenario); - break; + case SDLK_F3: + current_theme = ColorTheme::NEON; + initBalls(scenario); + break; - case SDLK_F4: - current_theme = ColorTheme::FOREST; - initBalls(scenario); - break; + case SDLK_F4: + current_theme = ColorTheme::FOREST; + initBalls(scenario); + break; - case SDLK_1: - scenario = 0; - initBalls(scenario); - break; + case SDLK_1: + scenario = 0; + initBalls(scenario); + break; - case SDLK_2: - scenario = 1; - initBalls(scenario); - break; + case SDLK_2: + scenario = 1; + initBalls(scenario); + break; - case SDLK_3: - scenario = 2; - initBalls(scenario); - break; + case SDLK_3: + scenario = 2; + initBalls(scenario); + break; - case SDLK_4: - scenario = 3; - initBalls(scenario); - break; + case SDLK_4: + scenario = 3; + initBalls(scenario); + break; - case SDLK_5: - scenario = 4; - initBalls(scenario); - break; + case SDLK_5: + scenario = 4; + initBalls(scenario); + break; - case SDLK_6: - scenario = 5; - initBalls(scenario); - break; + case SDLK_6: + scenario = 5; + initBalls(scenario); + break; - case SDLK_7: - scenario = 6; - initBalls(scenario); - break; + case SDLK_7: + scenario = 6; + initBalls(scenario); + break; - case SDLK_8: - scenario = 7; - initBalls(scenario); - break; - } - } - } + case SDLK_8: + scenario = 7; + initBalls(scenario); + break; + } + } + } } // Actualiza la lógica del juego -void update() -{ - // Calcular FPS - fps_frame_count++; - Uint64 current_time = SDL_GetTicks(); - if (current_time - fps_last_time >= 1000) // Actualizar cada segundo - { - fps_current = fps_frame_count; - fps_frame_count = 0; - fps_last_time = current_time; - fps_text = "FPS: " + std::to_string(fps_current); - } +void update() { + // Calcular FPS + fps_frame_count++; + Uint64 current_time = SDL_GetTicks(); + if (current_time - fps_last_time >= 1000) // Actualizar cada segundo + { + fps_current = fps_frame_count; + fps_frame_count = 0; + fps_last_time = current_time; + fps_text = "FPS: " + std::to_string(fps_current); + } - // ¡DELTA TIME! Actualizar física siempre, usando tiempo transcurrido - for (auto &ball : balls) - { - ball->update(delta_time); // Pasar delta time a cada pelota - } + // ¡DELTA TIME! Actualizar física siempre, usando tiempo transcurrido + for (auto &ball : balls) { + ball->update(delta_time); // Pasar delta time a cada pelota + } - // Actualizar texto (sin cambios en la lógica) - if (show_text) - { - show_text = !(SDL_GetTicks() - text_init_time > TEXT_DURATION); - } + // Actualizar texto (sin cambios en la lógica) + if (show_text) { + show_text = !(SDL_GetTicks() - text_init_time > TEXT_DURATION); + } } // Renderiza el contenido en la pantalla -void render() -{ - // Renderizar fondo degradado en lugar de color sólido - renderGradientBackground(); +void render() { + // Renderizar fondo degradado en lugar de color sólido + renderGradientBackground(); - // Limpiar batches del frame anterior - batch_vertices.clear(); - batch_indices.clear(); + // Limpiar batches del frame anterior + batch_vertices.clear(); + batch_indices.clear(); - // Recopilar datos de todas las bolas para batch rendering - for (auto &ball : balls) - { - // En lugar de ball->render(), obtener datos para batch - SDL_FRect pos = ball->getPosition(); - Color color = ball->getColor(); - addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b); - } + // Recopilar datos de todas las bolas para batch rendering + for (auto &ball : balls) { + // En lugar de ball->render(), obtener datos para batch + SDL_FRect pos = ball->getPosition(); + Color color = ball->getColor(); + addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b); + } - // Renderizar todas las bolas en una sola llamada - if (!batch_vertices.empty()) - { - SDL_RenderGeometry(renderer, texture->getSDLTexture(), - batch_vertices.data(), static_cast(batch_vertices.size()), - batch_indices.data(), static_cast(batch_indices.size())); - } + // Renderizar todas las bolas en una sola llamada + if (!batch_vertices.empty()) { + SDL_RenderGeometry(renderer, texture->getSDLTexture(), batch_vertices.data(), static_cast(batch_vertices.size()), batch_indices.data(), static_cast(batch_indices.size())); + } - if (show_text) - { - dbg_print(text_pos, 8, text.c_str(), 255, 255, 255); + if (show_text) { + dbg_print(text_pos, 8, text.c_str(), 255, 255, 255); - // Mostrar nombre del tema en castellano debajo del número de pelotas - std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE"}; - std::string theme_name = theme_names_es[static_cast(current_theme)]; - int theme_text_width = static_cast(theme_name.length() * 8); // 8 píxeles por carácter - int theme_x = (SCREEN_WIDTH - theme_text_width) / 2; // Centrar horizontalmente + // Mostrar nombre del tema en castellano debajo del número de pelotas + std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE"}; + std::string theme_name = theme_names_es[static_cast(current_theme)]; + int theme_text_width = static_cast(theme_name.length() * 8); // 8 píxeles por carácter + int theme_x = (SCREEN_WIDTH - theme_text_width) / 2; // Centrar horizontalmente - // Colores acordes a cada tema - int theme_colors[][3] = { - {255, 140, 60}, // ATARDECER: Naranja cálido - {80, 200, 255}, // OCEANO: Azul océano - {255, 60, 255}, // NEON: Magenta brillante - {100, 255, 100} // BOSQUE: Verde natural - }; - int theme_idx = static_cast(current_theme); - dbg_print(theme_x, 24, theme_name.c_str(), - theme_colors[theme_idx][0], - theme_colors[theme_idx][1], - theme_colors[theme_idx][2]); - } + // Colores acordes a cada tema + int theme_colors[][3] = { + {255, 140, 60}, // ATARDECER: Naranja cálido + {80, 200, 255}, // OCEANO: Azul océano + {255, 60, 255}, // NEON: Magenta brillante + {100, 255, 100} // BOSQUE: Verde natural + }; + int theme_idx = static_cast(current_theme); + dbg_print(theme_x, 24, theme_name.c_str(), theme_colors[theme_idx][0], theme_colors[theme_idx][1], theme_colors[theme_idx][2]); + } - // Debug display (solo si está activado con tecla H) - if (show_debug) - { - // Mostrar contador de FPS en esquina superior derecha - int fps_text_width = static_cast(fps_text.length() * 8); // 8 píxeles por carácter - int fps_x = SCREEN_WIDTH - fps_text_width - 8; // 8 píxeles de margen - dbg_print(fps_x, 8, fps_text.c_str(), 255, 255, 0); // Amarillo para distinguir + // Debug display (solo si está activado con tecla H) + if (show_debug) { + // Mostrar contador de FPS en esquina superior derecha + int fps_text_width = static_cast(fps_text.length() * 8); // 8 píxeles por carácter + int fps_x = SCREEN_WIDTH - fps_text_width - 8; // 8 píxeles de margen + dbg_print(fps_x, 8, fps_text.c_str(), 255, 255, 0); // Amarillo para distinguir - // Mostrar estado V-Sync en esquina superior izquierda - dbg_print(8, 8, vsync_text.c_str(), 0, 255, 255); // Cian para distinguir + // Mostrar estado V-Sync en esquina superior izquierda + dbg_print(8, 8, vsync_text.c_str(), 0, 255, 255); // Cian para distinguir - // Debug: Mostrar valores de la primera pelota (si existe) - if (!balls.empty()) - { - // Línea 1: Gravedad (solo números enteros) - int grav_int = static_cast(balls[0]->getGravityForce()); - std::string grav_text = "GRAV " + std::to_string(grav_int); - dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug + // Debug: Mostrar valores de la primera pelota (si existe) + if (!balls.empty()) { + // Línea 1: Gravedad (solo números enteros) + int grav_int = static_cast(balls[0]->getGravityForce()); + std::string grav_text = "GRAV " + std::to_string(grav_int); + dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug - // Línea 2: Velocidad Y (solo números enteros) - int vy_int = static_cast(balls[0]->getVelocityY()); - std::string vy_text = "VY " + std::to_string(vy_int); - dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug + // Línea 2: Velocidad Y (solo números enteros) + int vy_int = static_cast(balls[0]->getVelocityY()); + std::string vy_text = "VY " + std::to_string(vy_int); + dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug - // Línea 3: Estado suelo - std::string floor_text = balls[0]->isOnFloor() ? "FLOOR YES" : "FLOOR NO"; - dbg_print(8, 40, floor_text.c_str(), 255, 0, 255); // Magenta para debug - } + // Línea 3: Estado suelo + std::string floor_text = balls[0]->isOnFloor() ? "FLOOR YES" : "FLOOR NO"; + dbg_print(8, 40, floor_text.c_str(), 255, 0, 255); // Magenta para debug + } - // Debug: Mostrar tema actual - std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"}; - std::string theme_text = "THEME " + theme_names[static_cast(current_theme)]; - dbg_print(8, 48, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema - } + // Debug: Mostrar tema actual + std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"}; + std::string theme_text = "THEME " + theme_names[static_cast(current_theme)]; + dbg_print(8, 48, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema + } - SDL_RenderPresent(renderer); + SDL_RenderPresent(renderer); } // Función principal -int main(int argc, char *args[]) -{ - if (!init()) - { - std::cout << "Ocurrió un error durante la inicialización." << std::endl; - return 1; - } +int main(int argc, char *args[]) { + if (!init()) { + std::cout << "Ocurrió un error durante la inicialización." << std::endl; + return 1; + } - while (!should_exit) - { - // 1. Calcular delta time antes de actualizar la lógica - calculateDeltaTime(); + while (!should_exit) { + // 1. Calcular delta time antes de actualizar la lógica + calculateDeltaTime(); - // 2. Actualizar lógica del juego con delta time - update(); + // 2. Actualizar lógica del juego con delta time + update(); - // 3. Procesar eventos de entrada - checkEvents(); + // 3. Procesar eventos de entrada + checkEvents(); - // 4. Renderizar la escena - render(); - } + // 4. Renderizar la escena + render(); + } - close(); + close(); - return 0; + return 0; }