Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.5 KiB
id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
| id | title | status | type | domain | scope | priority | depends | blocks | related | created | updated | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0072k | gamedev — demo plataformero `engine_demo` (referencia stack completo) | pendiente | feature |
|
multi-app | alta |
|
2026-05-10 | 2026-05-17 |
|
Objetivo
App cpp/apps/engine_demo/ que valida end-to-end que el stack funciona en las 4 plataformas: PC, Web, Android, iOS. Plataformero 2D simple, 1 nivel, con todas las features tipicas para servir como referencia y test de regresion del stack.
Por qué este demo
- Sirve de test integrado del stack completo (runtime + assets + physics + crypto).
- Es la referencia que cualquier dev nuevo lee para entender como ensamblar las funciones del registry en un juego completo.
- Permite medir performance real (FPS, peso de bundle) en cada plataforma.
- Acta como gate del CI: si
engine_demorompe, algo del stack rompio.
Features del juego
| Feature | Funciones del registry usadas |
|---|---|
| Player con sprite animado | sprite_batch, anim_* (issue 0031), input_unified |
| Movimiento (left/right/jump) | physics_body, physics_shape, input_unified |
| Tilemap nivel 1 | tilemap_render, tilemap_compile, physics_shape_chain |
| Coins coleccionables | sensores Box2D + physics_get_sensor_events |
| Enemy patrullando | kinematic body + simple AI state machine |
| Trampas (spikes) | sensor + game over |
| Goal flag | sensor + level complete |
| HUD: score + lives | ImGui o custom MSDF text |
| Menu principal | ImGui o sprites + input |
| Pause menu | ImGui |
| Sound effects | audio_play_sound (jump, coin pickup, hit, win) |
| Background music | audio_play_music |
| Shaders vistosos | bg parallax + bloom post-process via gfx/shader_canvas |
| Save game | local storage (PC) / localStorage (WASM) / getFilesDir() (Android/iOS) |
| Settings (volumen, controles) | app_settings (ya en registry) |
| Splash screen + loading | logo + barra |
Features crypto opcionales (gated por flag de build):
- Connect wallet button (sub-issue 0072e)
- High score leaderboard firmado (sub-issue 0072f)
- NFT skin del wallet conectado (0072f)
Estructura
cpp/apps/engine_demo/
CMakeLists.txt
app.md
main.cpp # Entry point + game loop
game.{cpp,h} # Game state machine (menu/play/pause/gameover)
player.{cpp,h} # Player controller + animations
enemy.{cpp,h} # Simple AI
level.{cpp,h} # Tilemap loader + collision setup
hud.{cpp,h} # Score, lives, timer
menus.{cpp,h} # Title, pause, gameover, settings
audio.{cpp,h} # SFX/music coordinator
crypto.{cpp,h} # Wallet connect + leaderboard (#ifdef CRYPTO)
android/ # Android project (sub-issue 0072g)
ios/ # iOS project (sub-issue 0072h)
web/ # WASM shell.html + bridge.js (sub-issue 0072e)
assets/ # Source assets (.png, .wav, .ttf, .tmx)
sprites/
sounds/
music/
fonts/
levels/
build/ # Output del asset_compiler (gitignored)
Asset budget
Limites para mantener el download inicial razonable:
| Asset | Limite |
|---|---|
| Sprite atlas (1024x1024) | 200 KB PNG |
| MSDF font | 50 KB PNG + 5 KB JSON |
| SFX (4 sonidos, ogg) | 100 KB total |
| Music (1 track, ogg vorbis q=3) | 1 MB |
| Tilemap binario (1 nivel) | 30 KB |
| Total assets bundle | ≤ 1.5 MB |
WASM gzip + assets gzip total: ≤ 3.5 MB descargados.
Pipeline de build
bash/functions/pipelines/build_engine_demo_all.sh:
#!/usr/bin/env bash
set -euo pipefail
# 1. Compile assets
./build/cpp/apps/asset_compiler/asset_compiler bundle \
--in cpp/apps/engine_demo/assets \
--out build/engine_demo/assets.pak
# 2. Build PC
cmake --build build --target engine_demo -j
# 3. Build WASM
bash bash/functions/pipelines/build_wasm_cpp_pipelines.sh engine_demo
# 4. Build Android (si hay NDK)
[ -n "${ANDROID_NDK_HOME:-}" ] && \
bash bash/functions/pipelines/build_android_cpp_pipelines.sh engine_demo
# 5. Build iOS (si hay mac)
[ "$(uname)" = "Darwin" ] && \
bash bash/functions/pipelines/build_ios_cpp_pipelines.sh engine_demo
# 6. Reporte
echo "── Sizes ──"
ls -lah build/engine_demo/
e2e_checks completos
e2e_checks:
- id: build_pc
cmd: "cmake --build build --target engine_demo -j"
timeout_s: 300
- id: self_test
cmd: "./build/cpp/apps/engine_demo/engine_demo --self-test"
timeout_s: 60
- id: build_wasm
cmd: "bash bash/functions/pipelines/build_wasm_cpp_pipelines.sh engine_demo"
timeout_s: 600
- id: wasm_size_budget
cmd: "test $(stat -c%s build/wasm/engine_demo.wasm.gz) -lt 2097152" # 2MB
- id: assets_size_budget
cmd: "test $(stat -c%s build/engine_demo/assets.pak) -lt 1572864" # 1.5MB
- id: replay_test
cmd: "./build/cpp/apps/engine_demo/engine_demo --replay tests/replay_level1_complete.bin"
timeout_s: 60
- id: ops_audit
ref: "fn-recopilador:apps/engine_demo"
Replay determinista
Para validar que el stack es determinista (importante por crypto leaderboards), grabar inputs de una run completa del nivel y poder reproducirla:
// --record output.bin → graba InputState cada frame
// --replay input.bin → reproduce inputs, asserta que el final state es identico
Funcion: cpp/functions/gamedev/replay_record.{cpp,h,md} + replay_play.{cpp,h,md}.
Si el replay diverge, hay un bug de determinismo en alguna funcion del stack. Es nuestro test de regresion mas potente.
Niveles
1 solo nivel built-in para mantener simple. Si el editor (0072i) esta listo, el nivel se hace ahi y se exporta. Si no, se hace a mano en Tiled (formato .tmx).
Visual style
Pixel art simple para mantener tamaño bajo. Paleta limitada (PICO-8 o similar). Background con gradiente shader animado (no PNG → ahorra KB).
Shaders incluidos:
- Background gradient + parallax
- Player squash/stretch on jump (vertex shader simple)
- Coin sparkle (sprite + shader noise)
- Bloom post-process (fullscreen pass) — opcional, toggle en settings
- CRT-effect overlay — opcional, toggle en settings
Crypto features (gated)
Build flag CRYPTO=1 activa:
- Boton "Connect Wallet" en main menu.
- Leaderboard mostrando top 10 firmados.
- Si conectado wallet con NFT skin, usa la imagen del NFT como sprite del player.
Sin CRYPTO=1, el juego es totalmente jugable sin wallet (importante: NO gating del juego basico).
Criterio de exito
- Jugable en PC (Win + Linux), navegador moderno (Chrome + Firefox), Android device, iOS device.
- Mismo binario base + plataforma layer especifica.
- Replay grabado en PC reproduce identico en WASM (test de determinismo).
- Tamaños dentro de budget en todas las plataformas.
- FPS estable ≥60 en hardware modesto.
- Crypto features funcionan en navegador con MetaMask.
- CI corre
e2e_checksy bloquea regresiones.
No-objetivos
- Multiple niveles. Solo 1 para demo.
- Multiplayer.
- Save/load con cloud sync.
- Achievements / Steam integration.
- Mas que un genero. Plataformero por encajar bien con todas las features.
Riesgos
- Determinismo cross-platform —
-ffast-matho diferencias defloor/ceilpueden romperlo. Auditar flags por plataforma. - Audio latency mobile — pruebas reales en device. Si > 80ms, evaluar AAudio backend en Android.
- Performance en device viejo — target Android 7+ y iPhone 6S+. Profile en hardware modesto.