Files
fn_registry/docs/capabilities/gamedev-engine.md
T
egutierrez a27dcc028c docs(capabilities): unifica tag gamedev en gamedev-2d + separa gamedev-engine
El doctor reportaba el dominio gamedev en doble FAIL: el tag plano `gamedev`
(44 funciones) como `ungrouped_candidate` y la pagina `gamedev-2d.md` como
`doc_orphan`. Causa raiz: el INDEX declaraba `[gamedev](gamedev-2d.md)` y el
auditor solo registra el slug cuando label==target, asi que ni casaba la
pagina ni declaraba el tag.

Al revisar las 44 funciones habia dos clusters reales bajo el mismo tag, asi
que se separan en dos grupos honestos:

- gamedev-2d (tag canonico): 31 builders de workflow ComfyUI + 5 de apoyo
  (post-proceso + puente a Godot) = 36. Se elimina el tag plano `gamedev` de
  los builders (ya tenian `gamedev-2d`) y se reemplaza por `gamedev-2d` en las
  de apoyo.
- gamedev-engine (grupo nuevo, pagina madre nueva): runtime de juego C++
  multiplataforma (SDL3 + sokol_gfx + miniaudio, Issue 0072b) = 8. Game loop,
  camara 2D, input unificado, sprite batch, setup render/audio, build wasm.

El tag plano `gamedev` queda eliminado (count 0). INDEX corregido: fila
gamedev-2d con label==target y conteo 36 + fila nueva gamedev-engine (8).

Verificacion: `fn index` + `fn doctor capabilities` -> ambos grupos OK
(declared_in_index=yes, doc_exists=yes, sin issues); `gamedev` plano = 0.
Solo se modifico el campo `tags` de los .md, ningun archivo de codigo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 02:40:50 +02:00

6.2 KiB
Raw Blame History

Capability group: gamedev-engine — runtime de juego C++ multiplataforma (PC + WebAssembly)

Cluster de primitivas C++ que forman el núcleo de un runtime de juego 2D portable a escritorio (Windows/Linux/macOS) y navegador (WebAssembly via emscripten). Stack: SDL3 (ventana + input + GL context) + sokol_gfx (render) + miniaudio (audio). Nacido del Issue 0072b.

A diferencia del grupo hermano gamedev-2d (generación de assets 2D con ComfyUI y puente a Godot), este grupo es el motor que ejecuta el juego: el bucle de simulación, la cámara, el input, el render por lotes y el audio. No genera arte; lo consume en tiempo de ejecución.

Tag: gamedev-engine. Filtro: mcp__registry__fn_search query="" tag="gamedev-engine".

Funciones del grupo

ID Firma corta Qué hace Pureza
game_loop_cpp_gamedev loop_run(SDL_Window*, const LoopCfg&) -> void Game loop fixed-timestep estilo Glenn Fiedler ("Fix Your Timestep"): desacopla on_fixed_update (dt fijo) de on_render (factor de interpolación), acumulador con cap anti spiral-of-death. Branch automático desktop (while loop) vs __EMSCRIPTEN__ (emscripten_set_main_loop). impure
input_unified_cpp_gamedev input_begin_frame(InputState&); input_process_event(InputState&, const SDL_Event*) Snapshot unificado de input por frame para SDL3: mapea teclado (WASD+flechas), ratón, gamepad y touch a botones lógicos (left/right/up/down/action_a..y/start/back) y ejes analógicos, con flags *_pressed de rising edge limpio. impure
camera_2d_cpp_gamedev world_to_screen / screen_to_world(Camera2D, Vec2) -> Vec2; visible_world_rect(Camera2D) -> Rect; view_proj_matrix(Camera2D, float[16]) Cámara ortográfica 2D pura (pos centro, zoom, rotación, viewport): conversiones world↔screen, AABB visible y matriz view-projection 4×4 column-major lista para cualquier renderer. Fast-path sin trig si rotation==0. pure
sokol_setup_cpp_gfx make_environment() -> sg_environment; make_swapchain(int w, int h) -> sg_swapchain Builders puros para inicializar sokol_gfx sobre un GL context creado por SDL3 (no por sokol_app): sg_environment con defaults RGBA8 + depth/stencil y sg_swapchain del default framebuffer del contexto activo. pure
sprite_batch_cpp_gfx sprite_batch_create(int cap=4096) -> SpriteBatch; sprite_batch_begin/draw/end Batched textured quad renderer sobre sokol_gfx: begin/draw/end con auto-flush por cambio de atlas o capacidad llena. Vertex layout pos+uv+color, alpha blending estándar, GLSL 330 / GLES 300. Base de plataformeros, top-down y UI sprites. impure
audio_engine_cpp_gamedev engine_init() -> Engine; engine_shutdown(Engine&); engine_set_volume(Engine&, float) Lifecycle del engine de audio basado en miniaudio (single-header, public domain): inicializa device default, master volume, libera recursos. Cross-platform (WASAPI/ALSA/CoreAudio y WebAudio bajo emscripten). Única TU que define MINIAUDIO_IMPLEMENTATION. impure
audio_play_cpp_gamedev sound_load(Engine&, const char*) -> Sound; sound_play/stop/set_volume/destroy(Sound&); play_sound_oneshot(Engine&, const char*, float) Reproducción de audio sobre fn::audio::Engine: carga con streaming desde disco (wav/mp3/flac/ogg), play/stop/volumen por sonido, y helper fire-and-forget para one-shots sin handle. impure
build_wasm_cpp_app_bash_infra build_wasm_cpp_app(app_name, [--no-budget-check]) -> void Compila una app C++ del registry (cpp/apps/<name>) a WebAssembly via emscripten. Produce build/wasm/<name>/<name>.{html,js,wasm,wasm.gz}. Falla si el gzip supera 2 MB (budget). impure

Ejemplo canónico (esqueleto de un juego 2D)

Las primitivas se componen así dentro del main() de una app C++ del registry. Cada identificador (fn::game_loop, fn::input, fn::camera2d, fn::gfx, fn::audio) proviene de la función homónima del registry; la app solo aporta la lógica de juego.

// 1. Ventana + GL context con SDL3, sokol_gfx encima (sokol_setup)
sg_setup(...);                              // usa make_environment() del registry
auto swap   = fn::gfx::make_swapchain(W, H);
auto batch  = fn::gfx::sprite_batch_create(4096);
auto audio  = fn::audio::engine_init();
fn::audio::play_sound_oneshot(audio, "assets/music.ogg", 0.6f);

// 2. Estado de cámara e input
fn::game::Camera2D cam{ .pos = {0,0}, .zoom = 1.0f, .viewport = {W, H} };
fn::input::InputState in{};

// 3. Game loop fixed-timestep: simulación e interpolación desacopladas
fn::game::LoopCfg cfg{
  .on_event        = [&](const SDL_Event* e){ fn::input::input_process_event(in, e); },
  .on_fixed_update = [&](float dt){ /* mover entidades usando in.left_pressed... */ },
  .on_render       = [&](float alpha){
      fn::gfx::sprite_batch_begin(batch);
      // draw sprites con cam.view_proj_matrix(...) como transform
      fn::gfx::sprite_batch_end(batch);
  },
};
fn::game::loop_run(window, cfg);

// 4. Distribuir a navegador: build_wasm_cpp_app "<app>" -> build/wasm/<app>/

Fronteras (qué NO cubre)

  • Generación de assets (sprites, tiles, VFX): es el grupo hermano gamedev-2d (ComfyUI → post-proceso → Godot). Este grupo solo los renderiza en runtime.
  • Física / colisiones / ECS: no incluidos. El on_fixed_update recibe el dt fijo; la simulación la pone la app.
  • TileSet / mapas / escenas: no hay sistema de niveles; sprite_batch dibuja quads sueltos.
  • App end-to-end consumidora: a fecha de hoy estas primitivas son el núcleo del runtime (Issue 0072b) pero no hay todavía una app C++ que las componga end-to-end (varias están marcadas pendiente-usar). El ejemplo de arriba es el esqueleto previsto, no un binario validado. Cuando exista la primera app, su app.md declarará estas IDs en uses_functions y servirá de validación e2e.

Prerequisitos / notas

  • SDL3 para ventana + input + GL context; sokol_gfx (vendored en cpp/vendor/) para render; miniaudio (single-header) para audio.
  • Target nativo: GLSL 330. Target WebAssembly (emscripten): GLES 300 — sprite_batch emite ambos shaders.
  • build_wasm_cpp_app exige el SDK de emscripten en el entorno y respeta un budget de 2 MB gzip por defecto (--no-budget-check para saltarlo).