Files
orni-attack/MIGRATION_PLAN.md
T
JailDesigner ba6fd00b54 Fase 7a: infraestructura SDL3 GPU (dormida, sin tocar runtime)
Preparacion del pipeline GPU. Codigo nuevo aislado en
core/rendering/gpu/; el runtime sigue usando SDL_Renderer hasta
Fase 7b. Tras 7a el juego sigue funcionando identico.

Shaders (shaders/):
- line.vert.glsl: vertex shader, transforma de pixeles logicos a NDC
  via uniform buffer LineUniforms{viewport_w, viewport_h}.
- line.frag.glsl: pinta el color RGBA interpolado.

Build:
- CMakeLists.txt: step nuevo que compila *.glsl a build/shaders/*.spv
  con glslc. ALL depende del target 'shaders' para incluirlo en cada
  build. Falla en cmake config si glslc no esta instalado.

Wrappers C++ (source/core/rendering/gpu/):
- gpu_device.hpp/cpp: GpuDevice, claim del window, loadShader desde
  .spv. Backends solicitados: Vulkan + Metal (sin DirectX).
- gpu_line_pipeline.hpp/cpp: GpuLinePipeline. Vertex layout
  (vec2 pos + vec4 color), primitive TRIANGLELIST (lineas como
  quads), alpha blending estandar, sin culling ni depth.
- gpu_frame_renderer.hpp/cpp: GpuFrameRenderer, API alto nivel:
  beginFrame / pushLine / endFrame. Extrusion perpendicular en CPU
  por linea (thickness libre por linea). Un draw call por frame
  con vertex+index buffers transitorios.

Plan: 7b swap del SDL_Renderer al GpuFrameRenderer en SDLManager.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:01:34 +02:00

6.8 KiB
Raw Blame History

Plan de migración Orni Attack → SDL3 GPU + física vectorial

Documento maestro de la rama rewrite/physics-gpu. Resumen del progreso y qué queda. Si pierdes el contexto de la sesión, léeme primero.

Visión

Modernizar la base técnica del juego antes de tunear jugabilidad:

  1. Limpiar legacy (polares, mezcla catalán/inglés, header guards).
  2. Adoptar formato 16:9 (1280×720).
  3. Importar subsistemas robustos de AEEA (audio, input deferido).
  4. Implementar física vectorial 2D con rigid bodies + colisiones elásticas.
  5. Migrar renderizado a SDL3 GPU sin fallback (memoria: project-no-sdl-fallback).
  6. Postprocesado y color.

El tuning de feeling se hace al final, post-GPU.

Estado actual

Rama de trabajo: rewrite/physics-gpu (pusheada a Gitea). Tag de seguridad: beta-3.0 (snapshot de main antes de empezar).

Fase Estado Commits
0 — Limpieza de código muerto (primitives, polígonos, Bresenham, polares) 6cf990b
1a — Punt → Vec2 con operadores modernos cd38101
1b — Renames de entidades + métodos virtuales a camelBack ae5cc1c
1c — Renames de escenas 5871d29
1d — Renames effects/stage_system/locales 7ee359b
1e — Pragma once + locales restantes + comentarios castellano bf83f16
(fix) — clave YAML quadrat → cuadrado post-sweep 56533ca
2 — Cambio a 1280×720 (16:9) a4f6a55
3 — Import del subsistema de Audio desde AEEA ed98ef6
4 — Input parcial AEEA ⏭️ saltado (decisión usuario)
5 — Infraestructura física (RigidBody, PhysicsWorld) 0fd9360
6a+b — body_ en Entity + world_ en GameScene 0574077
6c — Migrar Ship 2fe22ff
6d — Migrar Enemy 27242f5
6e — Migrar Bullet 9993b2d
7a — Infra GPU (shaders + wrappers, runtime dormido) (este commit)
7b — Swap SDL_Renderer → SDL_GPUDevice (clear/present por GPU) 🔲
7c — Pipeline de líneas (quads con thickness configurable) 🔲
7d — Refactor de firmas (SDL_Renderer* → FrameContext*) 🔲
7e — Cleanup + smoke test final 🔲
8 — Postprocesado, color, paleta por tipo 🔲
9 — Refactor de GameScene (2.877 LOC → módulos) 🔲
10 — Tuning final de masa/restitución/damping 🔲

Lo que queda inmediato (Fase 7b)

Swap del runtime de SDL_Renderer a SDL_GPUDevice.

Fase 7a completada: infraestructura GPU dormida (no llamada en runtime aún).

  • shaders/line.{vert,frag}.glsl → compilados en build a build/shaders/*.spv (CMake step con glslc). Vertex layout: vec2 position + vec4 color. Transformación a NDC vía uniform buffer LineUniforms{viewport_w, viewport_h}.
  • core/rendering/gpu/:
    • GpuDevice: claim del window, loadShader desde .spv.
    • GpuLinePipeline: pipeline TRIANGLELIST con vertex layout + alpha blending.
    • GpuFrameRenderer: API beginFrame / pushLine / endFrame. Extrusión perpendicular en CPU por línea (thickness configurable libre). Un draw call por frame con un vertex/index buffer transitorio.

Backend: Vulkan (Linux/Windows) y Metal (macOS). Sin DirectX.

Fase 7b siguiente:

  1. En SDLManager::iniciar, sustituir SDL_CreateRenderer por Rendering::GPU::GpuFrameRenderer::init(window, 1280, 720).
  2. SDLManager::neteja(r,g,b)gpu_renderer_.beginFrame(r/255, g/255, b/255).
  3. SDLManager::presenta()gpu_renderer_.endFrame().
  4. Borrar renderer_ (SDL_Renderer*) del SDLManager.
  5. Validar arranque con xvfb: pantalla negra (sin líneas todavía), sin crash.

Después de 7b el juego se verá NEGRO porque ningún sistema sabe pintar líneas todavía. Eso se arregla en 7c (line_renderer apunta al pipeline GPU) y 7d (refactor de firmas SDL_Renderer* → FrameContext*).

Fase 10 (tuning) queda pendiente para después de SDL3 GPU + postpro.

Memoria del proyecto

Las preferencias y decisiones persistentes están en: ~/.claude/projects/-home-sergio-gitea-orni-attack/memory/MEMORY.md y los archivos enlazados desde ahí. Léelos al empezar sesión nueva.

Resumen:

  • No fallback a SDL_Renderer en Fase 7 — solo GPU o falla.
  • Naming: .clang-tidy exige CamelCase tipos, camelBack métodos, lower_case_ miembros privados, UPPER_CASE constantes.
  • Costuras del título tras 16:9 son tuning artístico, no bug, post-Fase 10.
  • Push automático tras cada commit en rewrite/physics-gpu.
  • Smoke test xvfb (timeout 5 xvfb-run -a ./build/orni 2>&1 | head -40) tras builds importantes para validar arranque.

Convenciones técnicas

  • Lenguaje código: inglés. Lenguaje comentarios: castellano. Strings de UI: valenciano (preservados).
  • Coordenadas: cartesianas (Vec2). Polares prohibidas (legacy).
  • Resolución lógica: 1280×720. Constantes en core/defaults.hpp.
  • Audio: import de AEEA. API: Audio::get()->playSound/playMusic con crossfade y efectos.
  • Física: Physics::RigidBody en core/physics/rigid_body.hpp, Physics::PhysicsWorld en core/physics/physics_world.hpp/.cpp. Entity tiene body_ como member. Flujo tri-fase por frame en GameScene::update:
    1. physics_world_.update(dt) — integrar y resolver
    2. entity.postUpdate(dt) — sincronizar mirror (center_, angle_)
    3. Lógica del juego (input, AI, etc.) — aplica fuerzas/cambia velocity

Cómo reanudar tras compactación

  1. Lee este archivo.
  2. Lee MEMORY.md (memorias persistentes).
  3. git log --oneline -20 para ver últimos commits.
  4. git status para ver si hay trabajo en curso sin commitear.
  5. Si la fase actual estaba a medias: continúa donde se quedó (este archivo indica en qué fase estamos).
  6. Tras cada commit, push automático: git push origin rewrite/physics-gpu.

Configuración física actual (Fase 6e)

Entidad mass radius (world) restitution linear_damping angular_damping
Ship 10.0 12 0.6 1.5 0.0
Enemy Pentagon 5.0 20 1.0 0.0 0.0
Enemy Quadrat 8.0 20 1.0 0.0 0.0
Enemy Molinillo 4.0 20 1.0 0.0 0.0
Bullet 0.5 0 (cinemática) 0 0 0
Wall (PLAYAREA bounds) ∞ (estático)

Nota: Bullet usa radius=0 en el body físico para que no participe en las colisiones del world (ni body-body ni bounds). El radio de gameplay (Defaults::Entities::BULLET_RADIUS = 3) lo expone vía getCollisionRadius() y lo consumen check_collision y la detección de salida del PLAYAREA en Bullet::update.

Las paredes son implícitas: physics_world_.setBounds(PLAYAREA) en GameScene::init. No son RigidBody separados, sino un AABB que rebota.