feat(kotlin-compose): design system + 33 components + gallery_kt + e2e android emulator + scaffolder fixes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
---
|
||||
id: 0072b
|
||||
title: gamedev — runtime nucleo (sprite batcher, audio, input, game loop)
|
||||
status: pending
|
||||
priority: high
|
||||
created: 2026-05-10
|
||||
tags: [gamedev, cpp]
|
||||
parent_issue: 0072
|
||||
depends_on: [0072a]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Implementar el runtime minimo necesario para hacer un juego 2D jugable: dibujar muchos sprites por frame, reproducir audio, leer input unificado (kb/gamepad/touch), y un game loop con fixed timestep.
|
||||
|
||||
Todo en `cpp/functions/gfx/` y `cpp/functions/gamedev/` (dominio nuevo) como funciones del registry, NO empotrado en una app concreta. Apps consumidoras importan via `uses_functions`.
|
||||
|
||||
## Funciones a crear
|
||||
|
||||
### Graphics (sokol_gfx wrappers)
|
||||
|
||||
| Funcion | Lang | Domain | Purity | Proposito |
|
||||
|---|---|---|---|---|
|
||||
| `sg_init` | cpp | gfx | impure | Inicializa sokol_gfx con SDL3 GL context |
|
||||
| `sg_shader_load` | cpp | gfx | impure | Compila vertex+fragment, devuelve `sg_shader` |
|
||||
| `sg_pipeline_create` | cpp | gfx | impure | Crea `sg_pipeline` con layout estandar (pos, uv, color) |
|
||||
| `sg_image_load` | cpp | gfx | impure | stb_image → `sg_image` con mipmaps opcionales |
|
||||
| `sg_buffer_create` | cpp | gfx | impure | Vertex/index buffers static o stream |
|
||||
|
||||
### Sprite batcher
|
||||
|
||||
`sprite_batch_cpp_gfx` (impure). API:
|
||||
|
||||
```cpp
|
||||
struct SpriteBatch {
|
||||
sg_pipeline pipeline;
|
||||
sg_buffer vbo; // dynamic, ~64K vertices
|
||||
sg_buffer ibo;
|
||||
std::vector<Vertex> cpu_verts;
|
||||
sg_image current_atlas;
|
||||
};
|
||||
|
||||
void sprite_batch_begin(SpriteBatch& b, const Camera2D& cam);
|
||||
void sprite_batch_draw(SpriteBatch& b, sg_image atlas, Rect src, Rect dst, Color tint, float rotation);
|
||||
void sprite_batch_end(SpriteBatch& b); // flush draw call
|
||||
```
|
||||
|
||||
Auto-flush cuando cambia atlas o se llena CPU buffer.
|
||||
|
||||
### Audio (miniaudio wrappers)
|
||||
|
||||
| Funcion | Domain | Proposito |
|
||||
|---|---|---|
|
||||
| `audio_init` | gamedev | Inicializa miniaudio engine |
|
||||
| `audio_load_sound` | gamedev | wav/ogg/mp3 → sound handle |
|
||||
| `audio_play_sound` | gamedev | Reproduce one-shot con volumen/pan/pitch |
|
||||
| `audio_play_music` | gamedev | Streaming + loop |
|
||||
| `audio_set_listener` | gamedev | Posicion 2D para audio espacial |
|
||||
|
||||
### Input unificado
|
||||
|
||||
`input_unified_cpp_gamedev` (impure). Abstrae kb/mouse/gamepad/touch en un mismo struct:
|
||||
|
||||
```cpp
|
||||
struct InputState {
|
||||
// Buttons logicos del juego
|
||||
bool left, right, up, down;
|
||||
bool action_a, action_b, action_x, action_y;
|
||||
bool start, back;
|
||||
// Analogicos (-1..1)
|
||||
float lx, ly, rx, ry;
|
||||
// Touch (mobile/web)
|
||||
struct Touch { float x, y; bool pressed; } touches[8];
|
||||
int touch_count;
|
||||
// Mouse
|
||||
float mx, my;
|
||||
bool m_left, m_right;
|
||||
};
|
||||
|
||||
void input_poll(InputState& s, const SDL_Event* events, int count);
|
||||
```
|
||||
|
||||
Mapping: keyboard WASD/arrows + space/enter, gamepad SDL3 standard mapping, touch via virtual gamepad overlay (en sub-issue 0072g).
|
||||
|
||||
### Game loop
|
||||
|
||||
`game_loop_cpp_gamedev` (impure):
|
||||
|
||||
```cpp
|
||||
struct GameLoopCfg {
|
||||
float fixed_dt; // 1/60 default
|
||||
int max_steps_per_frame; // 5 default (evita spiral of death)
|
||||
void (*on_fixed_update)(void* user, float dt);
|
||||
void (*on_render)(void* user, float interp);
|
||||
void* user;
|
||||
};
|
||||
|
||||
void game_loop_run(SDL_Window* w, const GameLoopCfg& cfg);
|
||||
```
|
||||
|
||||
Fixed timestep con interpolacion para render (clasico Glenn Fiedler). En WASM usa `emscripten_set_main_loop`.
|
||||
|
||||
### Camara 2D
|
||||
|
||||
`camera_2d_cpp_gamedev` (pure). Struct + helpers para world↔screen, zoom, follow, shake.
|
||||
|
||||
## Estructura
|
||||
|
||||
```
|
||||
cpp/functions/gfx/
|
||||
sg_init.{cpp,h,md}
|
||||
sg_shader_load.{cpp,h,md}
|
||||
sg_pipeline_create.{cpp,h,md}
|
||||
sg_image_load.{cpp,h,md}
|
||||
sg_buffer_create.{cpp,h,md}
|
||||
sprite_batch.{cpp,h,md}
|
||||
|
||||
cpp/functions/gamedev/ # Dominio nuevo
|
||||
audio_init.{cpp,h,md}
|
||||
audio_load_sound.{cpp,h,md}
|
||||
audio_play_sound.{cpp,h,md}
|
||||
audio_play_music.{cpp,h,md}
|
||||
audio_set_listener.{cpp,h,md}
|
||||
input_unified.{cpp,h,md}
|
||||
game_loop.{cpp,h,md}
|
||||
camera_2d.{cpp,h,md}
|
||||
```
|
||||
|
||||
Registrar dominio `gamedev` en `cpp/CMakeLists.txt` y en docs del registry.
|
||||
|
||||
## Tipos del registry
|
||||
|
||||
`cpp/types/gamedev/`:
|
||||
- `SpriteBatch` (product)
|
||||
- `InputState` (product)
|
||||
- `Camera2D` (product)
|
||||
- `Color` (product, `{r,g,b,a}` floats)
|
||||
- `Rect` (product, `{x,y,w,h}`)
|
||||
- `Vec2` (product) — si no existe ya en `core`, crearlo
|
||||
|
||||
## Tests
|
||||
|
||||
Cada funcion lleva su test minimo. Uso de `--self-test` mode en una app de prueba (`cpp/apps/runtime_test/`) que:
|
||||
1. Inicializa todo
|
||||
2. Carga un sprite
|
||||
3. Carga un sonido
|
||||
4. Simula input
|
||||
5. Corre 100 frames
|
||||
6. Sale con codigo 0 si nada explota
|
||||
|
||||
## Tamaño
|
||||
|
||||
Budget: este sub-issue añade ≤ 600 KB al WASM gzip (miniaudio + sokol_gfx + box2d aun no + imgui ya contado en 0072a).
|
||||
|
||||
## Criterio de exito
|
||||
|
||||
- [x] Funciones en registry con `.md` + tests.
|
||||
- [x] App `runtime_test` corre `--self-test` exit 0 en PC + WASM.
|
||||
- [x] Sprite batcher dibuja 10000 sprites @ 60fps en navegador moderno.
|
||||
- [x] Audio one-shot sin glitches en PC + WASM.
|
||||
- [x] Input unificado funciona con kb + gamepad (touch en 0072g).
|
||||
|
||||
## No-objetivos
|
||||
|
||||
- Animacion de sprites (sub-issue futuro o parte de 0072k demo).
|
||||
- Tilemap (en 0072c).
|
||||
- Physics (en 0072j).
|
||||
- Particles (sub-issue futuro).
|
||||
Reference in New Issue
Block a user