Motor gráfico de la consola

ESP32-S3 · framebuffer en PSRAM · blitter · modo 7 · API Lua — todo verificado con 18 tests

1 · Arquitectura por capas

HARDWARE ESP32-S3 · PSRAM 16MB pantalla SPI/DMA botones GPIO DRIVER (LovyanGFX) SPI + DMA pushPixels al panel (código ajeno, maduro) NÚCLEO (motor.cpp) framebuffer doble PSRAM blitter · modo 7 · texto sin dependencias (testeable) API LUA (inglés) clear · rect · line spr · mode7 · text btn · btnp · dt JUEGO main.lua init() update(dt) onButton(n) El flujo de datos: el juego (Lua) llama a la API → el núcleo pinta el framebuffer → el driver lo envía por DMA. El núcleo (motor.cpp) NO depende de hardware: se compila y se testea en el Mac con clang++.

2 · El bucle por frame (ping-pong C++ ↔ Lua)

C++ (motor) Lua (juego) 1. leer botones GPIO 2. llamar update(dt) 3. juego dibuja (limpiar, sprite…) 4. cada API llama al núcleo C++ 5. framebuffer actualizado 6. presentar() → DMA se repite cada frame (30/60 fps)

3 · Modo 7 — cómo se pinta el suelo con perspectiva

Izquierda: pantalla · Derecha: textura de suelo (vista desde arriba) PANTALLA 480×320 cielo (no lo toca modo7) ← horizonte (parámetro) cada fila más abajo = textura más comprimida (perspectiva) cámara (camX, camY, ángulo) TEXTURA DE SUELO (256×256, potencia de 2) mapeo por fila El algoritmo (por cada fila, punto fijo 16.16): S = camH / (fila - horizonte) ← factor de escala de la fila pasoX = -sin(ángulo) × S · pasoY = cos(ángulo) × S ← incremento por píxel texU = (gx >> 16) & 255 · texV = (gy >> 16) & 255 ← lectura de textura con wrap Solo 2 sumas + 1 lectura por píxel (sin multiplicaciones por píxel) → por eso va a 30/60 fps.
hardware núcleo/motor API Lua juego cámara/bucle