2fe22ff911
Primera entidad migrada. La nave del jugador ya NO mantiene su propio estado cinemático ad-hoc — toda la física vive en Entity::body_ y el movimiento lo realiza Physics::PhysicsWorld. Cambios en ship.hpp: - Eliminado: float velocity_ (escalar, polar) - Eliminado: void applyPhysics() (lo hace el world) - Añadido: override postUpdate() para sincronizar center_/angle_ - getVelocityVector() ahora devuelve body_.velocity (Vec2 cartesiano) - Nuevo getter getSpeed() = body_.velocity.length() - setCenter() actualiza tanto el mirror como body_.position - markHit() detiene el body_ (velocity = 0) Cambios en ship.cpp: - Constructor configura el body_: * mass = 10.0 (referencia para impulsos en choques) * radius = SHIP_RADIUS (12.0) * restitution = 0.6 (rebote moderado en paredes) * linear_damping = 1.5 s⁻¹ (fricción exponencial) * angular_damping = 0.0 (la rotación es por input, no inercial) - init() resetea body_ a la posición/orientación nueva, velocity = 0 - processInput() ahora: * Rotación: modifica body_.angle directamente (no física) * Thrust: applyForce(direction * mass * ACCELERATION) - update() solo gestiona timer de invulnerabilidad y aplica el cap de MAX_VELOCITY (el thrust acumula fuerza sin tope; clampamos body_.velocity) - postUpdate() copia body_.position -> center_ y body_.angle -> angle_ - draw() sin cambios funcionales (usa getSpeed() en lugar de velocity_) Cambios en GameScene: - En init(): physics_world_.addBody(&ship.getBody()) por cada nave activa - En update(): physics_world_.update(dt) + ship.postUpdate(dt) al inicio del frame (las fuerzas del frame N-1 se integran en el frame N; 1 frame de latencia ~16ms, imperceptible a 60fps) Cambios de comportamiento visibles esperados: - La nave ahora rebota contra las paredes del PLAYAREA con restitution=0.6 (antes: clipping silencioso). PRIMERA muestra de la nueva física. - Inercia: tras soltar THRUST, la nave conserva velocidad y se decelera exponencialmente con linear_damping. Sensación más espacial. - Velocidad limitada en magnitud vectorial (antes: escalar). El cap preserva el feel arcade aproximado de MAX_VELOCITY = 120 px/s. Edge case pendiente para tuning: - Naves muertas siguen en el world como obstáculos físicos (radius=12). No es crítico mientras los enemies/bullets no estén migrados. Smoke test xvfb: arranca correctamente. Validación de feeling requiere test del usuario en vivo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>