Aplicar formato automático con clang-format a todo el código fuente

- Reformatear archivos .cpp y .h según configuración Google personalizada
- Mejorar consistencia en indentación y espaciado
- Reorganizar includes y declaraciones de clases
- Mantener funcionalidad existente sin cambios

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-15 13:57:01 +02:00
parent 230046152c
commit 79c27dad6a
9 changed files with 494 additions and 585 deletions

View File

@@ -1,14 +1,16 @@
#include "ball.h" #include "ball.h"
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include <cmath> // for fabs
#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE #include <cmath> // for fabs
#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE
class Texture; class Texture;
// Constructor // Constructor
Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture) Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture)
: sprite_(std::make_unique<Sprite>(texture)), : sprite_(std::make_unique<Sprite>(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) // 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;
@@ -24,58 +26,48 @@ Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> te
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void Ball::update(float deltaTime) void Ball::update(float deltaTime) {
{ if (stopped_) {
if (stopped_)
{
return; return;
} }
// Aplica la gravedad a la velocidad (píxeles/segundo²) // Aplica la gravedad a la velocidad (píxeles/segundo²)
if (!on_floor_) if (!on_floor_) {
{
vy_ += gravity_force_ * deltaTime; vy_ += gravity_force_ * deltaTime;
} }
// Actualiza la posición en función de la velocidad (píxeles/segundo) // Actualiza la posición en función de la velocidad (píxeles/segundo)
pos_.x += vx_ * deltaTime; pos_.x += vx_ * deltaTime;
if (!on_floor_) if (!on_floor_) {
{
pos_.y += vy_ * deltaTime; pos_.y += vy_ * deltaTime;
} } else {
else
{
// Si está en el suelo, mantenerla ahí // Si está en el suelo, mantenerla ahí
pos_.y = SCREEN_HEIGHT - pos_.h; pos_.y = SCREEN_HEIGHT - pos_.h;
} }
// Comprueba las colisiones con el lateral izquierdo // Comprueba las colisiones con el lateral izquierdo
if (pos_.x < 0) if (pos_.x < 0) {
{
pos_.x = 0; pos_.x = 0;
vx_ = -vx_; vx_ = -vx_;
} }
// Comprueba las colisiones con el lateral derecho // 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; pos_.x = SCREEN_WIDTH - pos_.w;
vx_ = -vx_; vx_ = -vx_;
} }
// Comprueba las colisiones con la parte superior // Comprueba las colisiones con la parte superior
if (pos_.y < 0) if (pos_.y < 0) {
{
pos_.y = 0; pos_.y = 0;
vy_ = -vy_; vy_ = -vy_;
} }
// Comprueba las colisiones con la parte inferior // 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; pos_.y = SCREEN_HEIGHT - pos_.h;
vy_ = -vy_ * loss_; 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; vy_ = 0.0f;
on_floor_ = true; on_floor_ = true;
@@ -83,15 +75,14 @@ void Ball::update(float deltaTime)
} }
// Aplica rozamiento al rodar por el suelo // Aplica rozamiento al rodar por el suelo
if (on_floor_) if (on_floor_) {
{
// Convertir rozamiento de frame-based a time-based // Convertir rozamiento de frame-based a time-based
// 0.97f por frame equivale a pow(0.97f, 60 * deltaTime) // 0.97f por frame equivale a pow(0.97f, 60 * deltaTime)
float friction_factor = pow(0.97f, 60.0f * deltaTime); float friction_factor = pow(0.97f, 60.0f * deltaTime);
vx_ = vx_ * friction_factor; vx_ = vx_ * friction_factor;
// Umbral de parada ajustado para velocidades en píxeles/segundo // 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; vx_ = 0.0f;
stopped_ = true; stopped_ = true;
@@ -103,26 +94,22 @@ void Ball::update(float deltaTime)
} }
// Pinta la clase // Pinta la clase
void Ball::render() void Ball::render() {
{
sprite_->setColor(color_.r, color_.g, color_.b); sprite_->setColor(color_.r, color_.g, color_.b);
sprite_->render(); sprite_->render();
} }
// Modifica la velocidad (convierte de frame-based a time-based) // Modifica la velocidad (convierte de frame-based a time-based)
void Ball::modVel(float vx, float vy) void Ball::modVel(float vx, float vy) {
{ if (stopped_) {
if (stopped_) vx_ = vx_ + (vx * 60.0f); // Convertir a píxeles/segundo
{
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; on_floor_ = false;
stopped_ = false; stopped_ = false;
} }
// Cambia la gravedad (usa la versión convertida) // 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; gravity_force_ = gravity_force_ == 0.0f ? (GRAVITY_FORCE * 60.0f * 60.0f) : 0.0f;
} }

View File

@@ -1,48 +1,49 @@
#pragma once #pragma once
#include <SDL3/SDL_rect.h> // for SDL_FRect #include <SDL3/SDL_rect.h> // for SDL_FRect
#include <memory> // for shared_ptr, unique_ptr
#include "defines.h" // for Color #include <memory> // for shared_ptr, unique_ptr
#include "external/sprite.h" // for Sprite
#include "defines.h" // for Color
#include "external/sprite.h" // for Sprite
class Texture; class Texture;
class Ball class Ball {
{ private:
private: std::unique_ptr<Sprite> sprite_; // Sprite para pintar la clase
std::unique_ptr<Sprite> sprite_; // Sprite para pintar la clase SDL_FRect pos_; // Posición y tamaño de la pelota
SDL_FRect pos_; // Posición y tamaño de la pelota float vx_, vy_; // Velocidad
float vx_, vy_; // Velocidad float gravity_force_; // Gravedad
float gravity_force_; // Gravedad Color color_; // Color de la pelota
Color color_; // Color de la pelota bool on_floor_; // Indica si la pelota está ya en el suelo
bool on_floor_; // Indica si la pelota está ya en el suelo bool stopped_; // Indica si la pelota ha terminado de moverse;
bool stopped_; // Indica si la pelota ha terminado de moverse; float loss_; // Coeficiente de rebote. Pérdida de energía en cada rebote
float loss_; // Coeficiente de rebote. Pérdida de energía en cada rebote
public: public:
// Constructor // Constructor
Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture); Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture);
// Destructor // Destructor
~Ball() = default; ~Ball() = default;
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void update(float deltaTime); void update(float deltaTime);
// Pinta la clase // Pinta la clase
void render(); void render();
// Modifica la velocidad // Modifica la velocidad
void modVel(float vx, float vy); void modVel(float vx, float vy);
// Cambia la gravedad // Cambia la gravedad
void switchGravity(); void switchGravity();
// Getters para debug // Getters para debug
float getVelocityY() const { return vy_; } float getVelocityY() const { return vy_; }
float getGravityForce() const { return gravity_force_; } float getGravityForce() const { return gravity_force_; }
bool isOnFloor() const { return on_floor_; } bool isOnFloor() const { return on_floor_; }
// Getters para batch rendering // Getters para batch rendering
SDL_FRect getPosition() const { return pos_; } SDL_FRect getPosition() const { return pos_; }
Color getColor() const { return color_; } Color getColor() const { return color_; }
}; };

View File

@@ -11,7 +11,6 @@ constexpr float GRAVITY_FORCE = 0.2f;
// DEMO_SPEED eliminado - ya no se usa con delta time // DEMO_SPEED eliminado - ya no se usa con delta time
constexpr Uint64 TEXT_DURATION = 2000; constexpr Uint64 TEXT_DURATION = 2000;
struct Color struct Color {
{ int r, g, b;
int r, g, b;
}; };

View File

@@ -1,24 +1,20 @@
#pragma once #pragma once
namespace namespace {
{ SDL_Texture* dbg_tex = nullptr;
SDL_Texture *dbg_tex = nullptr; SDL_Renderer* dbg_ren = nullptr;
SDL_Renderer *dbg_ren = nullptr; } // namespace
}
void dbg_init(SDL_Renderer *renderer) void dbg_init(SDL_Renderer* renderer) {
{
dbg_ren = 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}; 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 // Cargar surface del bitmap font
SDL_Surface* font_surface = SDL_LoadBMP_IO(SDL_IOFromMem(font, 448), 1); 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 // 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); 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 // Obtener píxeles de ambas surfaces
Uint8* src_pixels = (Uint8*)font_surface->pixels; Uint8* src_pixels = (Uint8*)font_surface->pixels;
Uint32* dst_pixels = (Uint32*)rgba_surface->pixels; Uint32* dst_pixels = (Uint32*)rgba_surface->pixels;
@@ -27,23 +23,20 @@ void dbg_init(SDL_Renderer *renderer)
int height = font_surface->h; int height = font_surface->h;
// Procesar cada píxel // Procesar cada píxel
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++) {
{ for (int x = 0; x < width; x++) {
for (int x = 0; x < width; x++)
{
int byte_index = y * font_surface->pitch + (x / 8); int byte_index = y * font_surface->pitch + (x / 8);
int bit_index = 7 - (x % 8); int bit_index = 7 - (x % 8);
// Extraer bit del bitmap monocromo // Extraer bit del bitmap monocromo
bool is_white = (src_pixels[byte_index] >> bit_index) & 1; 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 dst_pixels[y * width + x] = 0x00000000; // Transparente
} } else // Texto negro original -> blanco opaco
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 // 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); SDL_SetTextureScaleMode(dbg_tex, SDL_SCALEMODE_NEAREST);
// Configurar blend mode para transparencia normal // Configurar blend mode para transparencia normal
SDL_SetTextureBlendMode(dbg_tex, SDL_BLENDMODE_BLEND); 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; int cc = 0;
SDL_SetTextureColorMod(dbg_tex, r, g, b); SDL_SetTextureColorMod(dbg_tex, r, g, b);
SDL_FRect src = {0, 0, 8, 8}; SDL_FRect src = {0, 0, 8, 8};
SDL_FRect dst = {static_cast<float>(x), static_cast<float>(y), 8, 8}; SDL_FRect dst = {static_cast<float>(x), static_cast<float>(y), 8, 8};
while (text[cc] != 0) while (text[cc] != 0) {
{ if (text[cc] != 32) {
if (text[cc] != 32) if (text[cc] >= 65) {
{
if (text[cc] >= 65)
{
src.x = ((text[cc] - 65) % 6) * 8; src.x = ((text[cc] - 65) % 6) * 8;
src.y = ((text[cc] - 65) / 6) * 8; src.y = ((text[cc] - 65) / 6) * 8;
} } else {
else
{
src.x = ((text[cc] - 22) % 6) * 8; src.x = ((text[cc] - 22) % 6) * 8;
src.y = ((text[cc] - 22) / 6) * 8; src.y = ((text[cc] - 22) / 6) * 8;
} }

View File

@@ -1,4 +1,5 @@
#include "sprite.h" #include "sprite.h"
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
@@ -8,33 +9,28 @@ Sprite::Sprite(std::shared_ptr<Texture> texture)
clip_{0.0f, 0.0f, 0.0f, 0.0f} {} clip_{0.0f, 0.0f, 0.0f, 0.0f} {}
// Establece la posición del sprite // Establece la posición del sprite
void Sprite::setPos(SDL_FPoint pos) void Sprite::setPos(SDL_FPoint pos) {
{
pos_.x = pos.x; pos_.x = pos.x;
pos_.y = pos.y; pos_.y = pos.y;
} }
// Pinta el sprite // Pinta el sprite
void Sprite::render() void Sprite::render() {
{
texture_->render(&clip_, &pos_); texture_->render(&clip_, &pos_);
} }
// Establece el rectangulo de la textura que se va a pintar // 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; clip_ = clip;
} }
// Establece el tamaño del sprite // Establece el tamaño del sprite
void Sprite::setSize(float w, float h) void Sprite::setSize(float w, float h) {
{
pos_.w = w; pos_.w = w;
pos_.h = h; pos_.h = h;
} }
// Modulación de color // 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); texture_->setColor(r, g, b);
} }

View File

@@ -1,35 +1,35 @@
#pragma once #pragma once
#include <SDL3/SDL_rect.h> // for SDL_FRect, SDL_FPoint #include <SDL3/SDL_rect.h> // for SDL_FRect, SDL_FPoint
#include <memory> // for shared_ptr
#include <memory> // for shared_ptr
class Texture; class Texture;
class Sprite class Sprite {
{ private:
private: std::shared_ptr<Texture> texture_; // Textura con los gráficos del sprite
std::shared_ptr<Texture> texture_; // Textura con los gráficos del sprite SDL_FRect pos_; // Posición y tamaño del sprite
SDL_FRect pos_; // Posición y tamaño del sprite SDL_FRect clip_; // Parte de la textura que se va a dibujar
SDL_FRect clip_; // Parte de la textura que se va a dibujar
public: public:
// Constructor // Constructor
explicit Sprite(std::shared_ptr<Texture> texture); explicit Sprite(std::shared_ptr<Texture> texture);
// Destructor // Destructor
~Sprite() = default; ~Sprite() = default;
// Establece la posición del sprite // Establece la posición del sprite
void setPos(SDL_FPoint pos); void setPos(SDL_FPoint pos);
// Pinta el sprite // Pinta el sprite
void render(); void render();
// Establece el rectangulo de la textura que se va a pintar // Establece el rectangulo de la textura que se va a pintar
void setClip(SDL_FRect clip); void setClip(SDL_FRect clip);
// Establece el tamaño del sprite // Establece el tamaño del sprite
void setSize(float w, float h); void setSize(float w, float h);
// Modulación de color // Modulación de color
void setColor(int r, int g, int b); void setColor(int r, int g, int b);
}; };

View File

@@ -1,55 +1,55 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "texture.h" #include "texture.h"
#include <SDL3/SDL_error.h> // Para SDL_GetError #include <SDL3/SDL_error.h> // Para SDL_GetError
#include <SDL3/SDL_log.h> // Para SDL_Log #include <SDL3/SDL_log.h> // Para SDL_Log
#include <SDL3/SDL_pixels.h> // Para SDL_PixelFormat #include <SDL3/SDL_pixels.h> // Para SDL_PixelFormat
#include <SDL3/SDL_surface.h> // Para SDL_CreateSurfaceFrom, SDL_DestroySurface #include <SDL3/SDL_surface.h> // Para SDL_CreateSurfaceFrom, SDL_DestroySurface
#include <stdio.h> // Para NULL #include <stdio.h> // Para NULL
#include <stdlib.h> // Para exit #include <stdlib.h> // Para exit
#include <iostream> // Para basic_ostream, char_traits, operator<<
#include <string> // Para operator<<, string #include <iostream> // Para basic_ostream, char_traits, operator<<
#include "stb_image.h" // Para stbi_failure_reason, stbi_image_free #include <string> // Para operator<<, string
#include "stb_image.h" // Para stbi_failure_reason, stbi_image_free
Texture::Texture(SDL_Renderer *renderer) 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) 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); loadFromFile(file_path);
} }
Texture::~Texture() Texture::~Texture() {
{
free(); free();
} }
// Carga la imagen desde una ruta especificada // 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); const std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha; int req_format = STBI_rgb_alpha;
int width, height, orig_format; int width, height, orig_format;
unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_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()); SDL_Log("Error al cargar la imagen: %s", stbi_failure_reason());
exit(1); exit(1);
} } else {
else
{
std::cout << "Imagen cargada: " << filename.c_str() << std::endl; std::cout << "Imagen cargada: " << filename.c_str() << std::endl;
} }
int pitch; int pitch;
SDL_PixelFormat pixel_format; SDL_PixelFormat pixel_format;
if (req_format == STBI_rgb) if (req_format == STBI_rgb) {
{ pitch = 3 * width; // 3 bytes por pixel * pixels por línea
pitch = 3 * width; // 3 bytes por pixel * pixels por línea
pixel_format = SDL_PIXELFORMAT_RGB24; pixel_format = SDL_PIXELFORMAT_RGB24;
} } else { // STBI_rgb_alpha (RGBA)
else
{ // STBI_rgb_alpha (RGBA)
pitch = 4 * width; pitch = 4 * width;
pixel_format = SDL_PIXELFORMAT_RGBA32; 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 // Crea la superficie de la imagen desde los datos cargados
SDL_Surface *loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, (void *)data, pitch); 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; std::cout << "No se pudo cargar la imagen " << file_path << std::endl;
} } else {
else
{
// Crea la textura desde los píxeles de la superficie // Crea la textura desde los píxeles de la superficie
new_texture = SDL_CreateTextureFromSurface(renderer_, loaded_surface); 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; 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 // Obtiene las dimensiones de la imagen
width_ = loaded_surface->w; width_ = loaded_surface->w;
height_ = loaded_surface->h; height_ = loaded_surface->h;
@@ -95,10 +89,8 @@ bool Texture::loadFromFile(const std::string &file_path)
} }
// Libera la textura si existe // Libera la textura si existe
void Texture::free() void Texture::free() {
{ if (texture_ != nullptr) {
if (texture_ != nullptr)
{
SDL_DestroyTexture(texture_); SDL_DestroyTexture(texture_);
texture_ = nullptr; texture_ = nullptr;
width_ = 0; width_ = 0;
@@ -107,25 +99,21 @@ void Texture::free()
} }
// Renderiza la textura en pantalla // 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); SDL_RenderTexture(renderer_, texture_, src, dst);
} }
// Obtiene el ancho de la imagen // Obtiene el ancho de la imagen
int Texture::getWidth() int Texture::getWidth() {
{
return width_; return width_;
} }
// Obtiene la altura de la imagen // Obtiene la altura de la imagen
int Texture::getHeight() int Texture::getHeight() {
{
return height_; return height_;
} }
// Modula el color de la textura // 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); SDL_SetTextureColorMod(texture_, r, g, b);
} }

View File

@@ -2,42 +2,42 @@
#include <SDL3/SDL_rect.h> // Para SDL_FRect #include <SDL3/SDL_rect.h> // Para SDL_FRect
#include <SDL3/SDL_render.h> // Para SDL_Renderer, SDL_Texture #include <SDL3/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <string> // Para std::string
class Texture #include <string> // Para std::string
{
private:
SDL_Renderer *renderer_;
SDL_Texture *texture_;
// Dimensiones de la imagen class Texture {
int width_; private:
int height_; SDL_Renderer *renderer_;
SDL_Texture *texture_;
public: // Dimensiones de la imagen
// Inicializa las variables int width_;
explicit Texture(SDL_Renderer *renderer); int height_;
Texture(SDL_Renderer *renderer, const std::string &file_path);
// Libera la memoria public:
~Texture(); // Inicializa las variables
explicit Texture(SDL_Renderer *renderer);
Texture(SDL_Renderer *renderer, const std::string &file_path);
// Carga una imagen desde la ruta especificada // Libera la memoria
bool loadFromFile(const std::string &path); ~Texture();
// Libera la textura // Carga una imagen desde la ruta especificada
void free(); bool loadFromFile(const std::string &path);
// Renderiza la textura en el punto especificado // Libera la textura
void render(SDL_FRect *src = nullptr, SDL_FRect *dst = nullptr); void free();
// Obtiene las dimensiones de la imagen // Renderiza la textura en el punto especificado
int getWidth(); void render(SDL_FRect *src = nullptr, SDL_FRect *dst = nullptr);
int getHeight();
// Modula el color de la textura // Obtiene las dimensiones de la imagen
void setColor(int r, int g, int b); int getWidth();
int getHeight();
// Getter para batch rendering // Modula el color de la textura
SDL_Texture* getSDLTexture() const { return texture_; } void setColor(int r, int g, int b);
// Getter para batch rendering
SDL_Texture *getSDLTexture() const { return texture_; }
}; };

View File

@@ -6,17 +6,19 @@
#include <SDL3/SDL_stdinc.h> // for Uint64 #include <SDL3/SDL_stdinc.h> // for Uint64
#include <SDL3/SDL_timer.h> // for SDL_GetTicks #include <SDL3/SDL_timer.h> // for SDL_GetTicks
#include <SDL3/SDL_video.h> // for SDL_CreateWindow, SDL_DestroyWindow #include <SDL3/SDL_video.h> // for SDL_CreateWindow, SDL_DestroyWindow
#include <array> // for array
#include <cstdlib> // for rand, srand #include <array> // for array
#include <ctime> // for time #include <cstdlib> // for rand, srand
#include <iostream> // for basic_ostream, char_traits, operator<< #include <ctime> // for time
#include <memory> // for unique_ptr, shared_ptr, make_shared #include <iostream> // for basic_ostream, char_traits, operator<<
#include <string> // for operator+, string, to_string #include <memory> // for unique_ptr, shared_ptr, make_shared
#include <vector> // for vector #include <string> // for operator+, string, to_string
#include <vector> // for vector
#include "ball.h" // for Ball #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 "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 // Variables globales
SDL_Window *window = nullptr; SDL_Window *window = nullptr;
@@ -27,28 +29,28 @@ std::array<int, 8> test = {1, 10, 100, 500, 1000, 10000, 50000, 100000};
bool should_exit = false; // Controla si la aplicación debe cerrarse bool should_exit = false; // Controla si la aplicación debe cerrarse
// ticks eliminado - reemplazado por delta time system // ticks eliminado - reemplazado por delta time system
int scenario = 0; // Escenario actual basado en el número de bolas int scenario = 0; // Escenario actual basado en el número de bolas
std::string text; // Texto a mostrar en pantalla std::string text; // Texto a mostrar en pantalla
int text_pos = 0; // Posición del texto en la pantalla int text_pos = 0; // Posición del texto en la pantalla
bool show_text = true; // Determina si el texto se debe mostrar bool show_text = true; // Determina si el texto se debe mostrar
Uint64 text_init_time = 0; // Temporizador para mostrar el texto Uint64 text_init_time = 0; // Temporizador para mostrar el texto
// Variables para contador de FPS // Variables para contador de FPS
Uint64 fps_last_time = 0; // Último tiempo para cálculo de FPS Uint64 fps_last_time = 0; // Último tiempo para cálculo de FPS
int fps_frame_count = 0; // Contador de frames int fps_frame_count = 0; // Contador de frames
int fps_current = 0; // FPS actuales calculados int fps_current = 0; // FPS actuales calculados
std::string fps_text = "FPS: 0"; // Texto del contador de FPS std::string fps_text = "FPS: 0"; // Texto del contador de FPS
// Variables para V-Sync // Variables para V-Sync
bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto) bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto)
std::string vsync_text = "VSYNC ON"; // Texto del estado V-Sync std::string vsync_text = "VSYNC ON"; // Texto del estado V-Sync
// Variables para Delta Time // Variables para Delta Time
Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos
float delta_time = 0.0f; // Tiempo transcurrido desde el último frame en segundos float delta_time = 0.0f; // Tiempo transcurrido desde el último frame en segundos
// Variables para Debug Display // 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 // Sistema de temas de colores
enum class ColorTheme { enum class ColorTheme {
@@ -62,57 +64,51 @@ ColorTheme current_theme = ColorTheme::SUNSET;
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"}; std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"};
struct ThemeColors { struct ThemeColors {
// Colores de fondo (superior -> inferior) // Colores de fondo (superior -> inferior)
float bg_top_r, bg_top_g, bg_top_b; float bg_top_r, bg_top_g, bg_top_b;
float bg_bottom_r, bg_bottom_g, bg_bottom_b; float bg_bottom_r, bg_bottom_g, bg_bottom_b;
// Paletas de colores para bolas (RGB 0-255) // Paletas de colores para bolas (RGB 0-255)
int ball_colors[8][3]; // 8 colores por tema int ball_colors[8][3]; // 8 colores por tema
}; };
ThemeColors themes[4] = { ThemeColors themes[4] = {
// SUNSET: Naranjas, rojos, amarillos, rosas // SUNSET: Naranjas, rojos, amarillos, rosas
{ {180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior (naranja suave)
180.0f/255.0f, 140.0f/255.0f, 100.0f/255.0f, // Fondo superior (naranja suave) 40.0f / 255.0f,
40.0f/255.0f, 20.0f/255.0f, 60.0f/255.0f, // Fondo inferior (púrpura oscuro) 20.0f / 255.0f,
{{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, // Bolas sunset 60.0f / 255.0f, // Fondo inferior (púrpura oscuro)
{255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}} {{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 // OCEAN: Azules, cianes, verdes agua, blancos
{ {100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior (azul cielo)
100.0f/255.0f, 150.0f/255.0f, 200.0f/255.0f, // Fondo superior (azul cielo) 20.0f / 255.0f,
20.0f/255.0f, 40.0f/255.0f, 80.0f/255.0f, // Fondo inferior (azul marino) 40.0f / 255.0f,
{{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, // Bolas ocean 80.0f / 255.0f, // Fondo inferior (azul marino)
{70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}} {{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 // NEON: Cian, magenta, verde lima, amarillo vibrante
{ {20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior (negro azulado)
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, 0.0f/255.0f, // Fondo inferior (negro) 0.0f / 255.0f,
{{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, // Bolas neon 0.0f / 255.0f, // Fondo inferior (negro)
{255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}} {{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 // FOREST: Verdes, marrones, amarillos otoño
{ {144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior (verde claro)
144.0f/255.0f, 238.0f/255.0f, 144.0f/255.0f, // Fondo superior (verde claro) 101.0f / 255.0f,
101.0f/255.0f, 67.0f/255.0f, 33.0f/255.0f, // Fondo inferior (marrón tierra) 67.0f / 255.0f,
{{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, // Bolas forest 33.0f / 255.0f, // Fondo inferior (marrón tierra)
{210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}} {{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 // Variables para Batch Rendering
std::vector<SDL_Vertex> batch_vertices; std::vector<SDL_Vertex> batch_vertices;
std::vector<int> batch_indices; std::vector<int> batch_indices;
// Función para renderizar fondo degradado // Función para renderizar fondo degradado
void renderGradientBackground() void renderGradientBackground() {
{
// Crear quad de pantalla completa con degradado // Crear quad de pantalla completa con degradado
SDL_Vertex bg_vertices[4]; SDL_Vertex bg_vertices[4];
// Obtener colores del tema actual // Obtener colores del tema actual
ThemeColors& theme = themes[static_cast<int>(current_theme)]; ThemeColors &theme = themes[static_cast<int>(current_theme)];
float top_r = theme.bg_top_r; float top_r = theme.bg_top_r;
float top_g = theme.bg_top_g; float top_g = theme.bg_top_g;
@@ -150,8 +146,7 @@ void renderGradientBackground()
} }
// Función para añadir un sprite al batch // 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<int>(batch_vertices.size()); int vertex_index = static_cast<int>(batch_vertices.size());
// Crear 4 vértices para el quad (2 triángulos) // 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 // Establece el texto en pantalla mostrando el número de bolas actuales
void setText() void setText() {
{ const std::string TEXT_NUMBER = test[scenario] == 1 ? " PELOTA" : " PELOTAS";
const std::string TEXT_NUMBER = test[scenario] == 1 ? " PELOTA" : " PELOTAS"; text = std::to_string(test[scenario]) + TEXT_NUMBER;
text = std::to_string(test[scenario]) + TEXT_NUMBER; const int TEXT_SIZE = static_cast<int>(text.size() * 8);
const int TEXT_SIZE = static_cast<int>(text.size() * 8); text_pos = SCREEN_WIDTH / 2 - TEXT_SIZE / 2;
text_pos = SCREEN_WIDTH / 2 - TEXT_SIZE / 2; text_init_time = SDL_GetTicks();
text_init_time = SDL_GetTicks(); show_text = true;
show_text = true;
} }
// Inicializa las bolas según el escenario seleccionado // Inicializa las bolas según el escenario seleccionado
void initBalls(int value) void initBalls(int value) {
{ balls.clear();
balls.clear(); for (int i = 0; i < test.at(value); ++i) {
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 int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -) const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X
const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y
const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X // Seleccionar color de la paleta del tema actual
const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y ThemeColors &theme = themes[static_cast<int>(current_theme)];
// Seleccionar color de la paleta del tema actual int color_index = rand() % 8; // 8 colores por tema
ThemeColors& theme = themes[static_cast<int>(current_theme)]; const Color COLOR = {theme.ball_colors[color_index][0],
int color_index = rand() % 8; // 8 colores por tema theme.ball_colors[color_index][1],
const Color COLOR = {theme.ball_colors[color_index][0], theme.ball_colors[color_index][2]};
theme.ball_colors[color_index][1], balls.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture));
theme.ball_colors[color_index][2]}; }
balls.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture)); setText(); // Actualiza el texto
}
setText(); // Actualiza el texto
} }
// Aumenta la velocidad vertical de las bolas "hacia arriba" // Aumenta la velocidad vertical de las bolas "hacia arriba"
void pushUpBalls() void pushUpBalls() {
{ for (auto &ball : balls) {
for (auto &ball : balls) const int SIGNO = ((rand() % 2) * 2) - 1;
{ const float VX = (((rand() % 20) + 10) * 0.1f) * SIGNO;
const int SIGNO = ((rand() % 2) * 2) - 1; const float VY = ((rand() % 40) * 0.1f) + 5;
const float VX = (((rand() % 20) + 10) * 0.1f) * SIGNO; ball->modVel(VX, -VY); // Modifica la velocidad de la bola
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 // Cambia la gravedad de todas las bolas
void switchBallsGravity() void switchBallsGravity() {
{ for (auto &ball : balls) {
for (auto &ball : balls) ball->switchGravity();
{ }
ball->switchGravity();
}
} }
// Alterna el estado del V-Sync // Alterna el estado del V-Sync
void toggleVSync() void toggleVSync() {
{ vsync_enabled = !vsync_enabled;
vsync_enabled = !vsync_enabled; vsync_text = vsync_enabled ? "VSYNC ON" : "VSYNC OFF";
vsync_text = vsync_enabled ? "VSYNC ON" : "VSYNC OFF";
// Aplicar el cambio de V-Sync al renderizador // Aplicar el cambio de V-Sync al renderizador
SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0);
} }
// Calcula el delta time entre frames // Calcula el delta time entre frames
void calculateDeltaTime() void calculateDeltaTime() {
{ Uint64 current_time = SDL_GetTicks();
Uint64 current_time = SDL_GetTicks();
// En el primer frame, inicializar el tiempo anterior // En el primer frame, inicializar el tiempo anterior
if (last_frame_time == 0) if (last_frame_time == 0) {
{ last_frame_time = current_time;
last_frame_time = current_time; delta_time = 1.0f / 60.0f; // Asumir 60 FPS para el primer frame
delta_time = 1.0f / 60.0f; // Asumir 60 FPS para el primer frame return;
return; }
}
// Calcular delta time en segundos // Calcular delta time en segundos
delta_time = (current_time - last_frame_time) / 1000.0f; delta_time = (current_time - last_frame_time) / 1000.0f;
last_frame_time = current_time; last_frame_time = current_time;
// Limitar delta time para evitar saltos grandes (pausa larga, depuración, etc.) // Limitar delta time para evitar saltos grandes (pausa larga, depuración, etc.)
if (delta_time > 0.05f) // Máximo 50ms (20 FPS mínimo) if (delta_time > 0.05f) // Máximo 50ms (20 FPS mínimo)
{ {
delta_time = 1.0f / 60.0f; // Usar 60 FPS como fallback delta_time = 1.0f / 60.0f; // Usar 60 FPS como fallback
} }
} }
// Inicializa SDL y configura los componentes principales // Inicializa SDL y configura los componentes principales
bool init() bool init() {
{ bool success = true;
bool success = true;
// Inicializa SDL // Inicializa SDL
if (!SDL_Init(SDL_INIT_VIDEO)) if (!SDL_Init(SDL_INIT_VIDEO)) {
{ std::cout << "¡SDL no se pudo inicializar! Error de SDL: " << SDL_GetError() << std::endl;
std::cout << "¡SDL no se pudo inicializar! Error de SDL: " << SDL_GetError() << std::endl; success = false;
success = false; } else {
} // Crear ventana principal
else window = SDL_CreateWindow(WINDOW_CAPTION, SCREEN_WIDTH * WINDOW_SIZE, SCREEN_HEIGHT * WINDOW_SIZE, SDL_WINDOW_OPENGL);
{ if (window == nullptr) {
// Crear ventana principal std::cout << "¡No se pudo crear la ventana! Error de SDL: " << SDL_GetError() << std::endl;
window = SDL_CreateWindow(WINDOW_CAPTION, SCREEN_WIDTH * WINDOW_SIZE, SCREEN_HEIGHT * WINDOW_SIZE, SDL_WINDOW_OPENGL); success = false;
if (window == nullptr) } else {
{ // Crear renderizador
std::cout << "¡No se pudo crear la ventana! Error de SDL: " << SDL_GetError() << std::endl; renderer = SDL_CreateRenderer(window, nullptr);
success = false; if (renderer == nullptr) {
} std::cout << "¡No se pudo crear el renderizador! Error de SDL: " << SDL_GetError() << std::endl;
else success = false;
{ } else {
// Crear renderizador // Establecer color inicial del renderizador
renderer = SDL_CreateRenderer(window, nullptr); SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
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 // Establecer tamaño lógico para el renderizado
SDL_SetRenderLogicalPresentation(renderer, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); SDL_SetRenderLogicalPresentation(renderer, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE);
// Configurar V-Sync inicial // Configurar V-Sync inicial
SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0); SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0);
} }
} }
} }
// Inicializar otros componentes // Inicializar otros componentes
texture = std::make_shared<Texture>(renderer, "resources/ball.png"); texture = std::make_shared<Texture>(renderer, "resources/ball.png");
// ticks eliminado - delta time system se inicializa automáticamente // ticks eliminado - delta time system se inicializa automáticamente
srand(static_cast<unsigned>(time(nullptr))); srand(static_cast<unsigned>(time(nullptr)));
dbg_init(renderer); dbg_init(renderer);
initBalls(scenario); initBalls(scenario);
return success; return success;
} }
// Limpia todos los recursos y cierra SDL // Limpia todos los recursos y cierra SDL
void close() void close() {
{ SDL_DestroyRenderer(renderer);
SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window);
SDL_DestroyWindow(window); SDL_Quit();
SDL_Quit();
} }
// Verifica los eventos en la cola // Verifica los eventos en la cola
void checkEvents() void checkEvents() {
{ SDL_Event event;
SDL_Event event; while (SDL_PollEvent(&event) != 0) {
while (SDL_PollEvent(&event) != 0) // Evento de salida
{ if (event.type == SDL_EVENT_QUIT) {
// Evento de salida should_exit = true;
if (event.type == SDL_EVENT_QUIT) break;
{ }
should_exit = true;
break;
}
// Procesar eventos de teclado // Procesar eventos de teclado
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) {
{ switch (event.key.key) {
switch (event.key.key) case SDLK_ESCAPE:
{ should_exit = true;
case SDLK_ESCAPE: break;
should_exit = true;
break;
case SDLK_SPACE: case SDLK_SPACE:
pushUpBalls(); pushUpBalls();
break; break;
case SDLK_G: case SDLK_G:
switchBallsGravity(); switchBallsGravity();
break; break;
case SDLK_V: case SDLK_V:
toggleVSync(); toggleVSync();
break; break;
case SDLK_H: case SDLK_H:
show_debug = !show_debug; show_debug = !show_debug;
break; break;
case SDLK_T: case SDLK_T:
// Ciclar al siguiente tema // Ciclar al siguiente tema
current_theme = static_cast<ColorTheme>((static_cast<int>(current_theme) + 1) % 4); current_theme = static_cast<ColorTheme>((static_cast<int>(current_theme) + 1) % 4);
initBalls(scenario); // Regenerar bolas con nueva paleta initBalls(scenario); // Regenerar bolas con nueva paleta
break; break;
case SDLK_F1: case SDLK_F1:
current_theme = ColorTheme::SUNSET; current_theme = ColorTheme::SUNSET;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_F2: case SDLK_F2:
current_theme = ColorTheme::OCEAN; current_theme = ColorTheme::OCEAN;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_F3: case SDLK_F3:
current_theme = ColorTheme::NEON; current_theme = ColorTheme::NEON;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_F4: case SDLK_F4:
current_theme = ColorTheme::FOREST; current_theme = ColorTheme::FOREST;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_1: case SDLK_1:
scenario = 0; scenario = 0;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_2: case SDLK_2:
scenario = 1; scenario = 1;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_3: case SDLK_3:
scenario = 2; scenario = 2;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_4: case SDLK_4:
scenario = 3; scenario = 3;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_5: case SDLK_5:
scenario = 4; scenario = 4;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_6: case SDLK_6:
scenario = 5; scenario = 5;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_7: case SDLK_7:
scenario = 6; scenario = 6;
initBalls(scenario); initBalls(scenario);
break; break;
case SDLK_8: case SDLK_8:
scenario = 7; scenario = 7;
initBalls(scenario); initBalls(scenario);
break; break;
} }
} }
} }
} }
// Actualiza la lógica del juego // Actualiza la lógica del juego
void update() void update() {
{ // Calcular FPS
// Calcular FPS fps_frame_count++;
fps_frame_count++; Uint64 current_time = SDL_GetTicks();
Uint64 current_time = SDL_GetTicks(); if (current_time - fps_last_time >= 1000) // Actualizar cada segundo
if (current_time - fps_last_time >= 1000) // Actualizar cada segundo {
{ fps_current = fps_frame_count;
fps_current = fps_frame_count; fps_frame_count = 0;
fps_frame_count = 0; fps_last_time = current_time;
fps_last_time = current_time; fps_text = "FPS: " + std::to_string(fps_current);
fps_text = "FPS: " + std::to_string(fps_current); }
}
// ¡DELTA TIME! Actualizar física siempre, usando tiempo transcurrido // ¡DELTA TIME! Actualizar física siempre, usando tiempo transcurrido
for (auto &ball : balls) for (auto &ball : balls) {
{ ball->update(delta_time); // Pasar delta time a cada pelota
ball->update(delta_time); // Pasar delta time a cada pelota }
}
// Actualizar texto (sin cambios en la lógica) // Actualizar texto (sin cambios en la lógica)
if (show_text) if (show_text) {
{ show_text = !(SDL_GetTicks() - text_init_time > TEXT_DURATION);
show_text = !(SDL_GetTicks() - text_init_time > TEXT_DURATION); }
}
} }
// Renderiza el contenido en la pantalla // Renderiza el contenido en la pantalla
void render() void render() {
{ // Renderizar fondo degradado en lugar de color sólido
// Renderizar fondo degradado en lugar de color sólido renderGradientBackground();
renderGradientBackground();
// Limpiar batches del frame anterior // Limpiar batches del frame anterior
batch_vertices.clear(); batch_vertices.clear();
batch_indices.clear(); batch_indices.clear();
// Recopilar datos de todas las bolas para batch rendering // Recopilar datos de todas las bolas para batch rendering
for (auto &ball : balls) for (auto &ball : balls) {
{ // En lugar de ball->render(), obtener datos para batch
// En lugar de ball->render(), obtener datos para batch SDL_FRect pos = ball->getPosition();
SDL_FRect pos = ball->getPosition(); Color color = ball->getColor();
Color color = ball->getColor(); addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b);
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b); }
}
// Renderizar todas las bolas en una sola llamada // Renderizar todas las bolas en una sola llamada
if (!batch_vertices.empty()) if (!batch_vertices.empty()) {
{ SDL_RenderGeometry(renderer, texture->getSDLTexture(), batch_vertices.data(), static_cast<int>(batch_vertices.size()), batch_indices.data(), static_cast<int>(batch_indices.size()));
SDL_RenderGeometry(renderer, texture->getSDLTexture(), }
batch_vertices.data(), static_cast<int>(batch_vertices.size()),
batch_indices.data(), static_cast<int>(batch_indices.size()));
}
if (show_text) if (show_text) {
{ dbg_print(text_pos, 8, text.c_str(), 255, 255, 255);
dbg_print(text_pos, 8, text.c_str(), 255, 255, 255);
// Mostrar nombre del tema en castellano debajo del número de pelotas // Mostrar nombre del tema en castellano debajo del número de pelotas
std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE"}; std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE"};
std::string theme_name = theme_names_es[static_cast<int>(current_theme)]; std::string theme_name = theme_names_es[static_cast<int>(current_theme)];
int theme_text_width = static_cast<int>(theme_name.length() * 8); // 8 píxeles por carácter int theme_text_width = static_cast<int>(theme_name.length() * 8); // 8 píxeles por carácter
int theme_x = (SCREEN_WIDTH - theme_text_width) / 2; // Centrar horizontalmente int theme_x = (SCREEN_WIDTH - theme_text_width) / 2; // Centrar horizontalmente
// Colores acordes a cada tema // Colores acordes a cada tema
int theme_colors[][3] = { int theme_colors[][3] = {
{255, 140, 60}, // ATARDECER: Naranja cálido {255, 140, 60}, // ATARDECER: Naranja cálido
{80, 200, 255}, // OCEANO: Azul océano {80, 200, 255}, // OCEANO: Azul océano
{255, 60, 255}, // NEON: Magenta brillante {255, 60, 255}, // NEON: Magenta brillante
{100, 255, 100} // BOSQUE: Verde natural {100, 255, 100} // BOSQUE: Verde natural
}; };
int theme_idx = static_cast<int>(current_theme); int theme_idx = static_cast<int>(current_theme);
dbg_print(theme_x, 24, theme_name.c_str(), dbg_print(theme_x, 24, theme_name.c_str(), theme_colors[theme_idx][0], theme_colors[theme_idx][1], theme_colors[theme_idx][2]);
theme_colors[theme_idx][0], }
theme_colors[theme_idx][1],
theme_colors[theme_idx][2]);
}
// Debug display (solo si está activado con tecla H) // Debug display (solo si está activado con tecla H)
if (show_debug) if (show_debug) {
{ // Mostrar contador de FPS en esquina superior derecha
// Mostrar contador de FPS en esquina superior derecha int fps_text_width = static_cast<int>(fps_text.length() * 8); // 8 píxeles por carácter
int fps_text_width = static_cast<int>(fps_text.length() * 8); // 8 píxeles por carácter int fps_x = SCREEN_WIDTH - fps_text_width - 8; // 8 píxeles de margen
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
dbg_print(fps_x, 8, fps_text.c_str(), 255, 255, 0); // Amarillo para distinguir
// Mostrar estado V-Sync en esquina superior izquierda // Mostrar estado V-Sync en esquina superior izquierda
dbg_print(8, 8, vsync_text.c_str(), 0, 255, 255); // Cian para distinguir dbg_print(8, 8, vsync_text.c_str(), 0, 255, 255); // Cian para distinguir
// Debug: Mostrar valores de la primera pelota (si existe) // Debug: Mostrar valores de la primera pelota (si existe)
if (!balls.empty()) if (!balls.empty()) {
{ // Línea 1: Gravedad (solo números enteros)
// Línea 1: Gravedad (solo números enteros) int grav_int = static_cast<int>(balls[0]->getGravityForce());
int grav_int = static_cast<int>(balls[0]->getGravityForce()); std::string grav_text = "GRAV " + std::to_string(grav_int);
std::string grav_text = "GRAV " + std::to_string(grav_int); dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug
dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug
// Línea 2: Velocidad Y (solo números enteros) // Línea 2: Velocidad Y (solo números enteros)
int vy_int = static_cast<int>(balls[0]->getVelocityY()); int vy_int = static_cast<int>(balls[0]->getVelocityY());
std::string vy_text = "VY " + std::to_string(vy_int); std::string vy_text = "VY " + std::to_string(vy_int);
dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug
// Línea 3: Estado suelo // Línea 3: Estado suelo
std::string floor_text = balls[0]->isOnFloor() ? "FLOOR YES" : "FLOOR NO"; 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 dbg_print(8, 40, floor_text.c_str(), 255, 0, 255); // Magenta para debug
} }
// Debug: Mostrar tema actual // Debug: Mostrar tema actual
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"}; std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"};
std::string theme_text = "THEME " + theme_names[static_cast<int>(current_theme)]; std::string theme_text = "THEME " + theme_names[static_cast<int>(current_theme)];
dbg_print(8, 48, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema dbg_print(8, 48, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
} }
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
} }
// Función principal // Función principal
int main(int argc, char *args[]) int main(int argc, char *args[]) {
{ if (!init()) {
if (!init()) std::cout << "Ocurrió un error durante la inicialización." << std::endl;
{ return 1;
std::cout << "Ocurrió un error durante la inicialización." << std::endl; }
return 1;
}
while (!should_exit) while (!should_exit) {
{ // 1. Calcular delta time antes de actualizar la lógica
// 1. Calcular delta time antes de actualizar la lógica calculateDeltaTime();
calculateDeltaTime();
// 2. Actualizar lógica del juego con delta time // 2. Actualizar lógica del juego con delta time
update(); update();
// 3. Procesar eventos de entrada // 3. Procesar eventos de entrada
checkEvents(); checkEvents();
// 4. Renderizar la escena // 4. Renderizar la escena
render(); render();
} }
close(); close();
return 0; return 0;
} }