From c50ca231358a5d090b82df14c15dfe240a99cd91 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 19 May 2026 13:42:04 +0200 Subject: [PATCH] Anadir MIGRATION_PLAN.md en raiz como referencia maestra Documento que resume el estado de la migracion (rama rewrite/physics-gpu), las fases completadas con sus commits, lo que queda inmediato y donde estan las decisiones persistentes (memoria del proyecto). Para sobrevivir compactaciones de contexto y permitir reanudar la migracion en sesiones futuras sin perder el hilo. Co-Authored-By: Claude Opus 4.7 (1M context) --- MIGRATION_PLAN.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 MIGRATION_PLAN.md diff --git a/MIGRATION_PLAN.md b/MIGRATION_PLAN.md new file mode 100644 index 0000000..a5b1288 --- /dev/null +++ b/MIGRATION_PLAN.md @@ -0,0 +1,130 @@ +# 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](./.claude/projects/-home-sergio-gitea-orni-attack/memory/project_no_sdl_fallback.md)). +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 | 🔲 **siguiente** | — | +| 7 — Migración a SDL3 GPU (sin fallback) | 🔲 | — | +| 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 6e) + +Migrar `Bullet` al PhysicsWorld. Es la entidad más simple: + +- Constructor: `body_.setMass(0.5)`, `radius = BULLET_RADIUS = 3`, `restitution = 0` + (NO rebotan, salen del PLAYAREA y se desactivan), `linear_damping = 0`. +- `init()` resetea body_. +- `disparar()`/spawn: setear `body_.position` y `body_.velocity` cartesiano a `140 px/s` en + dirección del shooter. +- `update()`: detectar si salió del PLAYAREA con margen; si sí, `desactivar()`. +- `postUpdate()`: sincronizar `center_` desde `body_.position`. +- En GameScene: registrar bodies en `init()`, llamar `postUpdate()` en `update()`. +- Cuando un bullet se desactiva: `body_.radius = 0` para no estorbar. +- **Edge case importante**: las balas NO deben rebotar contra las naves de los + jugadores. Las colisiones físicas las hace el world automáticamente. Para + evitarlo: + - Opción A: dejar que el world resuelva el impulso, pero la lógica de + gameplay (en GameScene) detecta el hit y desactiva el bullet antes de que + se vea visualmente el rebote (1 frame de margen). + - Opción B: hacer que `body_.radius = 0` para las balas, así no colisionan + físicamente, y solo las colisiones de gameplay (check_collision en + GameScene) las gestionan. + - Recomendado: **Opción B**. Las balas físicamente no necesitan colisión + del world — son cinemáticas. Solo el gameplay las usa. + +Tras 6e, hacer **Fase 10 (tuning)**: ajustar masas, restitución, damping según +feel. Probablemente: +- Ship: subir `mass` a 15-20 (más "anclado", menos empujable por enemies). +- Enemies: reducir `restitution` a 0.85 (rebote más natural, sin "pelota"). +- Probar collision con friendly fire / nave-enemy en debris ahora que ambos + tienen body real. + +## 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 6d) + +| Entidad | mass | radius | 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 | (pendiente Fase 6e) | 3 | 0 | 0 | 0 | +| Wall (PLAYAREA bounds) | ∞ (estático) | — | — | — | — | + +Las paredes son implícitas: `physics_world_.setBounds(PLAYAREA)` en +`GameScene::init`. No son `RigidBody` separados, sino un AABB que rebota.