diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..ea43e1b --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(make:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d231d53 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,76 @@ +# Claude Code Session - ViBe1 Delta + +## Estado del Proyecto + +**Proyecto:** ViBe1 Delta - Simulador de sprites con fisica +**Objetivo:** Implementar delta time para separar bucle de proceso del de renderizado + +## Progreso Actual + +### ✅ Completado + +1. **Configuracion inicial** + - Reestructurar codigo: movido utilidades a `source/external/` + - Filtro nearest neighbor para texturas pixel-perfect + - Compilacion funcionando (Make y CMake) + +2. **Sistema de metricas** + - Contador FPS en esquina superior derecha (amarillo) + - Control V-Sync con tecla "V" (ON/OFF) + - Display V-Sync en esquina superior izquierda (cian) + +3. **Mejoras visuales** + - Tamaño pelota: 8x8 → 10x10 pixels + - Fondo aclarado: (32,32,32) → (64,64,64) + - Textura pelota redibujada con mejor calidad + +### 🚧 En Proceso + +- **Proximos pasos:** Implementar sistema delta time +- **Problema detectado:** Caracteres extraños en README.md (encoding) + +### 📋 Controles Actuales + +| Tecla | Accion | +|-------|---------| +| V | Alternar V-Sync ON/OFF | +| 1-8 | Cambiar numero de pelotas (1 a 100,000) | +| ESPACIO | Impulsar pelotas hacia arriba | +| G | Alternar direccion gravedad | +| ESC | Salir | + +## Arquitectura Actual + +``` +source/ +├── main.cpp # Bucle principal + FPS/V-Sync +├── ball.h/.cpp # Logica fisica pelotas +├── defines.h # Constantes (BALL_SIZE=10) +└── external/ # Utilidades externas + ├── texture.h/.cpp # Gestion texturas + nearest filter + ├── sprite.h/.cpp # Sistema sprites + ├── dbgtxt.h # Debug text + nearest filter + └── stb_image.h # Carga imagenes +``` + +## Bucket Actual: FPS Acoplado + +El sistema usa bucle acoplado a 60 FPS: +```cpp +if (SDL_GetTicks() - ticks > DEMO_SPEED) { // 16.67ms + // Solo aqui se actualiza fisica +} +``` + +**Problema:** Fisica dependiente del framerate → Inconsistencia cross-platform + +## Delta Time - Plan de Implementacion + +1. **Sistema timing independiente** +2. **Bucle desacoplado** logica vs renderizado +3. **Interpolacion** para renderizado suave +4. **Optimizaciones** rendimiento + +--- + +*Archivo de seguimiento para sesiones Claude Code* \ No newline at end of file diff --git a/README.md b/README.md index f75ec91..3aaec99 100644 Binary files a/README.md and b/README.md differ diff --git a/source/external/dbgtxt.h b/source/external/dbgtxt.h index ca421e1..0b32c20 100644 --- a/source/external/dbgtxt.h +++ b/source/external/dbgtxt.h @@ -11,6 +11,12 @@ 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}; dbg_tex = SDL_CreateTextureFromSurface(dbg_ren, SDL_LoadBMP_IO(SDL_IOFromMem(font, 448), 1)); + + // Configurar filtro nearest neighbor para píxel perfect del texto + if (dbg_tex != nullptr) + { + SDL_SetTextureScaleMode(dbg_tex, SDL_SCALEMODE_NEAREST); + } } void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b) diff --git a/source/main.cpp b/source/main.cpp index 051f5cc..7f82974 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -33,6 +33,16 @@ 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 + +// 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 + // Establece el texto en pantalla mostrando el número de bolas actuales void setText() { @@ -81,6 +91,16 @@ void switchBallsGravity() } } +// Alterna el estado del V-Sync +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); +} + // Inicializa SDL y configura los componentes principales bool init() { @@ -117,6 +137,9 @@ bool init() // 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); } } } @@ -169,6 +192,10 @@ void checkEvents() switchBallsGravity(); break; + case SDLK_V: + toggleVSync(); + break; + case SDLK_1: scenario = 0; initBalls(scenario); @@ -216,6 +243,17 @@ void checkEvents() // 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); + } + if (SDL_GetTicks() - ticks > DEMO_SPEED) { ticks = SDL_GetTicks(); @@ -248,6 +286,14 @@ void render() dbg_print(text_pos, 8, text.c_str(), 255, 255, 255); } + // 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 + SDL_RenderPresent(renderer); }