a27dcc028c
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>
52 lines
2.2 KiB
Markdown
52 lines
2.2 KiB
Markdown
---
|
|
name: game_loop
|
|
kind: function
|
|
lang: cpp
|
|
domain: gamedev
|
|
version: "0.1.0"
|
|
purity: impure
|
|
signature: "loop_run(SDL_Window*, const LoopCfg&) -> void"
|
|
description: "Game loop fixed-timestep estilo Glenn Fiedler ('Fix Your Timestep'). Desacopla simulacion (on_fixed_update con dt fijo) de renderizado (on_render con factor de interpolacion). Acumulador con cap anti spiral-of-death. Branch automatico desktop (while loop bloqueante) vs __EMSCRIPTEN__ (emscripten_set_main_loop). Issue 0072b."
|
|
tags: [gamedev-engine, game-loop, sdl3, wasm, fixed-timestep]
|
|
uses_functions: []
|
|
uses_types: []
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: "error_go_core"
|
|
imports: []
|
|
example: |
|
|
struct State { bool quit = false; float t = 0; };
|
|
State st;
|
|
fn::game::LoopCfg cfg;
|
|
cfg.user = &st;
|
|
cfg.on_fixed_update = [](void* u, float dt) {
|
|
auto s = (State*)u;
|
|
s->t += dt;
|
|
};
|
|
cfg.on_render = [](void* u, float interp) {
|
|
// render with interp factor between [0, 1)
|
|
};
|
|
cfg.should_quit = [](void* u) { return ((State*)u)->quit; };
|
|
fn::game::loop_run(window, cfg);
|
|
tested: false
|
|
tests: []
|
|
test_file_path: ""
|
|
file_path: "cpp/functions/gamedev/game_loop.cpp"
|
|
params:
|
|
- name: window
|
|
desc: "SDL_Window activo (no usado actualmente; reservado para futuras integraciones swap/vsync)."
|
|
- name: cfg
|
|
desc: "LoopCfg con fixed_dt (default 1/60), max_steps_per_frame (cap), callbacks on_fixed_update/on_render/should_quit y user pointer."
|
|
output: "Bloquea hasta should_quit==true (desktop). En WASM retorna inmediatamente y registra emscripten_set_main_loop."
|
|
---
|
|
|
|
# game_loop
|
|
|
|
Loop canonico para apps gamedev del registry. Garantiza que la simulacion corra a `fixed_dt` constante (default 60 Hz) independientemente del framerate de render, y expone factor `interp` para que el renderer interpole posiciones entre estados de fisica.
|
|
|
|
Detalles:
|
|
- `frame_time` se cap a `fixed_dt * max_steps_per_frame` para evitar la espiral de la muerte cuando el debugger pausa.
|
|
- En `__EMSCRIPTEN__` el estado del acumulador vive en variable static (`g_rt`) — solo un loop activo por modulo WASM.
|
|
- `should_quit` se consulta antes de cada frame; en WASM dispara `emscripten_cancel_main_loop`.
|
|
- `loop_run` retorna sin hacer nada si ambos callbacks son nulos.
|