05740775c2
Infraestructura mínima para la migración real de entidades a física vectorial (Fase 6c-e). Sin cambios de comportamiento: las entidades aún no usan body_ ni se registran al mundo. Entity (core/entities/entity.hpp): - Nuevo member protegido: Physics::RigidBody body_ (default-construido) - Nuevo método virtual: postUpdate(dt) — no-op por default, override opcional para sincronizar mirror center_/angle_ desde body_ tras la integración física. - Nuevos getters: getBody() (mutable y const) - Include de core/physics/rigid_body.hpp GameScene (game/scenes/game_scene.hpp/cpp): - Nuevo member: Physics::PhysicsWorld physics_world_ - En init(): physics_world_.clear() + setBounds(PLAYAREA). Las entidades migradas se registrarán cada una en su propio init(). El loop de GameScene::update() no se modifica todavía. La invocación de physics_world_.update(dt) + postUpdate() se añade en Fase 6c junto con la primera entidad migrada (Ship), para validar el flujo tri-fase con un caso real en lugar de cambios especulativos al control de flujo. Smoke test xvfb OK. Compila y arranca sin cambios visibles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
114 lines
5.2 KiB
C++
114 lines
5.2 KiB
C++
// game_scene.hpp - Lógica principal del juego
|
|
// © 1999 Visente i Sergi (versión Pascal)
|
|
// © 2025 Port a C++20 con SDL3
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "core/graphics/vector_text.hpp"
|
|
#include "core/physics/physics_world.hpp"
|
|
#include "core/rendering/sdl_manager.hpp"
|
|
#include "core/system/scene_context.hpp"
|
|
#include "core/system/game_config.hpp"
|
|
#include "core/types.hpp"
|
|
#include "game/constants.hpp"
|
|
#include "game/effects/debris_manager.hpp"
|
|
#include "game/effects/floating_score_manager.hpp"
|
|
#include "game/entities/bullet.hpp"
|
|
#include "game/entities/enemy.hpp"
|
|
#include "game/entities/ship.hpp"
|
|
#include "game/stage_system/stage_config.hpp"
|
|
#include "game/stage_system/stage_manager.hpp"
|
|
|
|
// Game over state machine
|
|
enum class GameOverState {
|
|
NONE, // Normal gameplay
|
|
CONTINUE, // Continue countdown screen (9→0)
|
|
GAME_OVER // Final game over (returning to title)
|
|
};
|
|
|
|
// Clase principal del juego (escena)
|
|
class GameScene {
|
|
public:
|
|
explicit GameScene(SDLManager& sdl, SceneManager::SceneContext& context);
|
|
~GameScene() = default;
|
|
|
|
void run(); // Bucle principal de l'escena
|
|
void init();
|
|
void update(float delta_time);
|
|
void draw();
|
|
|
|
private:
|
|
SDLManager& sdl_;
|
|
SceneManager::SceneContext& context_;
|
|
GameConfig::MatchConfig match_config_; // Configuración de jugadors active
|
|
|
|
// Mundo físico (Fase 5) — integración cinemática + colisiones
|
|
Physics::PhysicsWorld physics_world_;
|
|
|
|
// Efectes visuals
|
|
Effects::DebrisManager debris_manager_;
|
|
Effects::FloatingScoreManager floating_score_manager_;
|
|
|
|
// Estat del juego
|
|
std::array<Ship, 2> ships_; // [0]=P1, [1]=P2
|
|
std::array<Enemy, Constants::MAX_ORNIS> enemies_;
|
|
std::array<Bullet, Constants::MAX_BALES * 2> bullets_; // 6 balas: P1=[0,1,2], P2=[3,4,5]
|
|
std::array<float, 2> hit_timer_per_player_; // Death timers per player (seconds)
|
|
|
|
// Lives and game over system
|
|
std::array<int, 2> lives_per_player_; // [0]=P1, [1]=P2
|
|
GameOverState game_over_state_; // Game over state machine (NONE, CONTINUE, GAME_OVER)
|
|
int continue_counter_; // Continue countdown (9→0)
|
|
float continue_tick_timer_; // Timer for countdown tick (1.0s)
|
|
int continues_used_; // Continues used this game (0-3 max)
|
|
float game_over_timer_; // Final GAME OVER timer before title screen
|
|
Vec2 death_position_; // Death position (for respawn)
|
|
std::array<int, 2> score_per_player_; // [0]=P1, [1]=P2
|
|
|
|
// Text vectorial
|
|
Graphics::VectorText text_;
|
|
|
|
// [NEW] Stage system
|
|
std::unique_ptr<StageSystem::StageSystemConfig> stage_config_;
|
|
std::unique_ptr<StageSystem::StageManager> stage_manager_;
|
|
|
|
// Control de sons de animación INIT_HUD
|
|
bool init_hud_rect_sound_played_; // Flag para evitar repetir sonido del rectángulo
|
|
|
|
// Funciones privades
|
|
void tocado(uint8_t player_id);
|
|
void detectar_col·lisions_bales_enemics(); // Colisiones bullet-enemy
|
|
void detectar_col·lisio_naus_enemics(); // Ship-enemy collision detection (plural)
|
|
void detectar_col·lisions_bales_jugadors(); // Bullet-player collision detection (friendly fire)
|
|
void dibuixar_marges() const; // Dibuixar vores de la zona de juego
|
|
void dibuixar_marcador(); // Dibuixar marcador de puntuación
|
|
void disparar_bala(uint8_t player_id); // Shoot bullet from player
|
|
[[nodiscard]] Vec2 obtenir_punt_spawn(uint8_t player_id) const; // Get spawn position for player
|
|
|
|
// [NEW] Continue & Join system
|
|
void unir_jugador(uint8_t player_id); // Join inactive player mid-game
|
|
void processar_input_continue(); // Handle input during continue screen
|
|
void actualitzar_continue(float delta_time); // Update continue countdown
|
|
void check_and_apply_continue_timeout(); // Check if continue timed out and transition to GAME_OVER
|
|
void dibuixar_continue(); // Draw continue screen
|
|
|
|
// [NEW] Stage system helpers
|
|
void dibuixar_missatge_stage(const std::string& message);
|
|
|
|
// [NEW] Funciones de animación per INIT_HUD
|
|
void dibuixar_marges_animat(float progress) const; // Rectangle con creixement uniforme
|
|
void dibuixar_marcador_animat(float progress); // Marcador que puja desde baix
|
|
[[nodiscard]] Vec2 calcular_posicio_nau_init_hud(float progress, uint8_t player_id) const; // Posición animada de la ship
|
|
|
|
// [NEW] Función helper del sistema de animación INIT_HUD
|
|
[[nodiscard]] float calcular_progress_rango(float global_progress, float ratio_init, float ratio_end) const;
|
|
|
|
// [NEW] Función helper del marcador
|
|
[[nodiscard]] std::string buildScoreboard() const;
|
|
};
|