--- id: "0072k" title: "gamedev — demo plataformero `engine_demo` (referencia stack completo)" status: pendiente type: feature domain: - gamedev scope: multi-app priority: alta depends: - "0072b" - "0072c" - "0072d" - "0072j" blocks: [] related: [] created: 2026-05-10 updated: 2026-05-17 tags: - gamedev - cpp - demo --- ## 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_demo` rompe, 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`: ```bash #!/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 ```yaml 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: ```cpp // --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 - [x] Jugable en PC (Win + Linux), navegador moderno (Chrome + Firefox), Android device, iOS device. - [x] Mismo binario base + plataforma layer especifica. - [x] Replay grabado en PC reproduce identico en WASM (test de determinismo). - [x] Tamaños dentro de budget en todas las plataformas. - [x] FPS estable ≥60 en hardware modesto. - [x] Crypto features funcionan en navegador con MetaMask. - [x] CI corre `e2e_checks` y 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 1. **Determinismo cross-platform** — `-ffast-math` o diferencias de `floor/ceil` pueden romperlo. Auditar flags por plataforma. 2. **Audio latency mobile** — pruebas reales en device. Si > 80ms, evaluar AAudio backend en Android. 3. **Performance en device viejo** — target Android 7+ y iPhone 6S+. Profile en hardware modesto.