Files
orni-attack/MIGRATION_PLAN.md
T
2026-05-19 14:13:29 +02:00

7.3 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) ba6fd00
7b+c — Swap atómico a SDL3 GPU + line_renderer al pipeline fa7da4c
7d — Validación visual del usuario en hardware real pendiente
8 — Postprocesado, color, paleta por tipo 🔲
9 — Refactor de GameScene (2.877 LOC → módulos) 🔲
10 — Tuning final de masa/restitución/damping 🔲
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 7d — validación del usuario)

El proyecto ya no contiene SDL_Renderer ni una sola línea. Todo el rendering pasa por SDL3 GPU.

Estado tras fa7da4c:

  • Backend: Vulkan en Linux/Windows, Metal pendiente en macOS (shaders MSL todavía no se generan en build, solo SPIR-V).
  • SDLManager posee un Rendering::Renderer (alias de GpuFrameRenderer). clear()beginFrame(), present()endFrame(). Letterbox vía setViewport mid-frame. VSync vía SDL_SetGPUSwapchainParameters.
  • linea(renderer, x1,y1,x2,y2, brightness, thickness): la implementación empuja la línea como quad extrudido (pushLine) al batch del frame. El grosor es configurable por línea o global (default 1.5 px).
  • Todo el resto del juego (entities, effects, scenes, title, vector_text, starfield, shape_renderer) pasa Rendering::Renderer* opaco. Solo line_renderer.cpp toca métodos del backend.

Smoke test xvfb: compila, arranca con Backend GPU: vulkan, carga shapes y termina limpio. La pantalla del xvfb sale negra porque el host no tiene aceleración 3D (VMware), pero eso no es un bug del juego — es xvfb que no muestra el swapchain Vulkan.

Acción pendiente del usuario: probar el binario en hardware real con Vulkan nativo para validar que las líneas se dibujan correctamente. Si hay problemas visuales, los ajustes que más probablemente harán falta son:

  1. Convención de orientación de los triángulos (FRONTFACE_COUNTER_CLOCKWISE está en el pipeline; si se ven invertidos, cambiar a CLOCKWISE).
  2. Si las líneas se ven demasiado finas o gruesas: setLineThickness(N) global o pasar thickness por llamada.
  3. Si hay flicker o screen tearing: revisar Options::rendering.vsync.

Tras la validación visual, la migración técnica de SDL3 GPU está cerrada y podemos pasar a Fase 8 (postprocesado / paleta de colores por tipo de entidad) o Fase 9 (refactor de GameScene).

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.