layout de TITOL
This commit is contained in:
@@ -5,7 +5,9 @@ project(orni VERSION 0.6.0)
|
|||||||
|
|
||||||
# Info del proyecto
|
# Info del proyecto
|
||||||
set(PROJECT_LONG_NAME "Orni Attack")
|
set(PROJECT_LONG_NAME "Orni Attack")
|
||||||
set(PROJECT_COPYRIGHT "© 1999 Visente i Sergi, 2025 Port")
|
set(PROJECT_COPYRIGHT_ORIGINAL "© 1999 Visente i Sergi")
|
||||||
|
set(PROJECT_COPYRIGHT_PORT "© 2025 JailDesigner")
|
||||||
|
set(PROJECT_COPYRIGHT "${PROJECT_COPYRIGHT_ORIGINAL}, ${PROJECT_COPYRIGHT_PORT}")
|
||||||
|
|
||||||
# Establecer estándar de C++
|
# Establecer estándar de C++
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include "core/audio/audio_cache.hpp"
|
#include "core/audio/audio_cache.hpp"
|
||||||
|
|
||||||
#include "core/resources/resource_helper.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "core/resources/resource_helper.hpp"
|
||||||
|
|
||||||
// Inicialització de variables estàtiques
|
// Inicialització de variables estàtiques
|
||||||
std::unordered_map<std::string, JA_Sound_t*> AudioCache::sounds_;
|
std::unordered_map<std::string, JA_Sound_t*> AudioCache::sounds_;
|
||||||
std::unordered_map<std::string, JA_Music_t*> AudioCache::musics_;
|
std::unordered_map<std::string, JA_Music_t*> AudioCache::musics_;
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ namespace Zones {
|
|||||||
// Totes les zones definides com a percentatges de Game::WIDTH (640) i Game::HEIGHT (480)
|
// Totes les zones definides com a percentatges de Game::WIDTH (640) i Game::HEIGHT (480)
|
||||||
|
|
||||||
// Percentatges d'alçada (divisió vertical)
|
// Percentatges d'alçada (divisió vertical)
|
||||||
constexpr float SCOREBOARD_TOP_HEIGHT_PERCENT = 0.02f; // 10% superior
|
constexpr float SCOREBOARD_TOP_HEIGHT_PERCENT = 0.02f; // 10% superior
|
||||||
constexpr float MAIN_PLAYAREA_HEIGHT_PERCENT = 0.88f; // 80% central
|
constexpr float MAIN_PLAYAREA_HEIGHT_PERCENT = 0.88f; // 80% central
|
||||||
constexpr float SCOREBOARD_BOTTOM_HEIGHT_PERCENT = 0.10f; // 10% inferior
|
constexpr float SCOREBOARD_BOTTOM_HEIGHT_PERCENT = 0.10f; // 10% inferior
|
||||||
|
|
||||||
// Padding horizontal per a PLAYAREA (dins de MAIN_PLAYAREA)
|
// Padding horizontal per a PLAYAREA (dins de MAIN_PLAYAREA)
|
||||||
constexpr float PLAYAREA_PADDING_HORIZONTAL_PERCENT = 0.015f; // 5% a cada costat
|
constexpr float PLAYAREA_PADDING_HORIZONTAL_PERCENT = 0.015f; // 5% a cada costat
|
||||||
|
|
||||||
// --- CÀLCULS AUTOMÀTICS DE PÍXELS ---
|
// --- CÀLCULS AUTOMÀTICS DE PÍXELS ---
|
||||||
// Càlculs automàtics a partir dels percentatges
|
// Càlculs automàtics a partir dels percentatges
|
||||||
@@ -56,42 +56,42 @@ constexpr float PLAYAREA_PADDING_H = Game::WIDTH * PLAYAREA_PADDING_HORIZONTAL_P
|
|||||||
// Marcador superior (reservat per a futur ús)
|
// Marcador superior (reservat per a futur ús)
|
||||||
// Ocupa: 10% superior (0-48px)
|
// Ocupa: 10% superior (0-48px)
|
||||||
constexpr SDL_FRect SCOREBOARD_TOP = {
|
constexpr SDL_FRect SCOREBOARD_TOP = {
|
||||||
0.0f, // x = 0.0
|
0.0f, // x = 0.0
|
||||||
SCOREBOARD_TOP_Y, // y = 0.0
|
SCOREBOARD_TOP_Y, // y = 0.0
|
||||||
static_cast<float>(Game::WIDTH), // w = 640.0
|
static_cast<float>(Game::WIDTH), // w = 640.0
|
||||||
SCOREBOARD_TOP_H // h = 48.0
|
SCOREBOARD_TOP_H // h = 48.0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Àrea de joc principal (contenidor del 80% central, sense padding)
|
// Àrea de joc principal (contenidor del 80% central, sense padding)
|
||||||
// Ocupa: 10-90% (48-432px), ample complet
|
// Ocupa: 10-90% (48-432px), ample complet
|
||||||
constexpr SDL_FRect MAIN_PLAYAREA = {
|
constexpr SDL_FRect MAIN_PLAYAREA = {
|
||||||
0.0f, // x = 0.0
|
0.0f, // x = 0.0
|
||||||
MAIN_PLAYAREA_Y, // y = 48.0
|
MAIN_PLAYAREA_Y, // y = 48.0
|
||||||
static_cast<float>(Game::WIDTH), // w = 640.0
|
static_cast<float>(Game::WIDTH), // w = 640.0
|
||||||
MAIN_PLAYAREA_H // h = 384.0
|
MAIN_PLAYAREA_H // h = 384.0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Zona de joc real (amb padding horizontal del 5%)
|
// Zona de joc real (amb padding horizontal del 5%)
|
||||||
// Ocupa: dins de MAIN_PLAYAREA, amb marges laterals
|
// Ocupa: dins de MAIN_PLAYAREA, amb marges laterals
|
||||||
// S'utilitza per a límits del joc, col·lisions, spawn
|
// S'utilitza per a límits del joc, col·lisions, spawn
|
||||||
constexpr SDL_FRect PLAYAREA = {
|
constexpr SDL_FRect PLAYAREA = {
|
||||||
PLAYAREA_PADDING_H, // x = 32.0
|
PLAYAREA_PADDING_H, // x = 32.0
|
||||||
MAIN_PLAYAREA_Y, // y = 48.0 (igual que MAIN_PLAYAREA)
|
MAIN_PLAYAREA_Y, // y = 48.0 (igual que MAIN_PLAYAREA)
|
||||||
Game::WIDTH - 2.0f * PLAYAREA_PADDING_H, // w = 576.0
|
Game::WIDTH - 2.0f * PLAYAREA_PADDING_H, // w = 576.0
|
||||||
MAIN_PLAYAREA_H // h = 384.0 (igual que MAIN_PLAYAREA)
|
MAIN_PLAYAREA_H // h = 384.0 (igual que MAIN_PLAYAREA)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Marcador inferior (marcador actual)
|
// Marcador inferior (marcador actual)
|
||||||
// Ocupa: 10% inferior (432-480px)
|
// Ocupa: 10% inferior (432-480px)
|
||||||
constexpr SDL_FRect SCOREBOARD = {
|
constexpr SDL_FRect SCOREBOARD = {
|
||||||
0.0f, // x = 0.0
|
0.0f, // x = 0.0
|
||||||
SCOREBOARD_BOTTOM_Y, // y = 432.0
|
SCOREBOARD_BOTTOM_Y, // y = 432.0
|
||||||
static_cast<float>(Game::WIDTH), // w = 640.0
|
static_cast<float>(Game::WIDTH), // w = 640.0
|
||||||
SCOREBOARD_BOTTOM_H // h = 48.0
|
SCOREBOARD_BOTTOM_H // h = 48.0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Padding horizontal del marcador (per alinear zones esquerra/dreta amb PLAYAREA)
|
// Padding horizontal del marcador (per alinear zones esquerra/dreta amb PLAYAREA)
|
||||||
constexpr float SCOREBOARD_PADDING_H = 0.0f;//Game::WIDTH * 0.015f;
|
constexpr float SCOREBOARD_PADDING_H = 0.0f; // Game::WIDTH * 0.015f;
|
||||||
} // namespace Zones
|
} // namespace Zones
|
||||||
|
|
||||||
// Objetos del juego
|
// Objetos del juego
|
||||||
@@ -361,55 +361,112 @@ constexpr int MOLINILLO_SCORE = 200; // Molinillo (agressiu, 50 px/s)
|
|||||||
// Title scene ship animations (naus 3D flotants a l'escena de títol)
|
// Title scene ship animations (naus 3D flotants a l'escena de títol)
|
||||||
namespace Title {
|
namespace Title {
|
||||||
namespace Ships {
|
namespace Ships {
|
||||||
// Posicions clock (coordenades polars des del centre 320, 240)
|
// ============================================================
|
||||||
|
// PARÀMETRES BASE (ajustar aquí per experimentar)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// 1. Escala global de les naus
|
||||||
|
constexpr float SHIP_BASE_SCALE = 2.5f; // Multiplicador (1.0 = mida original del .shp)
|
||||||
|
|
||||||
|
// 2. Altura vertical (cercanía al centro)
|
||||||
|
// Ratio Y desde el centro de la pantalla (0.0 = centro, 1.0 = bottom de pantalla)
|
||||||
|
constexpr float TARGET_Y_RATIO = 0.15625f;
|
||||||
|
|
||||||
|
// 3. Radio orbital (distancia radial desde centro en coordenadas polares)
|
||||||
|
constexpr float CLOCK_RADIUS = 150.0f; // Distància des del centre
|
||||||
|
|
||||||
|
// 4. Ángulos de posición (clock positions en coordenadas polares)
|
||||||
// En coordenades de pantalla: 0° = dreta, 90° = baix, 180° = esquerra, 270° = dalt
|
// En coordenades de pantalla: 0° = dreta, 90° = baix, 180° = esquerra, 270° = dalt
|
||||||
constexpr float CLOCK_8_ANGLE = 150.0f * Math::PI / 180.0f; // 8 o'clock = bottom-left
|
constexpr float CLOCK_8_ANGLE = 150.0f * Math::PI / 180.0f; // 8 o'clock (bottom-left)
|
||||||
constexpr float CLOCK_4_ANGLE = 30.0f * Math::PI / 180.0f; // 4 o'clock = bottom-right
|
constexpr float CLOCK_4_ANGLE = 30.0f * Math::PI / 180.0f; // 4 o'clock (bottom-right)
|
||||||
constexpr float CLOCK_RADIUS = 150.0f; // Distància des del centre
|
|
||||||
|
|
||||||
// P1 (8 o'clock, bottom-left)
|
// 5. Radio máximo de la forma de la nave (para calcular offset automáticamente)
|
||||||
// 150° → cos(150°)=-0.866, sin(150°)=0.5 → X = 320 - 130 = 190, Y = 240 + 75 = 315
|
constexpr float SHIP_MAX_RADIUS = 30.0f; // Radi del cercle circumscrit a ship_p1.shp
|
||||||
constexpr float P1_TARGET_X = 190.0f;
|
|
||||||
constexpr float P1_TARGET_Y = 315.0f;
|
|
||||||
|
|
||||||
// P2 (4 o'clock, bottom-right)
|
// 6. Margen de seguridad para offset de entrada
|
||||||
// 30° → cos(30°)=0.866, sin(30°)=0.5 → X = 320 + 130 = 450, Y = 240 + 75 = 315
|
constexpr float ENTRY_OFFSET_MARGIN = 227.5f; // Para offset total de ~340px (ajustado)
|
||||||
constexpr float P2_TARGET_X = 450.0f;
|
|
||||||
constexpr float P2_TARGET_Y = 315.0f;
|
|
||||||
|
|
||||||
// Escala base de les naus (ajusta aquí per fer-les més grans o petites)
|
// ============================================================
|
||||||
constexpr float SHIP_BASE_SCALE = 2.5f; // Multiplicador global (1.0 = mida original)
|
// VALORS DERIVATS (calculats automàticament - NO modificar)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
// Escales d'animació (perspectiva ja incorporada a les formes .shp)
|
// Centre de la pantalla (punt de referència)
|
||||||
constexpr float ENTRY_SCALE_START = 1.5f * SHIP_BASE_SCALE; // Més gran per veure millor
|
constexpr float CENTER_X = Game::WIDTH / 2.0f; // 320.0f
|
||||||
constexpr float FLOATING_SCALE = 1.0f * SHIP_BASE_SCALE; // Mida normal (més grans)
|
constexpr float CENTER_Y = Game::HEIGHT / 2.0f; // 240.0f
|
||||||
|
|
||||||
// Animacions
|
// Posicions target (calculades dinàmicament des dels paràmetres base)
|
||||||
constexpr float ENTRY_DURATION = 2.0f; // Entrada
|
// Nota: std::cos/sin no són constexpr en C++20, però funcionen en runtime
|
||||||
constexpr float ENTRY_OFFSET = 340.0f; // Offset fora de pantalla (considera radi màxim 30px * escala 3.75 + marge)
|
// Les funcions inline són optimitzades pel compilador (zero overhead)
|
||||||
constexpr float EXIT_DURATION = 1.0f; // Sortida (configurable)
|
inline float P1_TARGET_X() {
|
||||||
|
return CENTER_X + CLOCK_RADIUS * std::cos(CLOCK_8_ANGLE);
|
||||||
|
}
|
||||||
|
inline float P1_TARGET_Y() {
|
||||||
|
return CENTER_Y + (Game::HEIGHT / 2.0f) * TARGET_Y_RATIO;
|
||||||
|
}
|
||||||
|
inline float P2_TARGET_X() {
|
||||||
|
return CENTER_X + CLOCK_RADIUS * std::cos(CLOCK_4_ANGLE);
|
||||||
|
}
|
||||||
|
inline float P2_TARGET_Y() {
|
||||||
|
return CENTER_Y + (Game::HEIGHT / 2.0f) * TARGET_Y_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escales d'animació (relatives a SHIP_BASE_SCALE)
|
||||||
|
constexpr float ENTRY_SCALE_START = 1.5f * SHIP_BASE_SCALE; // Entrada: 50% més gran
|
||||||
|
constexpr float FLOATING_SCALE = 1.0f * SHIP_BASE_SCALE; // Flotant: escala base
|
||||||
|
|
||||||
|
// Offset d'entrada (ajustat automàticament a l'escala)
|
||||||
|
// Fórmula: (radi màxim de la nau * escala d'entrada) + marge
|
||||||
|
constexpr float ENTRY_OFFSET = (SHIP_MAX_RADIUS * ENTRY_SCALE_START) + ENTRY_OFFSET_MARGIN;
|
||||||
|
|
||||||
|
// Punt de fuga (centre per a l'animació de sortida)
|
||||||
|
constexpr float VANISHING_POINT_X = CENTER_X; // 320.0f
|
||||||
|
constexpr float VANISHING_POINT_Y = CENTER_Y; // 240.0f
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// ANIMACIONS (durades, oscil·lacions, delays)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Durades d'animació
|
||||||
|
constexpr float ENTRY_DURATION = 2.0f; // Entrada (segons)
|
||||||
|
constexpr float EXIT_DURATION = 1.0f; // Sortida (segons)
|
||||||
|
|
||||||
// Flotació (oscil·lació reduïda i diferenciada per nau)
|
// Flotació (oscil·lació reduïda i diferenciada per nau)
|
||||||
constexpr float FLOAT_AMPLITUDE_X = 4.0f; // Era 6.0f
|
constexpr float FLOAT_AMPLITUDE_X = 4.0f; // Amplitud X (píxels)
|
||||||
constexpr float FLOAT_AMPLITUDE_Y = 2.5f; // Era 4.0f
|
constexpr float FLOAT_AMPLITUDE_Y = 2.5f; // Amplitud Y (píxels)
|
||||||
|
|
||||||
// Freqüències base
|
// Freqüències base
|
||||||
constexpr float FLOAT_FREQUENCY_X_BASE = 0.5f;
|
constexpr float FLOAT_FREQUENCY_X_BASE = 0.5f; // Hz
|
||||||
constexpr float FLOAT_FREQUENCY_Y_BASE = 0.7f;
|
constexpr float FLOAT_FREQUENCY_Y_BASE = 0.7f; // Hz
|
||||||
constexpr float FLOAT_PHASE_OFFSET = 1.57f; // π/2 (90°)
|
constexpr float FLOAT_PHASE_OFFSET = 1.57f; // π/2 (90°)
|
||||||
|
|
||||||
// Delays d'entrada
|
// Delays d'entrada (per a entrada escalonada)
|
||||||
constexpr float P1_ENTRY_DELAY = 0.0f; // P1 entra immediatament
|
constexpr float P1_ENTRY_DELAY = 0.0f; // P1 entra immediatament
|
||||||
constexpr float P2_ENTRY_DELAY = 0.5f; // P2 entra 0.5s després
|
constexpr float P2_ENTRY_DELAY = 0.5f; // P2 entra 0.5s després
|
||||||
|
|
||||||
// Multiplicadors de freqüència per a cada nau (variació sutil ±12%)
|
// Multiplicadors de freqüència per a cada nau (variació sutil ±12%)
|
||||||
constexpr float P1_FREQUENCY_MULTIPLIER = 0.88f; // 12% més lenta
|
constexpr float P1_FREQUENCY_MULTIPLIER = 0.88f; // 12% més lenta
|
||||||
constexpr float P2_FREQUENCY_MULTIPLIER = 1.12f; // 12% més ràpida
|
constexpr float P2_FREQUENCY_MULTIPLIER = 1.12f; // 12% més ràpida
|
||||||
|
|
||||||
// Punt de fuga
|
|
||||||
constexpr float VANISHING_POINT_X = Game::WIDTH / 2.0f; // 320.0f
|
|
||||||
constexpr float VANISHING_POINT_Y = Game::HEIGHT / 2.0f; // 240.0f
|
|
||||||
} // namespace Ships
|
} // namespace Ships
|
||||||
|
|
||||||
|
namespace Layout {
|
||||||
|
// Posicions verticals (anclatges des del TOP de pantalla lògica, 0.0-1.0)
|
||||||
|
constexpr float LOGO_POS = 0.20f; // Logo "ORNI"
|
||||||
|
constexpr float PRESS_START_POS = 0.73f; // "PRESS START TO PLAY"
|
||||||
|
constexpr float COPYRIGHT1_POS = 0.87f; // Primera línia copyright
|
||||||
|
|
||||||
|
// Separacions relatives (proporció respecte Game::HEIGHT = 480px)
|
||||||
|
constexpr float LOGO_LINE_SPACING = 0.02f; // Entre "ORNI" i "ATTACK!" (10px)
|
||||||
|
constexpr float COPYRIGHT_LINE_SPACING = 0.0f; // Entre línies copyright (5px)
|
||||||
|
|
||||||
|
// Factors d'escala
|
||||||
|
constexpr float LOGO_SCALE = 0.6f; // Escala "ORNI ATTACK!"
|
||||||
|
constexpr float PRESS_START_SCALE = 1.0f; // Escala "PRESS START TO PLAY"
|
||||||
|
constexpr float COPYRIGHT_SCALE = 0.5f; // Escala copyright
|
||||||
|
|
||||||
|
// Espaiat entre caràcters (usat per VectorText)
|
||||||
|
constexpr float TEXT_SPACING = 2.0f;
|
||||||
|
} // namespace Layout
|
||||||
} // namespace Title
|
} // namespace Title
|
||||||
|
|
||||||
// Floating score numbers (números flotants de puntuació)
|
// Floating score numbers (números flotants de puntuació)
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include "core/graphics/shape_loader.hpp"
|
#include "core/graphics/shape_loader.hpp"
|
||||||
|
|
||||||
#include "core/resources/resource_helper.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "core/resources/resource_helper.hpp"
|
||||||
|
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
|
|
||||||
// Inicialització de variables estàtiques
|
// Inicialització de variables estàtiques
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ float Starfield::calcular_brightness(const Estrella& estrella) const {
|
|||||||
// distancia_centre: 0.0 (centre, llunyanes) → 1.0 (vora, properes)
|
// distancia_centre: 0.0 (centre, llunyanes) → 1.0 (vora, properes)
|
||||||
float brightness_base = Defaults::Brightness::STARFIELD_MIN +
|
float brightness_base = Defaults::Brightness::STARFIELD_MIN +
|
||||||
(Defaults::Brightness::STARFIELD_MAX - Defaults::Brightness::STARFIELD_MIN) *
|
(Defaults::Brightness::STARFIELD_MAX - Defaults::Brightness::STARFIELD_MIN) *
|
||||||
estrella.distancia_centre;
|
estrella.distancia_centre;
|
||||||
|
|
||||||
// Aplicar multiplicador i limitar a 1.0
|
// Aplicar multiplicador i limitar a 1.0
|
||||||
return std::min(1.0f, brightness_base * multiplicador_brightness_);
|
return std::min(1.0f, brightness_base * multiplicador_brightness_);
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ class Starfield {
|
|||||||
SDL_Renderer* renderer_;
|
SDL_Renderer* renderer_;
|
||||||
|
|
||||||
// Configuració
|
// Configuració
|
||||||
Punt punt_fuga_; // Punt d'origen de les estrelles
|
Punt punt_fuga_; // Punt d'origen de les estrelles
|
||||||
SDL_FRect area_; // Àrea activa
|
SDL_FRect area_; // Àrea activa
|
||||||
float radi_max_; // Distància màxima del centre al límit de pantalla
|
float radi_max_; // Distància màxima del centre al límit de pantalla
|
||||||
int densitat_; // Nombre total d'estrelles
|
int densitat_; // Nombre total d'estrelles
|
||||||
float multiplicador_brightness_{1.0f}; // Multiplicador de brillantor (1.0 = default)
|
float multiplicador_brightness_{1.0f}; // Multiplicador de brillantor (1.0 = default)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -129,8 +129,8 @@ class Input {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr Sint16 AXIS_THRESHOLD = 30000; // Umbral para ejes analógicos
|
static constexpr Sint16 AXIS_THRESHOLD = 30000; // Umbral para ejes analógicos
|
||||||
static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (50% del rango)
|
static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (50% del rango)
|
||||||
static constexpr std::array<Action, 1> BUTTON_INPUTS = {Action::SHOOT}; // Inputs que usan botones
|
static constexpr std::array<Action, 1> BUTTON_INPUTS = {Action::SHOOT}; // Inputs que usan botones
|
||||||
|
|
||||||
// --- Métodos ---
|
// --- Métodos ---
|
||||||
|
|||||||
@@ -4,57 +4,57 @@
|
|||||||
|
|
||||||
// Definición de los mapas
|
// Definición de los mapas
|
||||||
const std::unordered_map<InputAction, std::string> ACTION_TO_STRING = {
|
const std::unordered_map<InputAction, std::string> ACTION_TO_STRING = {
|
||||||
{InputAction::LEFT, "LEFT"},
|
{InputAction::LEFT, "LEFT"},
|
||||||
{InputAction::RIGHT, "RIGHT"},
|
{InputAction::RIGHT, "RIGHT"},
|
||||||
{InputAction::THRUST, "THRUST"},
|
{InputAction::THRUST, "THRUST"},
|
||||||
{InputAction::SHOOT, "SHOOT"},
|
{InputAction::SHOOT, "SHOOT"},
|
||||||
{InputAction::WINDOW_INC_ZOOM, "WINDOW_INC_ZOOM"},
|
{InputAction::WINDOW_INC_ZOOM, "WINDOW_INC_ZOOM"},
|
||||||
{InputAction::WINDOW_DEC_ZOOM, "WINDOW_DEC_ZOOM"},
|
{InputAction::WINDOW_DEC_ZOOM, "WINDOW_DEC_ZOOM"},
|
||||||
{InputAction::TOGGLE_FULLSCREEN, "TOGGLE_FULLSCREEN"},
|
{InputAction::TOGGLE_FULLSCREEN, "TOGGLE_FULLSCREEN"},
|
||||||
{InputAction::TOGGLE_VSYNC, "TOGGLE_VSYNC"},
|
{InputAction::TOGGLE_VSYNC, "TOGGLE_VSYNC"},
|
||||||
{InputAction::EXIT, "EXIT"},
|
{InputAction::EXIT, "EXIT"},
|
||||||
{InputAction::NONE, "NONE"}};
|
{InputAction::NONE, "NONE"}};
|
||||||
|
|
||||||
const std::unordered_map<std::string, InputAction> STRING_TO_ACTION = {
|
const std::unordered_map<std::string, InputAction> STRING_TO_ACTION = {
|
||||||
{"LEFT", InputAction::LEFT},
|
{"LEFT", InputAction::LEFT},
|
||||||
{"RIGHT", InputAction::RIGHT},
|
{"RIGHT", InputAction::RIGHT},
|
||||||
{"THRUST", InputAction::THRUST},
|
{"THRUST", InputAction::THRUST},
|
||||||
{"SHOOT", InputAction::SHOOT},
|
{"SHOOT", InputAction::SHOOT},
|
||||||
{"WINDOW_INC_ZOOM", InputAction::WINDOW_INC_ZOOM},
|
{"WINDOW_INC_ZOOM", InputAction::WINDOW_INC_ZOOM},
|
||||||
{"WINDOW_DEC_ZOOM", InputAction::WINDOW_DEC_ZOOM},
|
{"WINDOW_DEC_ZOOM", InputAction::WINDOW_DEC_ZOOM},
|
||||||
{"TOGGLE_FULLSCREEN", InputAction::TOGGLE_FULLSCREEN},
|
{"TOGGLE_FULLSCREEN", InputAction::TOGGLE_FULLSCREEN},
|
||||||
{"TOGGLE_VSYNC", InputAction::TOGGLE_VSYNC},
|
{"TOGGLE_VSYNC", InputAction::TOGGLE_VSYNC},
|
||||||
{"EXIT", InputAction::EXIT},
|
{"EXIT", InputAction::EXIT},
|
||||||
{"NONE", InputAction::NONE}};
|
{"NONE", InputAction::NONE}};
|
||||||
|
|
||||||
const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING = {
|
const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING = {
|
||||||
{SDL_GAMEPAD_BUTTON_WEST, "WEST"},
|
{SDL_GAMEPAD_BUTTON_WEST, "WEST"},
|
||||||
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"},
|
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"},
|
||||||
{SDL_GAMEPAD_BUTTON_EAST, "EAST"},
|
{SDL_GAMEPAD_BUTTON_EAST, "EAST"},
|
||||||
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"},
|
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"},
|
||||||
{SDL_GAMEPAD_BUTTON_START, "START"},
|
{SDL_GAMEPAD_BUTTON_START, "START"},
|
||||||
{SDL_GAMEPAD_BUTTON_BACK, "BACK"},
|
{SDL_GAMEPAD_BUTTON_BACK, "BACK"},
|
||||||
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"},
|
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"},
|
||||||
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"},
|
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||||
{static_cast<SDL_GamepadButton>(100), "L2_AS_BUTTON"},
|
{static_cast<SDL_GamepadButton>(100), "L2_AS_BUTTON"},
|
||||||
{static_cast<SDL_GamepadButton>(101), "R2_AS_BUTTON"}};
|
{static_cast<SDL_GamepadButton>(101), "R2_AS_BUTTON"}};
|
||||||
|
|
||||||
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
||||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||||
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
||||||
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
||||||
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
||||||
{"START", SDL_GAMEPAD_BUTTON_START},
|
{"START", SDL_GAMEPAD_BUTTON_START},
|
||||||
{"BACK", SDL_GAMEPAD_BUTTON_BACK},
|
{"BACK", SDL_GAMEPAD_BUTTON_BACK},
|
||||||
{"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
{"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
||||||
{"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
{"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
||||||
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||||
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||||
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||||
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||||
{"L2_AS_BUTTON", static_cast<SDL_GamepadButton>(100)},
|
{"L2_AS_BUTTON", static_cast<SDL_GamepadButton>(100)},
|
||||||
{"R2_AS_BUTTON", static_cast<SDL_GamepadButton>(101)}};
|
{"R2_AS_BUTTON", static_cast<SDL_GamepadButton>(101)}};
|
||||||
|
|||||||
@@ -8,23 +8,23 @@
|
|||||||
|
|
||||||
// --- Enums ---
|
// --- Enums ---
|
||||||
enum class InputAction : int { // Acciones de entrada posibles en el juego
|
enum class InputAction : int { // Acciones de entrada posibles en el juego
|
||||||
// Inputs de juego (movimiento y acción)
|
// Inputs de juego (movimiento y acción)
|
||||||
LEFT, // Rotar izquierda
|
LEFT, // Rotar izquierda
|
||||||
RIGHT, // Rotar derecha
|
RIGHT, // Rotar derecha
|
||||||
THRUST, // Acelerar
|
THRUST, // Acelerar
|
||||||
SHOOT, // Disparar
|
SHOOT, // Disparar
|
||||||
START, // Empezar partida
|
START, // Empezar partida
|
||||||
|
|
||||||
// Inputs de sistema (globales)
|
// Inputs de sistema (globales)
|
||||||
WINDOW_INC_ZOOM, // F2
|
WINDOW_INC_ZOOM, // F2
|
||||||
WINDOW_DEC_ZOOM, // F1
|
WINDOW_DEC_ZOOM, // F1
|
||||||
TOGGLE_FULLSCREEN, // F3
|
TOGGLE_FULLSCREEN, // F3
|
||||||
TOGGLE_VSYNC, // F4
|
TOGGLE_VSYNC, // F4
|
||||||
EXIT, // ESC
|
EXIT, // ESC
|
||||||
|
|
||||||
// Input obligatorio
|
// Input obligatorio
|
||||||
NONE,
|
NONE,
|
||||||
SIZE,
|
SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
@@ -36,7 +36,6 @@ extern const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON
|
|||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
// Physical arcade buttons (excludes directional controls LEFT/RIGHT)
|
// Physical arcade buttons (excludes directional controls LEFT/RIGHT)
|
||||||
static constexpr std::array<InputAction, 3> ARCADE_BUTTONS = {
|
static constexpr std::array<InputAction, 3> ARCADE_BUTTONS = {
|
||||||
InputAction::SHOOT,
|
InputAction::SHOOT,
|
||||||
InputAction::THRUST,
|
InputAction::THRUST,
|
||||||
InputAction::START
|
InputAction::START};
|
||||||
};
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
class SDLManager {
|
class SDLManager {
|
||||||
public:
|
public:
|
||||||
SDLManager(); // Constructor per defecte (usa Defaults::)
|
SDLManager(); // Constructor per defecte (usa Defaults::)
|
||||||
SDLManager(int width, int height, bool fullscreen); // Constructor amb configuració
|
SDLManager(int width, int height, bool fullscreen); // Constructor amb configuració
|
||||||
~SDLManager();
|
~SDLManager();
|
||||||
|
|
||||||
// No permetre còpia ni assignació
|
// No permetre còpia ni assignació
|
||||||
@@ -22,11 +22,11 @@ class SDLManager {
|
|||||||
SDLManager& operator=(const SDLManager&) = delete;
|
SDLManager& operator=(const SDLManager&) = delete;
|
||||||
|
|
||||||
// [NUEVO] Gestió de finestra dinàmica
|
// [NUEVO] Gestió de finestra dinàmica
|
||||||
void increaseWindowSize(); // F2: +100px
|
void increaseWindowSize(); // F2: +100px
|
||||||
void decreaseWindowSize(); // F1: -100px
|
void decreaseWindowSize(); // F1: -100px
|
||||||
void toggleFullscreen(); // F3
|
void toggleFullscreen(); // F3
|
||||||
void toggleVSync(); // F4
|
void toggleVSync(); // F4
|
||||||
bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED
|
bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED
|
||||||
|
|
||||||
// Funcions principals (renderitzat)
|
// Funcions principals (renderitzat)
|
||||||
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
||||||
|
|||||||
@@ -14,16 +14,22 @@ namespace Rendering {
|
|||||||
|
|
||||||
// Estructura per rotacions 3D (pitch, yaw, roll)
|
// Estructura per rotacions 3D (pitch, yaw, roll)
|
||||||
struct Rotation3D {
|
struct Rotation3D {
|
||||||
float pitch; // Rotació eix X (cabeceo arriba/baix)
|
float pitch; // Rotació eix X (cabeceo arriba/baix)
|
||||||
float yaw; // Rotació eix Y (guiñada esquerra/dreta)
|
float yaw; // Rotació eix Y (guiñada esquerra/dreta)
|
||||||
float roll; // Rotació eix Z (alabeo lateral)
|
float roll; // Rotació eix Z (alabeo lateral)
|
||||||
|
|
||||||
Rotation3D() : pitch(0.0f), yaw(0.0f), roll(0.0f) {}
|
Rotation3D()
|
||||||
Rotation3D(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
|
: pitch(0.0f),
|
||||||
|
yaw(0.0f),
|
||||||
|
roll(0.0f) {}
|
||||||
|
Rotation3D(float p, float y, float r)
|
||||||
|
: pitch(p),
|
||||||
|
yaw(y),
|
||||||
|
roll(r) {}
|
||||||
|
|
||||||
bool has_rotation() const {
|
bool has_rotation() const {
|
||||||
return pitch != 0.0f || yaw != 0.0f || roll != 0.0f;
|
return pitch != 0.0f || yaw != 0.0f || roll != 0.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Renderitzar forma amb transformacions
|
// Renderitzar forma amb transformacions
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
#include "resource_helper.hpp"
|
#include "resource_helper.hpp"
|
||||||
|
|
||||||
#include "resource_loader.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "resource_loader.hpp"
|
||||||
|
|
||||||
namespace Resource {
|
namespace Resource {
|
||||||
namespace Helper {
|
namespace Helper {
|
||||||
|
|
||||||
|
|||||||
@@ -4,50 +4,50 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "resource_pack.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "resource_pack.hpp"
|
||||||
|
|
||||||
namespace Resource {
|
namespace Resource {
|
||||||
|
|
||||||
// Singleton per gestionar la càrrega de recursos
|
// Singleton per gestionar la càrrega de recursos
|
||||||
class Loader {
|
class Loader {
|
||||||
public:
|
public:
|
||||||
// Singleton
|
// Singleton
|
||||||
static Loader& get();
|
static Loader& get();
|
||||||
|
|
||||||
// Inicialització
|
// Inicialització
|
||||||
bool initialize(const std::string& pack_file, bool enable_fallback);
|
bool initialize(const std::string& pack_file, bool enable_fallback);
|
||||||
|
|
||||||
// Càrrega de recursos
|
// Càrrega de recursos
|
||||||
std::vector<uint8_t> loadResource(const std::string& filename);
|
std::vector<uint8_t> loadResource(const std::string& filename);
|
||||||
bool resourceExists(const std::string& filename);
|
bool resourceExists(const std::string& filename);
|
||||||
|
|
||||||
// Validació
|
// Validació
|
||||||
bool validatePack();
|
bool validatePack();
|
||||||
bool isPackLoaded() const;
|
bool isPackLoaded() const;
|
||||||
|
|
||||||
// Estat
|
// Estat
|
||||||
void setBasePath(const std::string& path);
|
void setBasePath(const std::string& path);
|
||||||
std::string getBasePath() const;
|
std::string getBasePath() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Loader() = default;
|
Loader() = default;
|
||||||
~Loader() = default;
|
~Loader() = default;
|
||||||
|
|
||||||
// No es pot copiar ni moure
|
// No es pot copiar ni moure
|
||||||
Loader(const Loader&) = delete;
|
Loader(const Loader&) = delete;
|
||||||
Loader& operator=(const Loader&) = delete;
|
Loader& operator=(const Loader&) = delete;
|
||||||
|
|
||||||
// Dades
|
// Dades
|
||||||
std::unique_ptr<Pack> pack_;
|
std::unique_ptr<Pack> pack_;
|
||||||
bool fallback_enabled_ = false;
|
bool fallback_enabled_ = false;
|
||||||
std::string base_path_;
|
std::string base_path_;
|
||||||
|
|
||||||
// Funcions auxiliars
|
// Funcions auxiliars
|
||||||
std::vector<uint8_t> loadFromFilesystem(const std::string& filename);
|
std::vector<uint8_t> loadFromFilesystem(const std::string& filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Resource
|
} // namespace Resource
|
||||||
|
|||||||
@@ -13,55 +13,55 @@ namespace Resource {
|
|||||||
|
|
||||||
// Capçalera del fitxer de paquet
|
// Capçalera del fitxer de paquet
|
||||||
struct PackHeader {
|
struct PackHeader {
|
||||||
char magic[4]; // "ORNI"
|
char magic[4]; // "ORNI"
|
||||||
uint32_t version; // Versió del format (1)
|
uint32_t version; // Versió del format (1)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Entrada de recurs dins el paquet
|
// Entrada de recurs dins el paquet
|
||||||
struct ResourceEntry {
|
struct ResourceEntry {
|
||||||
std::string filename; // Nom del recurs (amb barres normals)
|
std::string filename; // Nom del recurs (amb barres normals)
|
||||||
uint64_t offset; // Posició dins el bloc de dades
|
uint64_t offset; // Posició dins el bloc de dades
|
||||||
uint64_t size; // Mida en bytes
|
uint64_t size; // Mida en bytes
|
||||||
uint32_t checksum; // Checksum CRC32 per verificació
|
uint32_t checksum; // Checksum CRC32 per verificació
|
||||||
};
|
};
|
||||||
|
|
||||||
// Classe principal per gestionar paquets de recursos
|
// Classe principal per gestionar paquets de recursos
|
||||||
class Pack {
|
class Pack {
|
||||||
public:
|
public:
|
||||||
Pack() = default;
|
Pack() = default;
|
||||||
~Pack() = default;
|
~Pack() = default;
|
||||||
|
|
||||||
// Afegir fitxers al paquet
|
// Afegir fitxers al paquet
|
||||||
bool addFile(const std::string& filepath, const std::string& pack_name);
|
bool addFile(const std::string& filepath, const std::string& pack_name);
|
||||||
bool addDirectory(const std::string& dir_path, const std::string& base_path = "");
|
bool addDirectory(const std::string& dir_path, const std::string& base_path = "");
|
||||||
|
|
||||||
// Guardar i carregar paquets
|
// Guardar i carregar paquets
|
||||||
bool savePack(const std::string& pack_file);
|
bool savePack(const std::string& pack_file);
|
||||||
bool loadPack(const std::string& pack_file);
|
bool loadPack(const std::string& pack_file);
|
||||||
|
|
||||||
// Accés a recursos
|
// Accés a recursos
|
||||||
std::vector<uint8_t> getResource(const std::string& filename);
|
std::vector<uint8_t> getResource(const std::string& filename);
|
||||||
bool hasResource(const std::string& filename) const;
|
bool hasResource(const std::string& filename) const;
|
||||||
std::vector<std::string> getResourceList() const;
|
std::vector<std::string> getResourceList() const;
|
||||||
|
|
||||||
// Validació
|
// Validació
|
||||||
bool validatePack() const;
|
bool validatePack() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constants
|
// Constants
|
||||||
static constexpr const char* MAGIC_HEADER = "ORNI";
|
static constexpr const char* MAGIC_HEADER = "ORNI";
|
||||||
static constexpr uint32_t VERSION = 1;
|
static constexpr uint32_t VERSION = 1;
|
||||||
static constexpr const char* DEFAULT_ENCRYPT_KEY = "ORNI_RESOURCES_2025";
|
static constexpr const char* DEFAULT_ENCRYPT_KEY = "ORNI_RESOURCES_2025";
|
||||||
|
|
||||||
// Dades del paquet
|
// Dades del paquet
|
||||||
std::unordered_map<std::string, ResourceEntry> resources_;
|
std::unordered_map<std::string, ResourceEntry> resources_;
|
||||||
std::vector<uint8_t> data_;
|
std::vector<uint8_t> data_;
|
||||||
|
|
||||||
// Funcions auxiliars
|
// Funcions auxiliars
|
||||||
std::vector<uint8_t> readFile(const std::string& filepath);
|
std::vector<uint8_t> readFile(const std::string& filepath);
|
||||||
uint32_t calculateChecksum(const std::vector<uint8_t>& data) const;
|
uint32_t calculateChecksum(const std::vector<uint8_t>& data) const;
|
||||||
void encryptData(std::vector<uint8_t>& data, const std::string& key);
|
void encryptData(std::vector<uint8_t>& data, const std::string& key);
|
||||||
void decryptData(std::vector<uint8_t>& data, const std::string& key);
|
void decryptData(std::vector<uint8_t>& data, const std::string& key);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Resource
|
} // namespace Resource
|
||||||
|
|||||||
@@ -10,70 +10,70 @@ namespace GestorEscenes {
|
|||||||
// Context de transició entre escenes
|
// Context de transició entre escenes
|
||||||
// Conté l'escena destinació i opcions específiques per aquella escena
|
// Conté l'escena destinació i opcions específiques per aquella escena
|
||||||
class ContextEscenes {
|
class ContextEscenes {
|
||||||
public:
|
public:
|
||||||
// Tipus d'escena del joc
|
// Tipus d'escena del joc
|
||||||
enum class Escena {
|
enum class Escena {
|
||||||
LOGO, // Pantalla d'inici (logo JAILGAMES)
|
LOGO, // Pantalla d'inici (logo JAILGAMES)
|
||||||
TITOL, // Pantalla de títol amb menú
|
TITOL, // Pantalla de títol amb menú
|
||||||
JOC, // Joc principal (Asteroids)
|
JOC, // Joc principal (Asteroids)
|
||||||
EIXIR // Sortir del programa
|
EIXIR // Sortir del programa
|
||||||
};
|
};
|
||||||
|
|
||||||
// Opcions específiques per a cada escena
|
// Opcions específiques per a cada escena
|
||||||
enum class Opcio {
|
enum class Opcio {
|
||||||
NONE, // Sense opcions especials (comportament per defecte)
|
NONE, // Sense opcions especials (comportament per defecte)
|
||||||
JUMP_TO_TITLE_MAIN, // TITOL: Saltar directament a MAIN (starfield instantani)
|
JUMP_TO_TITLE_MAIN, // TITOL: Saltar directament a MAIN (starfield instantani)
|
||||||
// MODE_DEMO, // JOC: Mode demostració amb IA (futur)
|
// MODE_DEMO, // JOC: Mode demostració amb IA (futur)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructor inicial amb escena LOGO i sense opcions
|
// Constructor inicial amb escena LOGO i sense opcions
|
||||||
ContextEscenes()
|
ContextEscenes()
|
||||||
: escena_desti_(Escena::LOGO),
|
: escena_desti_(Escena::LOGO),
|
||||||
opcio_(Opcio::NONE) {}
|
opcio_(Opcio::NONE) {}
|
||||||
|
|
||||||
// Canviar escena amb opció específica
|
// Canviar escena amb opció específica
|
||||||
void canviar_escena(Escena nova_escena, Opcio opcio = Opcio::NONE) {
|
void canviar_escena(Escena nova_escena, Opcio opcio = Opcio::NONE) {
|
||||||
escena_desti_ = nova_escena;
|
escena_desti_ = nova_escena;
|
||||||
opcio_ = opcio;
|
opcio_ = opcio;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consultar escena destinació
|
// Consultar escena destinació
|
||||||
[[nodiscard]] auto escena_desti() const -> Escena {
|
[[nodiscard]] auto escena_desti() const -> Escena {
|
||||||
return escena_desti_;
|
return escena_desti_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consultar opció actual
|
// Consultar opció actual
|
||||||
[[nodiscard]] auto opcio() const -> Opcio {
|
[[nodiscard]] auto opcio() const -> Opcio {
|
||||||
return opcio_;
|
return opcio_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consumir opció (retorna valor i reseteja a NONE)
|
// Consumir opció (retorna valor i reseteja a NONE)
|
||||||
// Utilitzar quan l'escena processa l'opció
|
// Utilitzar quan l'escena processa l'opció
|
||||||
[[nodiscard]] auto consumir_opcio() -> Opcio {
|
[[nodiscard]] auto consumir_opcio() -> Opcio {
|
||||||
Opcio valor = opcio_;
|
Opcio valor = opcio_;
|
||||||
opcio_ = Opcio::NONE;
|
opcio_ = Opcio::NONE;
|
||||||
return valor;
|
return valor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset opció a NONE (sense retornar valor)
|
// Reset opció a NONE (sense retornar valor)
|
||||||
void reset_opcio() {
|
void reset_opcio() {
|
||||||
opcio_ = Opcio::NONE;
|
opcio_ = Opcio::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configurar partida abans de transicionar a JOC
|
// Configurar partida abans de transicionar a JOC
|
||||||
void set_config_partida(const GameConfig::ConfigPartida& config) {
|
void set_config_partida(const GameConfig::ConfigPartida& config) {
|
||||||
config_partida_ = config;
|
config_partida_ = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtenir configuració de partida (consumit per EscenaJoc)
|
// Obtenir configuració de partida (consumit per EscenaJoc)
|
||||||
[[nodiscard]] const GameConfig::ConfigPartida& get_config_partida() const {
|
[[nodiscard]] const GameConfig::ConfigPartida& get_config_partida() const {
|
||||||
return config_partida_;
|
return config_partida_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Escena escena_desti_; // Escena a la qual transicionar
|
Escena escena_desti_; // Escena a la qual transicionar
|
||||||
Opcio opcio_; // Opció específica per l'escena
|
Opcio opcio_; // Opció específica per l'escena
|
||||||
GameConfig::ConfigPartida config_partida_; // Configuració de partida (jugadors actius, mode)
|
GameConfig::ConfigPartida config_partida_; // Configuració de partida (jugadors actius, mode)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variable global inline per gestionar l'escena actual (backward compatibility)
|
// Variable global inline per gestionar l'escena actual (backward compatibility)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "context_escenes.hpp"
|
||||||
#include "core/audio/audio.hpp"
|
#include "core/audio/audio.hpp"
|
||||||
#include "core/audio/audio_cache.hpp"
|
#include "core/audio/audio_cache.hpp"
|
||||||
#include "core/defaults.hpp"
|
#include "core/defaults.hpp"
|
||||||
@@ -20,7 +21,6 @@
|
|||||||
#include "game/escenes/escena_logo.hpp"
|
#include "game/escenes/escena_logo.hpp"
|
||||||
#include "game/escenes/escena_titol.hpp"
|
#include "game/escenes/escena_titol.hpp"
|
||||||
#include "game/options.hpp"
|
#include "game/options.hpp"
|
||||||
#include "context_escenes.hpp"
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -240,7 +240,7 @@ auto Director::run() -> int {
|
|||||||
// Crear context d'escenes
|
// Crear context d'escenes
|
||||||
ContextEscenes context;
|
ContextEscenes context;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
context.canviar_escena(Escena::JOC);
|
context.canviar_escena(Escena::TITOL);
|
||||||
#else
|
#else
|
||||||
context.canviar_escena(Escena::LOGO);
|
context.canviar_escena(Escena::LOGO);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,40 +12,40 @@ enum class Mode {
|
|||||||
|
|
||||||
// Configuració d'una partida
|
// Configuració d'una partida
|
||||||
struct ConfigPartida {
|
struct ConfigPartida {
|
||||||
bool jugador1_actiu{false}; // És actiu el jugador 1?
|
bool jugador1_actiu{false}; // És actiu el jugador 1?
|
||||||
bool jugador2_actiu{false}; // És actiu el jugador 2?
|
bool jugador2_actiu{false}; // És actiu el jugador 2?
|
||||||
Mode mode{Mode::NORMAL}; // Mode de joc
|
Mode mode{Mode::NORMAL}; // Mode de joc
|
||||||
|
|
||||||
// Mètodes auxiliars
|
// Mètodes auxiliars
|
||||||
|
|
||||||
// Retorna true si només hi ha un jugador actiu
|
// Retorna true si només hi ha un jugador actiu
|
||||||
[[nodiscard]] bool es_un_jugador() const {
|
[[nodiscard]] bool es_un_jugador() const {
|
||||||
return (jugador1_actiu && !jugador2_actiu) ||
|
return (jugador1_actiu && !jugador2_actiu) ||
|
||||||
(!jugador1_actiu && jugador2_actiu);
|
(!jugador1_actiu && jugador2_actiu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retorna true si hi ha dos jugadors actius
|
// Retorna true si hi ha dos jugadors actius
|
||||||
[[nodiscard]] bool son_dos_jugadors() const {
|
[[nodiscard]] bool son_dos_jugadors() const {
|
||||||
return jugador1_actiu && jugador2_actiu;
|
return jugador1_actiu && jugador2_actiu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retorna true si no hi ha cap jugador actiu
|
// Retorna true si no hi ha cap jugador actiu
|
||||||
[[nodiscard]] bool cap_jugador() const {
|
[[nodiscard]] bool cap_jugador() const {
|
||||||
return !jugador1_actiu && !jugador2_actiu;
|
return !jugador1_actiu && !jugador2_actiu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compte de jugadors actius (0, 1 o 2)
|
// Compte de jugadors actius (0, 1 o 2)
|
||||||
[[nodiscard]] uint8_t compte_jugadors() const {
|
[[nodiscard]] uint8_t compte_jugadors() const {
|
||||||
return (jugador1_actiu ? 1 : 0) + (jugador2_actiu ? 1 : 0);
|
return (jugador1_actiu ? 1 : 0) + (jugador2_actiu ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retorna l'ID de l'únic jugador actiu (0 o 1)
|
// Retorna l'ID de l'únic jugador actiu (0 o 1)
|
||||||
// Només vàlid si es_un_jugador() retorna true
|
// Només vàlid si es_un_jugador() retorna true
|
||||||
[[nodiscard]] uint8_t id_unic_jugador() const {
|
[[nodiscard]] uint8_t id_unic_jugador() const {
|
||||||
if (jugador1_actiu && !jugador2_actiu) return 0;
|
if (jugador1_actiu && !jugador2_actiu) return 0;
|
||||||
if (!jugador1_actiu && jugador2_actiu) return 1;
|
if (!jugador1_actiu && jugador2_actiu) return 1;
|
||||||
return 0; // Fallback (cal comprovar es_un_jugador() primer)
|
return 0; // Fallback (cal comprovar es_un_jugador() primer)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GameConfig
|
} // namespace GameConfig
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "context_escenes.hpp"
|
||||||
#include "core/input/input.hpp"
|
#include "core/input/input.hpp"
|
||||||
#include "core/input/mouse.hpp"
|
#include "core/input/mouse.hpp"
|
||||||
#include "core/rendering/sdl_manager.hpp"
|
#include "core/rendering/sdl_manager.hpp"
|
||||||
#include "context_escenes.hpp"
|
|
||||||
|
|
||||||
// Using declarations per simplificar el codi
|
// Using declarations per simplificar el codi
|
||||||
using GestorEscenes::ContextEscenes;
|
using GestorEscenes::ContextEscenes;
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class SDLManager;
|
class SDLManager;
|
||||||
namespace GestorEscenes { class ContextEscenes; }
|
namespace GestorEscenes {
|
||||||
|
class ContextEscenes;
|
||||||
|
}
|
||||||
|
|
||||||
namespace GlobalEvents {
|
namespace GlobalEvents {
|
||||||
// Processa events globals (F1/F2/F3/ESC/QUIT)
|
// Processa events globals (F1/F2/F3/ESC/QUIT)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ struct Debris {
|
|||||||
float acceleracio; // Acceleració negativa (fricció) en px/s²
|
float acceleracio; // Acceleració negativa (fricció) en px/s²
|
||||||
|
|
||||||
// Rotació
|
// Rotació
|
||||||
float angle_rotacio; // Angle de rotació acumulat (radians)
|
float angle_rotacio; // Angle de rotació acumulat (radians)
|
||||||
float velocitat_rot; // Velocitat de rotació de TRAYECTORIA (rad/s)
|
float velocitat_rot; // Velocitat de rotació de TRAYECTORIA (rad/s)
|
||||||
float velocitat_rot_visual; // Velocitat de rotació VISUAL del segment (rad/s)
|
float velocitat_rot_visual; // Velocitat de rotació VISUAL del segment (rad/s)
|
||||||
|
|
||||||
// Estat de vida
|
// Estat de vida
|
||||||
float temps_vida; // Temps transcorregut (segons)
|
float temps_vida; // Temps transcorregut (segons)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
namespace Effects {
|
namespace Effects {
|
||||||
|
|
||||||
GestorPuntuacioFlotant::GestorPuntuacioFlotant(SDL_Renderer* renderer)
|
GestorPuntuacioFlotant::GestorPuntuacioFlotant(SDL_Renderer* renderer)
|
||||||
: renderer_(renderer), text_(renderer) {
|
: renderer_(renderer),
|
||||||
|
text_(renderer) {
|
||||||
// Inicialitzar tots els slots com inactius
|
// Inicialitzar tots els slots com inactius
|
||||||
for (auto& pf : pool_) {
|
for (auto& pf : pool_) {
|
||||||
pf.actiu = false;
|
pf.actiu = false;
|
||||||
@@ -25,7 +26,7 @@ void GestorPuntuacioFlotant::crear(int punts, const Punt& posicio) {
|
|||||||
pf->text = std::to_string(punts);
|
pf->text = std::to_string(punts);
|
||||||
pf->posicio = posicio;
|
pf->posicio = posicio;
|
||||||
pf->velocitat = {Defaults::FloatingScore::VELOCITY_X,
|
pf->velocitat = {Defaults::FloatingScore::VELOCITY_X,
|
||||||
Defaults::FloatingScore::VELOCITY_Y};
|
Defaults::FloatingScore::VELOCITY_Y};
|
||||||
pf->temps_vida = 0.0f;
|
pf->temps_vida = 0.0f;
|
||||||
pf->temps_max = Defaults::FloatingScore::LIFETIME;
|
pf->temps_max = Defaults::FloatingScore::LIFETIME;
|
||||||
pf->brightness = 1.0f;
|
pf->brightness = 1.0f;
|
||||||
|
|||||||
@@ -17,38 +17,38 @@ namespace Effects {
|
|||||||
// Gestor de números de puntuació flotants
|
// Gestor de números de puntuació flotants
|
||||||
// Manté un pool de PuntuacioFlotant i gestiona el seu cicle de vida
|
// Manté un pool de PuntuacioFlotant i gestiona el seu cicle de vida
|
||||||
class GestorPuntuacioFlotant {
|
class GestorPuntuacioFlotant {
|
||||||
public:
|
public:
|
||||||
explicit GestorPuntuacioFlotant(SDL_Renderer* renderer);
|
explicit GestorPuntuacioFlotant(SDL_Renderer* renderer);
|
||||||
|
|
||||||
// Crear número flotant
|
// Crear número flotant
|
||||||
// - punts: valor numèric (100, 150, 200)
|
// - punts: valor numèric (100, 150, 200)
|
||||||
// - posicio: on apareix (normalment centre d'enemic destruït)
|
// - posicio: on apareix (normalment centre d'enemic destruït)
|
||||||
void crear(int punts, const Punt& posicio);
|
void crear(int punts, const Punt& posicio);
|
||||||
|
|
||||||
// Actualitzar tots els números actius
|
// Actualitzar tots els números actius
|
||||||
void actualitzar(float delta_time);
|
void actualitzar(float delta_time);
|
||||||
|
|
||||||
// Dibuixar tots els números actius
|
// Dibuixar tots els números actius
|
||||||
void dibuixar();
|
void dibuixar();
|
||||||
|
|
||||||
// Reiniciar tots (neteja)
|
// Reiniciar tots (neteja)
|
||||||
void reiniciar();
|
void reiniciar();
|
||||||
|
|
||||||
// Obtenir número actius (debug)
|
// Obtenir número actius (debug)
|
||||||
int get_num_actius() const;
|
int get_num_actius() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_Renderer* renderer_;
|
SDL_Renderer* renderer_;
|
||||||
Graphics::VectorText text_; // Sistema de text vectorial
|
Graphics::VectorText text_; // Sistema de text vectorial
|
||||||
|
|
||||||
// Pool de números flotants (màxim concurrent)
|
// Pool de números flotants (màxim concurrent)
|
||||||
// Màxim 15 enemics simultanis = màxim 15 números
|
// Màxim 15 enemics simultanis = màxim 15 números
|
||||||
static constexpr int MAX_PUNTUACIONS =
|
static constexpr int MAX_PUNTUACIONS =
|
||||||
Defaults::FloatingScore::MAX_CONCURRENT;
|
Defaults::FloatingScore::MAX_CONCURRENT;
|
||||||
std::array<PuntuacioFlotant, MAX_PUNTUACIONS> pool_;
|
std::array<PuntuacioFlotant, MAX_PUNTUACIONS> pool_;
|
||||||
|
|
||||||
// Trobar primer slot inactiu
|
// Trobar primer slot inactiu
|
||||||
PuntuacioFlotant* trobar_slot_lliure();
|
PuntuacioFlotant* trobar_slot_lliure();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Effects
|
} // namespace Effects
|
||||||
|
|||||||
@@ -12,22 +12,22 @@ namespace Effects {
|
|||||||
// PuntuacioFlotant: text animat que mostra punts guanyats
|
// PuntuacioFlotant: text animat que mostra punts guanyats
|
||||||
// S'activa quan es destrueix un enemic i s'esvaeix després d'un temps
|
// S'activa quan es destrueix un enemic i s'esvaeix després d'un temps
|
||||||
struct PuntuacioFlotant {
|
struct PuntuacioFlotant {
|
||||||
// Text a mostrar (e.g., "100", "150", "200")
|
// Text a mostrar (e.g., "100", "150", "200")
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
// Posició actual (coordenades mundials)
|
// Posició actual (coordenades mundials)
|
||||||
Punt posicio;
|
Punt posicio;
|
||||||
|
|
||||||
// Animació de moviment
|
// Animació de moviment
|
||||||
Punt velocitat; // px/s (normalment cap amunt: {0.0f, -30.0f})
|
Punt velocitat; // px/s (normalment cap amunt: {0.0f, -30.0f})
|
||||||
|
|
||||||
// Animació de fade
|
// Animació de fade
|
||||||
float temps_vida; // Temps transcorregut (segons)
|
float temps_vida; // Temps transcorregut (segons)
|
||||||
float temps_max; // Temps de vida màxim (segons)
|
float temps_max; // Temps de vida màxim (segons)
|
||||||
float brightness; // Brillantor calculada (0.0-1.0)
|
float brightness; // Brillantor calculada (0.0-1.0)
|
||||||
|
|
||||||
// Estat
|
// Estat
|
||||||
bool actiu;
|
bool actiu;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Effects
|
} // namespace Effects
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Enemic::Enemic(SDL_Renderer* renderer)
|
|||||||
tipus_(TipusEnemic::PENTAGON),
|
tipus_(TipusEnemic::PENTAGON),
|
||||||
tracking_timer_(0.0f),
|
tracking_timer_(0.0f),
|
||||||
ship_position_(nullptr),
|
ship_position_(nullptr),
|
||||||
tracking_strength_(0.5f), // Default tracking strength
|
tracking_strength_(0.5f), // Default tracking strength
|
||||||
timer_invulnerabilitat_(0.0f) { // Start vulnerable
|
timer_invulnerabilitat_(0.0f) { // Start vulnerable
|
||||||
// [NUEVO] Forma es carrega a inicialitzar() segons el tipus
|
// [NUEVO] Forma es carrega a inicialitzar() segons el tipus
|
||||||
// Constructor no carrega forma per permetre tipus diferents
|
// Constructor no carrega forma per permetre tipus diferents
|
||||||
@@ -126,7 +126,7 @@ void Enemic::inicialitzar(TipusEnemic tipus, const Punt* ship_pos) {
|
|||||||
|
|
||||||
// [NEW] Inicialitzar invulnerabilitat
|
// [NEW] Inicialitzar invulnerabilitat
|
||||||
timer_invulnerabilitat_ = Defaults::Enemies::Spawn::INVULNERABILITY_DURATION; // 3.0s
|
timer_invulnerabilitat_ = Defaults::Enemies::Spawn::INVULNERABILITY_DURATION; // 3.0s
|
||||||
brightness_ = Defaults::Enemies::Spawn::INVULNERABILITY_BRIGHTNESS_START; // 0.3f
|
brightness_ = Defaults::Enemies::Spawn::INVULNERABILITY_BRIGHTNESS_START; // 0.3f
|
||||||
|
|
||||||
// Activar
|
// Activar
|
||||||
esta_ = true;
|
esta_ = true;
|
||||||
@@ -144,7 +144,7 @@ void Enemic::actualitzar(float delta_time) {
|
|||||||
|
|
||||||
// [NEW] Update brightness with LERP during invulnerability
|
// [NEW] Update brightness with LERP during invulnerability
|
||||||
float t_inv = timer_invulnerabilitat_ / Defaults::Enemies::Spawn::INVULNERABILITY_DURATION;
|
float t_inv = timer_invulnerabilitat_ / Defaults::Enemies::Spawn::INVULNERABILITY_DURATION;
|
||||||
float t = 1.0f - t_inv; // 0.0 → 1.0
|
float t = 1.0f - t_inv; // 0.0 → 1.0
|
||||||
float smooth_t = t * t * (3.0f - 2.0f * t); // smoothstep
|
float smooth_t = t * t * (3.0f - 2.0f * t); // smoothstep
|
||||||
|
|
||||||
constexpr float START = Defaults::Enemies::Spawn::INVULNERABILITY_BRIGHTNESS_START;
|
constexpr float START = Defaults::Enemies::Spawn::INVULNERABILITY_BRIGHTNESS_START;
|
||||||
|
|||||||
@@ -54,8 +54,7 @@ class Enemic {
|
|||||||
Punt get_velocitat_vector() const {
|
Punt get_velocitat_vector() const {
|
||||||
return {
|
return {
|
||||||
velocitat_ * std::cos(angle_ - Constants::PI / 2.0f),
|
velocitat_ * std::cos(angle_ - Constants::PI / 2.0f),
|
||||||
velocitat_ * std::sin(angle_ - Constants::PI / 2.0f)
|
velocitat_ * std::sin(angle_ - Constants::PI / 2.0f)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set ship position reference for tracking behavior
|
// Set ship position reference for tracking behavior
|
||||||
@@ -68,7 +67,10 @@ class Enemic {
|
|||||||
|
|
||||||
// [NEW] Setters for difficulty multipliers (stage system)
|
// [NEW] Setters for difficulty multipliers (stage system)
|
||||||
void set_velocity(float vel) { velocitat_ = vel; }
|
void set_velocity(float vel) { velocitat_ = vel; }
|
||||||
void set_rotation(float rot) { drotacio_ = rot; animacio_.drotacio_base = rot; }
|
void set_rotation(float rot) {
|
||||||
|
drotacio_ = rot;
|
||||||
|
animacio_.drotacio_base = rot;
|
||||||
|
}
|
||||||
void set_tracking_strength(float strength);
|
void set_tracking_strength(float strength);
|
||||||
|
|
||||||
// [NEW] Invulnerability queries
|
// [NEW] Invulnerability queries
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ void Nau::dibuixar() const {
|
|||||||
if (es_invulnerable()) {
|
if (es_invulnerable()) {
|
||||||
// Calcular ciclo de parpadeo
|
// Calcular ciclo de parpadeo
|
||||||
float blink_cycle = Defaults::Ship::BLINK_VISIBLE_TIME +
|
float blink_cycle = Defaults::Ship::BLINK_VISIBLE_TIME +
|
||||||
Defaults::Ship::BLINK_INVISIBLE_TIME;
|
Defaults::Ship::BLINK_INVISIBLE_TIME;
|
||||||
float time_in_cycle = std::fmod(invulnerable_timer_, blink_cycle);
|
float time_in_cycle = std::fmod(invulnerable_timer_, blink_cycle);
|
||||||
|
|
||||||
// Si estamos en fase invisible, no dibujar
|
// Si estamos en fase invisible, no dibujar
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ class Nau {
|
|||||||
Punt get_velocitat_vector() const {
|
Punt get_velocitat_vector() const {
|
||||||
return {
|
return {
|
||||||
velocitat_ * std::cos(angle_ - Constants::PI / 2.0f),
|
velocitat_ * std::cos(angle_ - Constants::PI / 2.0f),
|
||||||
velocitat_ * std::sin(angle_ - Constants::PI / 2.0f)
|
velocitat_ * std::sin(angle_ - Constants::PI / 2.0f)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
@@ -55,7 +54,7 @@ class Nau {
|
|||||||
float angle_; // Angle d'orientació
|
float angle_; // Angle d'orientació
|
||||||
float velocitat_; // Velocitat (px/s)
|
float velocitat_; // Velocitat (px/s)
|
||||||
bool esta_tocada_;
|
bool esta_tocada_;
|
||||||
float brightness_; // Factor de brillantor (0.0-1.0)
|
float brightness_; // Factor de brillantor (0.0-1.0)
|
||||||
float invulnerable_timer_; // 0.0f = vulnerable, >0.0f = invulnerable
|
float invulnerable_timer_; // 0.0f = vulnerable, >0.0f = invulnerable
|
||||||
|
|
||||||
void aplicar_fisica(float delta_time);
|
void aplicar_fisica(float delta_time);
|
||||||
|
|||||||
@@ -323,22 +323,19 @@ void EscenaJoc::actualitzar(float delta_time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calcular global progress (0.0 al inicio → 1.0 al final)
|
// Calcular global progress (0.0 al inicio → 1.0 al final)
|
||||||
float global_progress = 1.0f - (stage_manager_->get_timer_transicio() /
|
float global_progress = 1.0f - (stage_manager_->get_timer_transicio() / Defaults::Game::INIT_HUD_DURATION);
|
||||||
Defaults::Game::INIT_HUD_DURATION);
|
|
||||||
global_progress = std::min(1.0f, global_progress);
|
global_progress = std::min(1.0f, global_progress);
|
||||||
|
|
||||||
// [NEW] Calcular progress independiente para cada nave
|
// [NEW] Calcular progress independiente para cada nave
|
||||||
float ship1_progress = calcular_progress_rango(
|
float ship1_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
|
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_SHIP1_RATIO_END
|
Defaults::Game::INIT_HUD_SHIP1_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
float ship2_progress = calcular_progress_rango(
|
float ship2_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
|
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_SHIP2_RATIO_END
|
Defaults::Game::INIT_HUD_SHIP2_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
// [MODIFICAT] Animar AMBAS naus con sus progress respectivos
|
// [MODIFICAT] Animar AMBAS naus con sus progress respectivos
|
||||||
if (config_partida_.jugador1_actiu && ship1_progress < 1.0f) {
|
if (config_partida_.jugador1_actiu && ship1_progress < 1.0f) {
|
||||||
@@ -501,26 +498,22 @@ void EscenaJoc::dibuixar() {
|
|||||||
float rect_progress = calcular_progress_rango(
|
float rect_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_RECT_RATIO_INIT,
|
Defaults::Game::INIT_HUD_RECT_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_RECT_RATIO_END
|
Defaults::Game::INIT_HUD_RECT_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
float score_progress = calcular_progress_rango(
|
float score_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_SCORE_RATIO_INIT,
|
Defaults::Game::INIT_HUD_SCORE_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_SCORE_RATIO_END
|
Defaults::Game::INIT_HUD_SCORE_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
float ship1_progress = calcular_progress_rango(
|
float ship1_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
|
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_SHIP1_RATIO_END
|
Defaults::Game::INIT_HUD_SHIP1_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
float ship2_progress = calcular_progress_rango(
|
float ship2_progress = calcular_progress_rango(
|
||||||
global_progress,
|
global_progress,
|
||||||
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
|
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
|
||||||
Defaults::Game::INIT_HUD_SHIP2_RATIO_END
|
Defaults::Game::INIT_HUD_SHIP2_RATIO_END);
|
||||||
);
|
|
||||||
|
|
||||||
// Dibuixar elements animats
|
// Dibuixar elements animats
|
||||||
if (rect_progress > 0.0f) {
|
if (rect_progress > 0.0f) {
|
||||||
@@ -643,15 +636,15 @@ void EscenaJoc::tocado(uint8_t player_id) {
|
|||||||
Punt vel_nau_80 = {vel_nau.x * 0.8f, vel_nau.y * 0.8f};
|
Punt vel_nau_80 = {vel_nau.x * 0.8f, vel_nau.y * 0.8f};
|
||||||
|
|
||||||
debris_manager_.explotar(
|
debris_manager_.explotar(
|
||||||
naus_[player_id].get_forma(), // Ship shape (3 lines)
|
naus_[player_id].get_forma(), // Ship shape (3 lines)
|
||||||
ship_pos, // Center position
|
ship_pos, // Center position
|
||||||
ship_angle, // Ship orientation
|
ship_angle, // Ship orientation
|
||||||
1.0f, // Normal scale
|
1.0f, // Normal scale
|
||||||
Defaults::Physics::Debris::VELOCITAT_BASE, // 80 px/s
|
Defaults::Physics::Debris::VELOCITAT_BASE, // 80 px/s
|
||||||
naus_[player_id].get_brightness(), // Heredar brightness
|
naus_[player_id].get_brightness(), // Heredar brightness
|
||||||
vel_nau_80, // Heredar 80% velocitat
|
vel_nau_80, // Heredar 80% velocitat
|
||||||
0.0f, // Nave: trayectorias rectas (sin drotacio)
|
0.0f, // Nave: trayectorias rectas (sin drotacio)
|
||||||
0.0f // Sin herencia visual (rotación aleatoria)
|
0.0f // Sin herencia visual (rotación aleatoria)
|
||||||
);
|
);
|
||||||
|
|
||||||
Audio::get()->playSound(Defaults::Sound::EXPLOSION, Audio::Group::GAME);
|
Audio::get()->playSound(Defaults::Sound::EXPLOSION, Audio::Group::GAME);
|
||||||
@@ -863,7 +856,7 @@ std::string EscenaJoc::construir_marcador() const {
|
|||||||
// Nivell (2 dígits)
|
// Nivell (2 dígits)
|
||||||
uint8_t stage_num = stage_manager_->get_stage_actual();
|
uint8_t stage_num = stage_manager_->get_stage_actual();
|
||||||
std::string stage_str = (stage_num < 10) ? "0" + std::to_string(stage_num)
|
std::string stage_str = (stage_num < 10) ? "0" + std::to_string(stage_num)
|
||||||
: std::to_string(stage_num);
|
: std::to_string(stage_num);
|
||||||
|
|
||||||
// Puntuació P2 (6 dígits) - mostrar zeros si inactiu
|
// Puntuació P2 (6 dígits) - mostrar zeros si inactiu
|
||||||
std::string score_p2;
|
std::string score_p2;
|
||||||
@@ -946,15 +939,15 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() {
|
|||||||
// 2. Crear explosió de fragments
|
// 2. Crear explosió de fragments
|
||||||
Punt vel_enemic = enemic.get_velocitat_vector();
|
Punt vel_enemic = enemic.get_velocitat_vector();
|
||||||
debris_manager_.explotar(
|
debris_manager_.explotar(
|
||||||
enemic.get_forma(), // Forma vectorial del pentàgon
|
enemic.get_forma(), // Forma vectorial del pentàgon
|
||||||
pos_enemic, // Posició central
|
pos_enemic, // Posició central
|
||||||
0.0f, // Angle (enemic té rotació interna)
|
0.0f, // Angle (enemic té rotació interna)
|
||||||
1.0f, // Escala normal
|
1.0f, // Escala normal
|
||||||
VELOCITAT_EXPLOSIO, // 50 px/s (explosió suau)
|
VELOCITAT_EXPLOSIO, // 50 px/s (explosió suau)
|
||||||
enemic.get_brightness(), // Heredar brightness
|
enemic.get_brightness(), // Heredar brightness
|
||||||
vel_enemic, // Heredar velocitat
|
vel_enemic, // Heredar velocitat
|
||||||
enemic.get_drotacio(), // Heredar velocitat angular (trayectorias curvas)
|
enemic.get_drotacio(), // Heredar velocitat angular (trayectorias curvas)
|
||||||
0.0f // Sin herencia visual (rotación aleatoria)
|
0.0f // Sin herencia visual (rotación aleatoria)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 3. Desactivar bala
|
// 3. Desactivar bala
|
||||||
@@ -1063,8 +1056,8 @@ void EscenaJoc::dibuixar_missatge_stage(const std::string& missatge) {
|
|||||||
|
|
||||||
// Auto-scale if text exceeds max width
|
// Auto-scale if text exceeds max width
|
||||||
float escala = (text_width_at_base <= max_width)
|
float escala = (text_width_at_base <= max_width)
|
||||||
? escala_base
|
? escala_base
|
||||||
: max_width / text_width_at_base;
|
: max_width / text_width_at_base;
|
||||||
|
|
||||||
// Recalculate dimensions with final scale (using FULL message for centering)
|
// Recalculate dimensions with final scale (using FULL message for centering)
|
||||||
float full_text_width = text_.get_text_width(missatge, escala, spacing);
|
float full_text_width = text_.get_text_width(missatge, escala, spacing);
|
||||||
@@ -1099,8 +1092,7 @@ Punt EscenaJoc::obtenir_punt_spawn(uint8_t player_id) const {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
zona.x + zona.w * x_ratio,
|
zona.x + zona.w * x_ratio,
|
||||||
zona.y + zona.h * Defaults::Game::SPAWN_Y_RATIO
|
zona.y + zona.h * Defaults::Game::SPAWN_Y_RATIO};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EscenaJoc::disparar_bala(uint8_t player_id) {
|
void EscenaJoc::disparar_bala(uint8_t player_id) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "../constants.hpp"
|
#include "../constants.hpp"
|
||||||
#include "../effects/debris_manager.hpp"
|
#include "../effects/debris_manager.hpp"
|
||||||
@@ -23,8 +24,6 @@
|
|||||||
#include "core/system/game_config.hpp"
|
#include "core/system/game_config.hpp"
|
||||||
#include "core/types.hpp"
|
#include "core/types.hpp"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Classe principal del joc (escena)
|
// Classe principal del joc (escena)
|
||||||
class EscenaJoc {
|
class EscenaJoc {
|
||||||
public:
|
public:
|
||||||
@@ -57,7 +56,7 @@ class EscenaJoc {
|
|||||||
bool game_over_; // Game over state flag
|
bool game_over_; // Game over state flag
|
||||||
float game_over_timer_; // Countdown timer for auto-return (seconds)
|
float game_over_timer_; // Countdown timer for auto-return (seconds)
|
||||||
// Punt punt_spawn_; // DEPRECATED: usar obtenir_punt_spawn(player_id)
|
// Punt punt_spawn_; // DEPRECATED: usar obtenir_punt_spawn(player_id)
|
||||||
Punt punt_mort_; // Death position (for respawn, legacy)
|
Punt punt_mort_; // Death position (for respawn, legacy)
|
||||||
std::array<int, 2> puntuacio_per_jugador_; // [0]=P1, [1]=P2
|
std::array<int, 2> puntuacio_per_jugador_; // [0]=P1, [1]=P2
|
||||||
|
|
||||||
// Text vectorial
|
// Text vectorial
|
||||||
@@ -72,20 +71,20 @@ class EscenaJoc {
|
|||||||
|
|
||||||
// Funcions privades
|
// Funcions privades
|
||||||
void tocado(uint8_t player_id);
|
void tocado(uint8_t player_id);
|
||||||
void detectar_col·lisions_bales_enemics(); // Col·lisions bala-enemic
|
void detectar_col·lisions_bales_enemics(); // Col·lisions bala-enemic
|
||||||
void detectar_col·lisio_naus_enemics(); // Ship-enemy collision detection (plural)
|
void detectar_col·lisio_naus_enemics(); // Ship-enemy collision detection (plural)
|
||||||
void dibuixar_marges() const; // Dibuixar vores de la zona de joc
|
void dibuixar_marges() const; // Dibuixar vores de la zona de joc
|
||||||
void dibuixar_marcador(); // Dibuixar marcador de puntuació
|
void dibuixar_marcador(); // Dibuixar marcador de puntuació
|
||||||
void disparar_bala(uint8_t player_id); // Shoot bullet from player
|
void disparar_bala(uint8_t player_id); // Shoot bullet from player
|
||||||
Punt obtenir_punt_spawn(uint8_t player_id) const; // Get spawn position for player
|
Punt obtenir_punt_spawn(uint8_t player_id) const; // Get spawn position for player
|
||||||
|
|
||||||
// [NEW] Stage system helpers
|
// [NEW] Stage system helpers
|
||||||
void dibuixar_missatge_stage(const std::string& missatge);
|
void dibuixar_missatge_stage(const std::string& missatge);
|
||||||
|
|
||||||
// [NEW] Funcions d'animació per INIT_HUD
|
// [NEW] Funcions d'animació per INIT_HUD
|
||||||
void dibuixar_marges_animat(float progress) const; // Rectangle amb creixement uniforme
|
void dibuixar_marges_animat(float progress) const; // Rectangle amb creixement uniforme
|
||||||
void dibuixar_marcador_animat(float progress); // Marcador que puja des de baix
|
void dibuixar_marcador_animat(float progress); // Marcador que puja des de baix
|
||||||
Punt calcular_posicio_nau_init_hud(float progress, uint8_t player_id) const; // Posició animada de la nau
|
Punt calcular_posicio_nau_init_hud(float progress, uint8_t player_id) const; // Posició animada de la nau
|
||||||
|
|
||||||
// [NEW] Función helper del sistema de animación INIT_HUD
|
// [NEW] Función helper del sistema de animación INIT_HUD
|
||||||
float calcular_progress_rango(float global_progress, float ratio_init, float ratio_end) const;
|
float calcular_progress_rango(float global_progress, float ratio_init, float ratio_end) const;
|
||||||
|
|||||||
@@ -220,10 +220,8 @@ void EscenaLogo::canviar_estat(EstatAnimacio nou_estat) {
|
|||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 g(rd());
|
std::mt19937 g(rd());
|
||||||
std::shuffle(ordre_explosio_.begin(), ordre_explosio_.end(), g);
|
std::shuffle(ordre_explosio_.begin(), ordre_explosio_.end(), g);
|
||||||
}
|
} else if (nou_estat == EstatAnimacio::POST_EXPLOSION) {
|
||||||
else if (nou_estat == EstatAnimacio::POST_EXPLOSION)
|
Audio::get()->playMusic("title.ogg");
|
||||||
{
|
|
||||||
Audio::get()->playMusic("title.ogg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "[EscenaLogo] Canvi a estat: " << static_cast<int>(nou_estat)
|
std::cout << "[EscenaLogo] Canvi a estat: " << static_cast<int>(nou_estat)
|
||||||
@@ -246,13 +244,13 @@ void EscenaLogo::actualitzar_explosions(float delta_time) {
|
|||||||
const auto& lletra = lletres_[index_actual];
|
const auto& lletra = lletres_[index_actual];
|
||||||
|
|
||||||
debris_manager_->explotar(
|
debris_manager_->explotar(
|
||||||
lletra.forma, // Forma a explotar
|
lletra.forma, // Forma a explotar
|
||||||
lletra.posicio, // Posició
|
lletra.posicio, // Posició
|
||||||
0.0f, // Angle (sense rotació)
|
0.0f, // Angle (sense rotació)
|
||||||
ESCALA_FINAL, // Escala (lletres a escala final)
|
ESCALA_FINAL, // Escala (lletres a escala final)
|
||||||
VELOCITAT_EXPLOSIO, // Velocitat base
|
VELOCITAT_EXPLOSIO, // Velocitat base
|
||||||
1.0f, // Brightness màxim (per defecte)
|
1.0f, // Brightness màxim (per defecte)
|
||||||
{0.0f, 0.0f} // Sense velocitat (per defecte)
|
{0.0f, 0.0f} // Sense velocitat (per defecte)
|
||||||
);
|
);
|
||||||
|
|
||||||
std::cout << "[EscenaLogo] Explota lletra " << lletra_explosio_index_ << "\n";
|
std::cout << "[EscenaLogo] Explota lletra " << lletra_explosio_index_ << "\n";
|
||||||
|
|||||||
@@ -10,18 +10,18 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "game/effects/debris_manager.hpp"
|
|
||||||
#include "core/defaults.hpp"
|
#include "core/defaults.hpp"
|
||||||
#include "core/graphics/shape.hpp"
|
#include "core/graphics/shape.hpp"
|
||||||
#include "core/input/input_types.hpp"
|
#include "core/input/input_types.hpp"
|
||||||
#include "core/rendering/sdl_manager.hpp"
|
#include "core/rendering/sdl_manager.hpp"
|
||||||
#include "core/system/context_escenes.hpp"
|
#include "core/system/context_escenes.hpp"
|
||||||
#include "core/types.hpp"
|
#include "core/types.hpp"
|
||||||
|
#include "game/effects/debris_manager.hpp"
|
||||||
|
|
||||||
class EscenaLogo {
|
class EscenaLogo {
|
||||||
public:
|
public:
|
||||||
explicit EscenaLogo(SDLManager& sdl, GestorEscenes::ContextEscenes& context);
|
explicit EscenaLogo(SDLManager& sdl, GestorEscenes::ContextEscenes& context);
|
||||||
~EscenaLogo(); // Destructor per aturar sons
|
~EscenaLogo(); // Destructor per aturar sons
|
||||||
void executar(); // Bucle principal de l'escena
|
void executar(); // Bucle principal de l'escena
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -140,10 +140,10 @@ void EscenaTitol::inicialitzar_titol() {
|
|||||||
float ancho_sin_escalar = max_x - min_x;
|
float ancho_sin_escalar = max_x - min_x;
|
||||||
float altura_sin_escalar = max_y - min_y;
|
float altura_sin_escalar = max_y - min_y;
|
||||||
|
|
||||||
// Escalar ancho, altura i offset amb ESCALA_TITULO
|
// Escalar ancho, altura i offset amb LOGO_SCALE
|
||||||
float ancho = ancho_sin_escalar * ESCALA_TITULO;
|
float ancho = ancho_sin_escalar * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
float altura = altura_sin_escalar * ESCALA_TITULO;
|
float altura = altura_sin_escalar * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
float offset_centre = (forma->get_centre().x - min_x) * ESCALA_TITULO;
|
float offset_centre = (forma->get_centre().x - min_x) * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
|
|
||||||
lletres_orni_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
lletres_orni_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ void EscenaTitol::inicialitzar_titol() {
|
|||||||
|
|
||||||
for (auto& lletra : lletres_orni_) {
|
for (auto& lletra : lletres_orni_) {
|
||||||
lletra.posicio.x = x_actual + lletra.offset_centre;
|
lletra.posicio.x = x_actual + lletra.offset_centre;
|
||||||
lletra.posicio.y = Y_ORNI;
|
lletra.posicio.y = Defaults::Game::HEIGHT * Defaults::Title::Layout::LOGO_POS;
|
||||||
x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES;
|
x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +169,9 @@ void EscenaTitol::inicialitzar_titol() {
|
|||||||
// === Calcular posició Y dinàmica per "ATTACK!" ===
|
// === Calcular posició Y dinàmica per "ATTACK!" ===
|
||||||
// Totes les lletres ORNI tenen la mateixa altura, utilitzem la primera
|
// Totes les lletres ORNI tenen la mateixa altura, utilitzem la primera
|
||||||
float altura_orni = lletres_orni_.empty() ? 50.0f : lletres_orni_[0].altura;
|
float altura_orni = lletres_orni_.empty() ? 50.0f : lletres_orni_[0].altura;
|
||||||
y_attack_dinamica_ = Y_ORNI + altura_orni + SEPARACION_LINEAS;
|
float y_orni = Defaults::Game::HEIGHT * Defaults::Title::Layout::LOGO_POS;
|
||||||
|
float separacion_lineas = Defaults::Game::HEIGHT * Defaults::Title::Layout::LOGO_LINE_SPACING;
|
||||||
|
y_attack_dinamica_ = y_orni + altura_orni + separacion_lineas;
|
||||||
|
|
||||||
std::cout << "[EscenaTitol] Altura ORNI: " << altura_orni
|
std::cout << "[EscenaTitol] Altura ORNI: " << altura_orni
|
||||||
<< " px, Y_ATTACK dinàmica: " << y_attack_dinamica_ << " px\n";
|
<< " px, Y_ATTACK dinàmica: " << y_attack_dinamica_ << " px\n";
|
||||||
@@ -212,10 +214,10 @@ void EscenaTitol::inicialitzar_titol() {
|
|||||||
float ancho_sin_escalar = max_x - min_x;
|
float ancho_sin_escalar = max_x - min_x;
|
||||||
float altura_sin_escalar = max_y - min_y;
|
float altura_sin_escalar = max_y - min_y;
|
||||||
|
|
||||||
// Escalar ancho, altura i offset amb ESCALA_TITULO
|
// Escalar ancho, altura i offset amb LOGO_SCALE
|
||||||
float ancho = ancho_sin_escalar * ESCALA_TITULO;
|
float ancho = ancho_sin_escalar * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
float altura = altura_sin_escalar * ESCALA_TITULO;
|
float altura = altura_sin_escalar * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
float offset_centre = (forma->get_centre().x - min_x) * ESCALA_TITULO;
|
float offset_centre = (forma->get_centre().x - min_x) * Defaults::Title::Layout::LOGO_SCALE;
|
||||||
|
|
||||||
lletres_attack_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
lletres_attack_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
||||||
|
|
||||||
@@ -326,9 +328,9 @@ void EscenaTitol::actualitzar(float delta_time) {
|
|||||||
// Actualitzar naus (quan visibles)
|
// Actualitzar naus (quan visibles)
|
||||||
if (ship_animator_ &&
|
if (ship_animator_ &&
|
||||||
(estat_actual_ == EstatTitol::STARFIELD_FADE_IN ||
|
(estat_actual_ == EstatTitol::STARFIELD_FADE_IN ||
|
||||||
estat_actual_ == EstatTitol::STARFIELD ||
|
estat_actual_ == EstatTitol::STARFIELD ||
|
||||||
estat_actual_ == EstatTitol::MAIN ||
|
estat_actual_ == EstatTitol::MAIN ||
|
||||||
estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) {
|
estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) {
|
||||||
ship_animator_->actualitzar(delta_time);
|
ship_animator_->actualitzar(delta_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +348,7 @@ void EscenaTitol::actualitzar(float delta_time) {
|
|||||||
// Transició a STARFIELD quan el fade es completa
|
// Transició a STARFIELD quan el fade es completa
|
||||||
if (temps_acumulat_ >= DURACIO_FADE_IN) {
|
if (temps_acumulat_ >= DURACIO_FADE_IN) {
|
||||||
estat_actual_ = EstatTitol::STARFIELD;
|
estat_actual_ = EstatTitol::STARFIELD;
|
||||||
temps_acumulat_ = 0.0f; // Reset timer per al següent estat
|
temps_acumulat_ = 0.0f; // Reset timer per al següent estat
|
||||||
starfield_->set_brightness(BRIGHTNESS_STARFIELD); // Assegurar valor final
|
starfield_->set_brightness(BRIGHTNESS_STARFIELD); // Assegurar valor final
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -538,9 +540,9 @@ void EscenaTitol::dibuixar() {
|
|||||||
// Dibuixar naus (després starfield, abans logo)
|
// Dibuixar naus (després starfield, abans logo)
|
||||||
if (ship_animator_ &&
|
if (ship_animator_ &&
|
||||||
(estat_actual_ == EstatTitol::STARFIELD_FADE_IN ||
|
(estat_actual_ == EstatTitol::STARFIELD_FADE_IN ||
|
||||||
estat_actual_ == EstatTitol::STARFIELD ||
|
estat_actual_ == EstatTitol::STARFIELD ||
|
||||||
estat_actual_ == EstatTitol::MAIN ||
|
estat_actual_ == EstatTitol::MAIN ||
|
||||||
estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) {
|
estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) {
|
||||||
ship_animator_->dibuixar();
|
ship_animator_->dibuixar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,7 +582,7 @@ void EscenaTitol::dibuixar() {
|
|||||||
lletres_orni_[i].forma,
|
lletres_orni_[i].forma,
|
||||||
pos_shadow,
|
pos_shadow,
|
||||||
0.0f,
|
0.0f,
|
||||||
ESCALA_TITULO,
|
Defaults::Title::Layout::LOGO_SCALE,
|
||||||
true,
|
true,
|
||||||
1.0f, // progress = 1.0 (totalment visible)
|
1.0f, // progress = 1.0 (totalment visible)
|
||||||
SHADOW_BRIGHTNESS // brightness = 0.4 (brillantor reduïda)
|
SHADOW_BRIGHTNESS // brightness = 0.4 (brillantor reduïda)
|
||||||
@@ -598,7 +600,7 @@ void EscenaTitol::dibuixar() {
|
|||||||
lletres_attack_[i].forma,
|
lletres_attack_[i].forma,
|
||||||
pos_shadow,
|
pos_shadow,
|
||||||
0.0f,
|
0.0f,
|
||||||
ESCALA_TITULO,
|
Defaults::Title::Layout::LOGO_SCALE,
|
||||||
true,
|
true,
|
||||||
1.0f, // progress = 1.0 (totalment visible)
|
1.0f, // progress = 1.0 (totalment visible)
|
||||||
SHADOW_BRIGHTNESS);
|
SHADOW_BRIGHTNESS);
|
||||||
@@ -614,7 +616,7 @@ void EscenaTitol::dibuixar() {
|
|||||||
lletra.forma,
|
lletra.forma,
|
||||||
lletra.posicio,
|
lletra.posicio,
|
||||||
0.0f,
|
0.0f,
|
||||||
ESCALA_TITULO,
|
Defaults::Title::Layout::LOGO_SCALE,
|
||||||
true,
|
true,
|
||||||
1.0f // Brillantor completa
|
1.0f // Brillantor completa
|
||||||
);
|
);
|
||||||
@@ -627,7 +629,7 @@ void EscenaTitol::dibuixar() {
|
|||||||
lletra.forma,
|
lletra.forma,
|
||||||
lletra.posicio,
|
lletra.posicio,
|
||||||
0.0f,
|
0.0f,
|
||||||
ESCALA_TITULO,
|
Defaults::Title::Layout::LOGO_SCALE,
|
||||||
true,
|
true,
|
||||||
1.0f // Brillantor completa
|
1.0f // Brillantor completa
|
||||||
);
|
);
|
||||||
@@ -637,7 +639,7 @@ void EscenaTitol::dibuixar() {
|
|||||||
// En estat MAIN: sempre visible
|
// En estat MAIN: sempre visible
|
||||||
// En estat TRANSITION: parpellejant (blink amb sinusoide)
|
// En estat TRANSITION: parpellejant (blink amb sinusoide)
|
||||||
|
|
||||||
const float spacing = 2.0f; // Espai entre caràcters (usat també per copyright)
|
const float spacing = Defaults::Title::Layout::TEXT_SPACING;
|
||||||
|
|
||||||
bool mostrar_text = true;
|
bool mostrar_text = true;
|
||||||
if (estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE) {
|
if (estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE) {
|
||||||
@@ -648,34 +650,46 @@ void EscenaTitol::dibuixar() {
|
|||||||
|
|
||||||
if (mostrar_text) {
|
if (mostrar_text) {
|
||||||
const std::string main_text = "PRESS START TO PLAY";
|
const std::string main_text = "PRESS START TO PLAY";
|
||||||
const float escala_main = 1.0f;
|
const float escala_main = Defaults::Title::Layout::PRESS_START_SCALE;
|
||||||
|
|
||||||
float text_width = text_.get_text_width(main_text, escala_main, spacing);
|
float text_width = text_.get_text_width(main_text, escala_main, spacing);
|
||||||
|
|
||||||
float x_center = (Defaults::Game::WIDTH - text_width) / 2.0f;
|
float x_center = (Defaults::Game::WIDTH - text_width) / 2.0f;
|
||||||
float altura_attack = lletres_attack_.empty() ? 50.0f : lletres_attack_[0].altura;
|
float y_center = Defaults::Game::HEIGHT * Defaults::Title::Layout::PRESS_START_POS;
|
||||||
float y_center = y_attack_dinamica_ + altura_attack + 70.0f;
|
|
||||||
|
|
||||||
text_.render(main_text, Punt{x_center, y_center}, escala_main, spacing);
|
text_.render(main_text, Punt{x_center, y_center}, escala_main, spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Copyright a la part inferior (centrat horitzontalment) ===
|
// === Copyright a la part inferior (centrat horitzontalment, dues línies) ===
|
||||||
// Convert to uppercase since VectorText only supports A-Z
|
const float escala_copy = Defaults::Title::Layout::COPYRIGHT_SCALE;
|
||||||
std::string copyright = Project::COPYRIGHT;
|
const float copy_height = text_.get_text_height(escala_copy);
|
||||||
for (char& c : copyright) {
|
const float line_spacing = Defaults::Game::HEIGHT * Defaults::Title::Layout::COPYRIGHT_LINE_SPACING;
|
||||||
if (c >= 'a' && c <= 'z') {
|
|
||||||
c = c - 32; // Convert to uppercase
|
// Línea 1: Original (© 1999 Visente i Sergi)
|
||||||
}
|
std::string copyright_original = Project::COPYRIGHT_ORIGINAL;
|
||||||
|
for (char& c : copyright_original) {
|
||||||
|
if (c >= 'a' && c <= 'z') c = c - 32; // Uppercase
|
||||||
}
|
}
|
||||||
const float escala_copy = 0.6f;
|
|
||||||
|
|
||||||
float copy_width = text_.get_text_width(copyright, escala_copy, spacing);
|
// Línea 2: Port (© 2025 jaildesigner)
|
||||||
float copy_height = text_.get_text_height(escala_copy);
|
std::string copyright_port = Project::COPYRIGHT_PORT;
|
||||||
|
for (char& c : copyright_port) {
|
||||||
|
if (c >= 'a' && c <= 'z') c = c - 32; // Uppercase
|
||||||
|
}
|
||||||
|
|
||||||
float x_copy = (Defaults::Game::WIDTH - copy_width) / 2.0f;
|
// Calcular posicions (anclatge des del top + separació)
|
||||||
float y_copy = Defaults::Game::HEIGHT - copy_height - 20.0f; // 20px des del fons
|
float y_line1 = Defaults::Game::HEIGHT * Defaults::Title::Layout::COPYRIGHT1_POS;
|
||||||
|
float y_line2 = y_line1 + copy_height + line_spacing; // Línea 2 debajo de línea 1
|
||||||
|
|
||||||
text_.render(copyright, Punt{x_copy, y_copy}, escala_copy, spacing);
|
// Renderitzar línea 1 (original)
|
||||||
|
float width_line1 = text_.get_text_width(copyright_original, escala_copy, spacing);
|
||||||
|
float x_line1 = (Defaults::Game::WIDTH - width_line1) / 2.0f;
|
||||||
|
text_.render(copyright_original, Punt{x_line1, y_line1}, escala_copy, spacing);
|
||||||
|
|
||||||
|
// Renderitzar línea 2 (port)
|
||||||
|
float width_line2 = text_.get_text_width(copyright_port, escala_copy, spacing);
|
||||||
|
float x_line2 = (Defaults::Game::WIDTH - width_line2) / 2.0f;
|
||||||
|
text_.render(copyright_port, Punt{x_line2, y_line2}, escala_copy, spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,7 @@
|
|||||||
|
|
||||||
// Botones para INICIAR PARTIDA desde MAIN (solo START)
|
// Botones para INICIAR PARTIDA desde MAIN (solo START)
|
||||||
static constexpr std::array<InputAction, 1> START_GAME_BUTTONS = {
|
static constexpr std::array<InputAction, 1> START_GAME_BUTTONS = {
|
||||||
InputAction::START
|
InputAction::START};
|
||||||
};
|
|
||||||
|
|
||||||
class EscenaTitol {
|
class EscenaTitol {
|
||||||
public:
|
public:
|
||||||
@@ -53,12 +52,12 @@ class EscenaTitol {
|
|||||||
|
|
||||||
SDLManager& sdl_;
|
SDLManager& sdl_;
|
||||||
GestorEscenes::ContextEscenes& context_;
|
GestorEscenes::ContextEscenes& context_;
|
||||||
GameConfig::ConfigPartida config_partida_; // Configuració de jugadors actius
|
GameConfig::ConfigPartida config_partida_; // Configuració de jugadors actius
|
||||||
Graphics::VectorText text_; // Sistema de text vectorial
|
Graphics::VectorText text_; // Sistema de text vectorial
|
||||||
std::unique_ptr<Graphics::Starfield> starfield_; // Camp d'estrelles de fons
|
std::unique_ptr<Graphics::Starfield> starfield_; // Camp d'estrelles de fons
|
||||||
std::unique_ptr<Title::ShipAnimator> ship_animator_; // Naus 3D flotants
|
std::unique_ptr<Title::ShipAnimator> ship_animator_; // Naus 3D flotants
|
||||||
EstatTitol estat_actual_; // Estat actual de la màquina
|
EstatTitol estat_actual_; // Estat actual de la màquina
|
||||||
float temps_acumulat_; // Temps acumulat per l'estat INIT
|
float temps_acumulat_; // Temps acumulat per l'estat INIT
|
||||||
|
|
||||||
// Lletres del títol "ORNI ATTACK!"
|
// Lletres del títol "ORNI ATTACK!"
|
||||||
std::vector<LetraLogo> lletres_orni_; // Lletres de "ORNI" (línia 1)
|
std::vector<LetraLogo> lletres_orni_; // Lletres de "ORNI" (línia 1)
|
||||||
@@ -80,10 +79,7 @@ class EscenaTitol {
|
|||||||
static constexpr float DURACIO_FADE_IN = 3.0f; // Duració del fade-in del starfield (1.5 segons)
|
static constexpr float DURACIO_FADE_IN = 3.0f; // Duració del fade-in del starfield (1.5 segons)
|
||||||
static constexpr float DURACIO_INIT = 4.0f; // Duració de l'estat INIT (2 segons)
|
static constexpr float DURACIO_INIT = 4.0f; // Duració de l'estat INIT (2 segons)
|
||||||
static constexpr float DURACIO_TRANSITION = 2.5f; // Duració de la transició (1.5 segons)
|
static constexpr float DURACIO_TRANSITION = 2.5f; // Duració de la transició (1.5 segons)
|
||||||
static constexpr float ESCALA_TITULO = 0.6f; // Escala per les lletres del títol (50%)
|
|
||||||
static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espai entre lletres
|
static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espai entre lletres
|
||||||
static constexpr float Y_ORNI = 150.0f; // Posició Y de "ORNI"
|
|
||||||
static constexpr float SEPARACION_LINEAS = 10.0f; // Separació entre "ORNI" i "ATTACK!" (0.0f = pegades)
|
|
||||||
static constexpr float BLINK_FREQUENCY = 3.0f; // Freqüència de parpelleig (3 Hz)
|
static constexpr float BLINK_FREQUENCY = 3.0f; // Freqüència de parpelleig (3 Hz)
|
||||||
static constexpr float DURACIO_BLACK_SCREEN = 2.0f; // Duració pantalla negra (2 segons)
|
static constexpr float DURACIO_BLACK_SCREEN = 2.0f; // Duració pantalla negra (2 segons)
|
||||||
static constexpr int MUSIC_FADE = 1500; // Duracio del fade de la musica del titol al començar a jugar
|
static constexpr int MUSIC_FADE = 1500; // Duracio del fade de la musica del titol al començar a jugar
|
||||||
|
|||||||
@@ -15,107 +15,169 @@ namespace Options {
|
|||||||
|
|
||||||
// Mapa de SDL_Scancode a string
|
// Mapa de SDL_Scancode a string
|
||||||
static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
||||||
{SDL_SCANCODE_A, "A"}, {SDL_SCANCODE_B, "B"}, {SDL_SCANCODE_C, "C"}, {SDL_SCANCODE_D, "D"},
|
{SDL_SCANCODE_A, "A"},
|
||||||
{SDL_SCANCODE_E, "E"}, {SDL_SCANCODE_F, "F"}, {SDL_SCANCODE_G, "G"}, {SDL_SCANCODE_H, "H"},
|
{SDL_SCANCODE_B, "B"},
|
||||||
{SDL_SCANCODE_I, "I"}, {SDL_SCANCODE_J, "J"}, {SDL_SCANCODE_K, "K"}, {SDL_SCANCODE_L, "L"},
|
{SDL_SCANCODE_C, "C"},
|
||||||
{SDL_SCANCODE_M, "M"}, {SDL_SCANCODE_N, "N"}, {SDL_SCANCODE_O, "O"}, {SDL_SCANCODE_P, "P"},
|
{SDL_SCANCODE_D, "D"},
|
||||||
{SDL_SCANCODE_Q, "Q"}, {SDL_SCANCODE_R, "R"}, {SDL_SCANCODE_S, "S"}, {SDL_SCANCODE_T, "T"},
|
{SDL_SCANCODE_E, "E"},
|
||||||
{SDL_SCANCODE_U, "U"}, {SDL_SCANCODE_V, "V"}, {SDL_SCANCODE_W, "W"}, {SDL_SCANCODE_X, "X"},
|
{SDL_SCANCODE_F, "F"},
|
||||||
{SDL_SCANCODE_Y, "Y"}, {SDL_SCANCODE_Z, "Z"},
|
{SDL_SCANCODE_G, "G"},
|
||||||
{SDL_SCANCODE_1, "1"}, {SDL_SCANCODE_2, "2"}, {SDL_SCANCODE_3, "3"}, {SDL_SCANCODE_4, "4"},
|
{SDL_SCANCODE_H, "H"},
|
||||||
{SDL_SCANCODE_5, "5"}, {SDL_SCANCODE_6, "6"}, {SDL_SCANCODE_7, "7"}, {SDL_SCANCODE_8, "8"},
|
{SDL_SCANCODE_I, "I"},
|
||||||
{SDL_SCANCODE_9, "9"}, {SDL_SCANCODE_0, "0"},
|
{SDL_SCANCODE_J, "J"},
|
||||||
{SDL_SCANCODE_RETURN, "RETURN"}, {SDL_SCANCODE_ESCAPE, "ESCAPE"},
|
{SDL_SCANCODE_K, "K"},
|
||||||
{SDL_SCANCODE_BACKSPACE, "BACKSPACE"}, {SDL_SCANCODE_TAB, "TAB"},
|
{SDL_SCANCODE_L, "L"},
|
||||||
{SDL_SCANCODE_SPACE, "SPACE"},
|
{SDL_SCANCODE_M, "M"},
|
||||||
{SDL_SCANCODE_UP, "UP"}, {SDL_SCANCODE_DOWN, "DOWN"},
|
{SDL_SCANCODE_N, "N"},
|
||||||
{SDL_SCANCODE_LEFT, "LEFT"}, {SDL_SCANCODE_RIGHT, "RIGHT"},
|
{SDL_SCANCODE_O, "O"},
|
||||||
{SDL_SCANCODE_LSHIFT, "LSHIFT"}, {SDL_SCANCODE_RSHIFT, "RSHIFT"},
|
{SDL_SCANCODE_P, "P"},
|
||||||
{SDL_SCANCODE_LCTRL, "LCTRL"}, {SDL_SCANCODE_RCTRL, "RCTRL"},
|
{SDL_SCANCODE_Q, "Q"},
|
||||||
{SDL_SCANCODE_LALT, "LALT"}, {SDL_SCANCODE_RALT, "RALT"}
|
{SDL_SCANCODE_R, "R"},
|
||||||
};
|
{SDL_SCANCODE_S, "S"},
|
||||||
|
{SDL_SCANCODE_T, "T"},
|
||||||
|
{SDL_SCANCODE_U, "U"},
|
||||||
|
{SDL_SCANCODE_V, "V"},
|
||||||
|
{SDL_SCANCODE_W, "W"},
|
||||||
|
{SDL_SCANCODE_X, "X"},
|
||||||
|
{SDL_SCANCODE_Y, "Y"},
|
||||||
|
{SDL_SCANCODE_Z, "Z"},
|
||||||
|
{SDL_SCANCODE_1, "1"},
|
||||||
|
{SDL_SCANCODE_2, "2"},
|
||||||
|
{SDL_SCANCODE_3, "3"},
|
||||||
|
{SDL_SCANCODE_4, "4"},
|
||||||
|
{SDL_SCANCODE_5, "5"},
|
||||||
|
{SDL_SCANCODE_6, "6"},
|
||||||
|
{SDL_SCANCODE_7, "7"},
|
||||||
|
{SDL_SCANCODE_8, "8"},
|
||||||
|
{SDL_SCANCODE_9, "9"},
|
||||||
|
{SDL_SCANCODE_0, "0"},
|
||||||
|
{SDL_SCANCODE_RETURN, "RETURN"},
|
||||||
|
{SDL_SCANCODE_ESCAPE, "ESCAPE"},
|
||||||
|
{SDL_SCANCODE_BACKSPACE, "BACKSPACE"},
|
||||||
|
{SDL_SCANCODE_TAB, "TAB"},
|
||||||
|
{SDL_SCANCODE_SPACE, "SPACE"},
|
||||||
|
{SDL_SCANCODE_UP, "UP"},
|
||||||
|
{SDL_SCANCODE_DOWN, "DOWN"},
|
||||||
|
{SDL_SCANCODE_LEFT, "LEFT"},
|
||||||
|
{SDL_SCANCODE_RIGHT, "RIGHT"},
|
||||||
|
{SDL_SCANCODE_LSHIFT, "LSHIFT"},
|
||||||
|
{SDL_SCANCODE_RSHIFT, "RSHIFT"},
|
||||||
|
{SDL_SCANCODE_LCTRL, "LCTRL"},
|
||||||
|
{SDL_SCANCODE_RCTRL, "RCTRL"},
|
||||||
|
{SDL_SCANCODE_LALT, "LALT"},
|
||||||
|
{SDL_SCANCODE_RALT, "RALT"}};
|
||||||
|
|
||||||
// Mapa invers: string a SDL_Scancode
|
// Mapa invers: string a SDL_Scancode
|
||||||
static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
||||||
{"A", SDL_SCANCODE_A}, {"B", SDL_SCANCODE_B}, {"C", SDL_SCANCODE_C}, {"D", SDL_SCANCODE_D},
|
{"A", SDL_SCANCODE_A},
|
||||||
{"E", SDL_SCANCODE_E}, {"F", SDL_SCANCODE_F}, {"G", SDL_SCANCODE_G}, {"H", SDL_SCANCODE_H},
|
{"B", SDL_SCANCODE_B},
|
||||||
{"I", SDL_SCANCODE_I}, {"J", SDL_SCANCODE_J}, {"K", SDL_SCANCODE_K}, {"L", SDL_SCANCODE_L},
|
{"C", SDL_SCANCODE_C},
|
||||||
{"M", SDL_SCANCODE_M}, {"N", SDL_SCANCODE_N}, {"O", SDL_SCANCODE_O}, {"P", SDL_SCANCODE_P},
|
{"D", SDL_SCANCODE_D},
|
||||||
{"Q", SDL_SCANCODE_Q}, {"R", SDL_SCANCODE_R}, {"S", SDL_SCANCODE_S}, {"T", SDL_SCANCODE_T},
|
{"E", SDL_SCANCODE_E},
|
||||||
{"U", SDL_SCANCODE_U}, {"V", SDL_SCANCODE_V}, {"W", SDL_SCANCODE_W}, {"X", SDL_SCANCODE_X},
|
{"F", SDL_SCANCODE_F},
|
||||||
{"Y", SDL_SCANCODE_Y}, {"Z", SDL_SCANCODE_Z},
|
{"G", SDL_SCANCODE_G},
|
||||||
{"1", SDL_SCANCODE_1}, {"2", SDL_SCANCODE_2}, {"3", SDL_SCANCODE_3}, {"4", SDL_SCANCODE_4},
|
{"H", SDL_SCANCODE_H},
|
||||||
{"5", SDL_SCANCODE_5}, {"6", SDL_SCANCODE_6}, {"7", SDL_SCANCODE_7}, {"8", SDL_SCANCODE_8},
|
{"I", SDL_SCANCODE_I},
|
||||||
{"9", SDL_SCANCODE_9}, {"0", SDL_SCANCODE_0},
|
{"J", SDL_SCANCODE_J},
|
||||||
{"RETURN", SDL_SCANCODE_RETURN}, {"ESCAPE", SDL_SCANCODE_ESCAPE},
|
{"K", SDL_SCANCODE_K},
|
||||||
{"BACKSPACE", SDL_SCANCODE_BACKSPACE}, {"TAB", SDL_SCANCODE_TAB},
|
{"L", SDL_SCANCODE_L},
|
||||||
{"SPACE", SDL_SCANCODE_SPACE},
|
{"M", SDL_SCANCODE_M},
|
||||||
{"UP", SDL_SCANCODE_UP}, {"DOWN", SDL_SCANCODE_DOWN},
|
{"N", SDL_SCANCODE_N},
|
||||||
{"LEFT", SDL_SCANCODE_LEFT}, {"RIGHT", SDL_SCANCODE_RIGHT},
|
{"O", SDL_SCANCODE_O},
|
||||||
{"LSHIFT", SDL_SCANCODE_LSHIFT}, {"RSHIFT", SDL_SCANCODE_RSHIFT},
|
{"P", SDL_SCANCODE_P},
|
||||||
{"LCTRL", SDL_SCANCODE_LCTRL}, {"RCTRL", SDL_SCANCODE_RCTRL},
|
{"Q", SDL_SCANCODE_Q},
|
||||||
{"LALT", SDL_SCANCODE_LALT}, {"RALT", SDL_SCANCODE_RALT}
|
{"R", SDL_SCANCODE_R},
|
||||||
};
|
{"S", SDL_SCANCODE_S},
|
||||||
|
{"T", SDL_SCANCODE_T},
|
||||||
|
{"U", SDL_SCANCODE_U},
|
||||||
|
{"V", SDL_SCANCODE_V},
|
||||||
|
{"W", SDL_SCANCODE_W},
|
||||||
|
{"X", SDL_SCANCODE_X},
|
||||||
|
{"Y", SDL_SCANCODE_Y},
|
||||||
|
{"Z", SDL_SCANCODE_Z},
|
||||||
|
{"1", SDL_SCANCODE_1},
|
||||||
|
{"2", SDL_SCANCODE_2},
|
||||||
|
{"3", SDL_SCANCODE_3},
|
||||||
|
{"4", SDL_SCANCODE_4},
|
||||||
|
{"5", SDL_SCANCODE_5},
|
||||||
|
{"6", SDL_SCANCODE_6},
|
||||||
|
{"7", SDL_SCANCODE_7},
|
||||||
|
{"8", SDL_SCANCODE_8},
|
||||||
|
{"9", SDL_SCANCODE_9},
|
||||||
|
{"0", SDL_SCANCODE_0},
|
||||||
|
{"RETURN", SDL_SCANCODE_RETURN},
|
||||||
|
{"ESCAPE", SDL_SCANCODE_ESCAPE},
|
||||||
|
{"BACKSPACE", SDL_SCANCODE_BACKSPACE},
|
||||||
|
{"TAB", SDL_SCANCODE_TAB},
|
||||||
|
{"SPACE", SDL_SCANCODE_SPACE},
|
||||||
|
{"UP", SDL_SCANCODE_UP},
|
||||||
|
{"DOWN", SDL_SCANCODE_DOWN},
|
||||||
|
{"LEFT", SDL_SCANCODE_LEFT},
|
||||||
|
{"RIGHT", SDL_SCANCODE_RIGHT},
|
||||||
|
{"LSHIFT", SDL_SCANCODE_LSHIFT},
|
||||||
|
{"RSHIFT", SDL_SCANCODE_RSHIFT},
|
||||||
|
{"LCTRL", SDL_SCANCODE_LCTRL},
|
||||||
|
{"RCTRL", SDL_SCANCODE_RCTRL},
|
||||||
|
{"LALT", SDL_SCANCODE_LALT},
|
||||||
|
{"RALT", SDL_SCANCODE_RALT}};
|
||||||
|
|
||||||
// Mapa de botó de gamepad (int) a string
|
// Mapa de botó de gamepad (int) a string
|
||||||
static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
||||||
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, // A (Xbox), Cross (PS)
|
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, // A (Xbox), Cross (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, // B (Xbox), Circle (PS)
|
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, // B (Xbox), Circle (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, // X (Xbox), Square (PS)
|
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, // X (Xbox), Square (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, // Y (Xbox), Triangle (PS)
|
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, // Y (Xbox), Triangle (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_BACK, "BACK"},
|
{SDL_GAMEPAD_BUTTON_BACK, "BACK"},
|
||||||
{SDL_GAMEPAD_BUTTON_START, "START"},
|
{SDL_GAMEPAD_BUTTON_START, "START"},
|
||||||
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"},
|
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"},
|
||||||
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"},
|
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||||
{100, "L2_AS_BUTTON"}, // Trigger L2 com a botó digital
|
{100, "L2_AS_BUTTON"}, // Trigger L2 com a botó digital
|
||||||
{101, "R2_AS_BUTTON"} // Trigger R2 com a botó digital
|
{101, "R2_AS_BUTTON"} // Trigger R2 com a botó digital
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mapa invers: string a botó de gamepad
|
// Mapa invers: string a botó de gamepad
|
||||||
static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
||||||
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
||||||
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
||||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||||
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
||||||
{"BACK", SDL_GAMEPAD_BUTTON_BACK},
|
{"BACK", SDL_GAMEPAD_BUTTON_BACK},
|
||||||
{"START", SDL_GAMEPAD_BUTTON_START},
|
{"START", SDL_GAMEPAD_BUTTON_START},
|
||||||
{"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
{"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
||||||
{"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
{"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
||||||
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||||
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||||
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||||
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||||
{"L2_AS_BUTTON", 100},
|
{"L2_AS_BUTTON", 100},
|
||||||
{"R2_AS_BUTTON", 101}
|
{"R2_AS_BUTTON", 101}};
|
||||||
};
|
|
||||||
|
|
||||||
static auto scancodeToString(SDL_Scancode code) -> std::string {
|
static auto scancodeToString(SDL_Scancode code) -> std::string {
|
||||||
auto it = SCANCODE_TO_STRING.find(code);
|
auto it = SCANCODE_TO_STRING.find(code);
|
||||||
return (it != SCANCODE_TO_STRING.end()) ? it->second : "UNKNOWN";
|
return (it != SCANCODE_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto stringToScancode(const std::string& str) -> SDL_Scancode {
|
static auto stringToScancode(const std::string& str) -> SDL_Scancode {
|
||||||
auto it = STRING_TO_SCANCODE.find(str);
|
auto it = STRING_TO_SCANCODE.find(str);
|
||||||
return (it != STRING_TO_SCANCODE.end()) ? it->second : SDL_SCANCODE_UNKNOWN;
|
return (it != STRING_TO_SCANCODE.end()) ? it->second : SDL_SCANCODE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto buttonToString(int button) -> std::string {
|
static auto buttonToString(int button) -> std::string {
|
||||||
auto it = BUTTON_TO_STRING.find(button);
|
auto it = BUTTON_TO_STRING.find(button);
|
||||||
return (it != BUTTON_TO_STRING.end()) ? it->second : "UNKNOWN";
|
return (it != BUTTON_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto stringToButton(const std::string& str) -> int {
|
static auto stringToButton(const std::string& str) -> int {
|
||||||
auto it = STRING_TO_BUTTON.find(str);
|
auto it = STRING_TO_BUTTON.find(str);
|
||||||
return (it != STRING_TO_BUTTON.end()) ? it->second : SDL_GAMEPAD_BUTTON_INVALID;
|
return (it != STRING_TO_BUTTON.end()) ? it->second : SDL_GAMEPAD_BUTTON_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== FI FUNCIONS AUXILIARS ==========
|
// ========== FI FUNCIONS AUXILIARS ==========
|
||||||
|
|
||||||
|
|
||||||
// Inicialitzar opcions amb valors per defecte de Defaults::
|
// Inicialitzar opcions amb valors per defecte de Defaults::
|
||||||
void init() {
|
void init() {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ struct KeyboardControls {
|
|||||||
struct GamepadControls {
|
struct GamepadControls {
|
||||||
int button_left{SDL_GAMEPAD_BUTTON_DPAD_LEFT};
|
int button_left{SDL_GAMEPAD_BUTTON_DPAD_LEFT};
|
||||||
int button_right{SDL_GAMEPAD_BUTTON_DPAD_RIGHT};
|
int button_right{SDL_GAMEPAD_BUTTON_DPAD_RIGHT};
|
||||||
int button_thrust{SDL_GAMEPAD_BUTTON_WEST}; // X button
|
int button_thrust{SDL_GAMEPAD_BUTTON_WEST}; // X button
|
||||||
int button_shoot{SDL_GAMEPAD_BUTTON_SOUTH}; // A button
|
int button_shoot{SDL_GAMEPAD_BUTTON_SOUTH}; // A button
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerControls {
|
struct PlayerControls {
|
||||||
@@ -85,23 +85,23 @@ inline Audio audio{};
|
|||||||
|
|
||||||
// Controles per jugador
|
// Controles per jugador
|
||||||
inline PlayerControls player1{
|
inline PlayerControls player1{
|
||||||
.keyboard =
|
.keyboard =
|
||||||
{.key_left = SDL_SCANCODE_LEFT,
|
{.key_left = SDL_SCANCODE_LEFT,
|
||||||
.key_right = SDL_SCANCODE_RIGHT,
|
.key_right = SDL_SCANCODE_RIGHT,
|
||||||
.key_thrust = SDL_SCANCODE_UP,
|
.key_thrust = SDL_SCANCODE_UP,
|
||||||
.key_shoot = SDL_SCANCODE_SPACE,
|
.key_shoot = SDL_SCANCODE_SPACE,
|
||||||
.key_start = SDL_SCANCODE_1},
|
.key_start = SDL_SCANCODE_1},
|
||||||
.gamepad_name = "" // Primer gamepad disponible
|
.gamepad_name = "" // Primer gamepad disponible
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PlayerControls player2{
|
inline PlayerControls player2{
|
||||||
.keyboard =
|
.keyboard =
|
||||||
{.key_left = SDL_SCANCODE_A,
|
{.key_left = SDL_SCANCODE_A,
|
||||||
.key_right = SDL_SCANCODE_D,
|
.key_right = SDL_SCANCODE_D,
|
||||||
.key_thrust = SDL_SCANCODE_W,
|
.key_thrust = SDL_SCANCODE_W,
|
||||||
.key_shoot = SDL_SCANCODE_LSHIFT,
|
.key_shoot = SDL_SCANCODE_LSHIFT,
|
||||||
.key_start = SDL_SCANCODE_2},
|
.key_start = SDL_SCANCODE_2},
|
||||||
.gamepad_name = "" // Segon gamepad disponible
|
.gamepad_name = "" // Segon gamepad disponible
|
||||||
};
|
};
|
||||||
|
|
||||||
// Per compatibilitat amb pollo (no utilitzat en orni, però necessari per Input)
|
// Per compatibilitat amb pollo (no utilitzat en orni, però necessari per Input)
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
namespace StageSystem {
|
namespace StageSystem {
|
||||||
|
|
||||||
SpawnController::SpawnController()
|
SpawnController::SpawnController()
|
||||||
: config_(nullptr), temps_transcorregut_(0.0f), index_spawn_actual_(0), ship_position_(nullptr) {}
|
: config_(nullptr),
|
||||||
|
temps_transcorregut_(0.0f),
|
||||||
|
index_spawn_actual_(0),
|
||||||
|
ship_position_(nullptr) {}
|
||||||
|
|
||||||
void SpawnController::configurar(const ConfigStage* config) {
|
void SpawnController::configurar(const ConfigStage* config) {
|
||||||
config_ = config;
|
config_ = config;
|
||||||
@@ -114,7 +117,7 @@ void SpawnController::generar_spawn_events() {
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < config_->total_enemics; i++) {
|
for (uint8_t i = 0; i < config_->total_enemics; i++) {
|
||||||
float spawn_time = config_->config_spawn.delay_inicial +
|
float spawn_time = config_->config_spawn.delay_inicial +
|
||||||
(i * config_->config_spawn.interval_spawn);
|
(i * config_->config_spawn.interval_spawn);
|
||||||
|
|
||||||
TipusEnemic tipus = seleccionar_tipus_aleatori();
|
TipusEnemic tipus = seleccionar_tipus_aleatori();
|
||||||
|
|
||||||
|
|||||||
@@ -15,44 +15,44 @@ namespace StageSystem {
|
|||||||
|
|
||||||
// Informació de spawn planificat
|
// Informació de spawn planificat
|
||||||
struct SpawnEvent {
|
struct SpawnEvent {
|
||||||
float temps_spawn; // Temps absolut (segons) per spawnejar
|
float temps_spawn; // Temps absolut (segons) per spawnejar
|
||||||
TipusEnemic tipus; // Tipus d'enemic
|
TipusEnemic tipus; // Tipus d'enemic
|
||||||
bool spawnejat; // Ja s'ha processat?
|
bool spawnejat; // Ja s'ha processat?
|
||||||
};
|
};
|
||||||
|
|
||||||
class SpawnController {
|
class SpawnController {
|
||||||
public:
|
public:
|
||||||
SpawnController();
|
SpawnController();
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
void configurar(const ConfigStage* config); // Set stage config
|
void configurar(const ConfigStage* config); // Set stage config
|
||||||
void iniciar(); // Generate spawn schedule
|
void iniciar(); // Generate spawn schedule
|
||||||
void reset(); // Clear all pending spawns
|
void reset(); // Clear all pending spawns
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
void actualitzar(float delta_time, std::array<Enemic, 15>& orni_array, bool pausar = false);
|
void actualitzar(float delta_time, std::array<Enemic, 15>& orni_array, bool pausar = false);
|
||||||
|
|
||||||
// Status queries
|
// Status queries
|
||||||
bool tots_enemics_spawnejats() const;
|
bool tots_enemics_spawnejats() const;
|
||||||
bool tots_enemics_destruits(const std::array<Enemic, 15>& orni_array) const;
|
bool tots_enemics_destruits(const std::array<Enemic, 15>& orni_array) const;
|
||||||
uint8_t get_enemics_vius(const std::array<Enemic, 15>& orni_array) const;
|
uint8_t get_enemics_vius(const std::array<Enemic, 15>& orni_array) const;
|
||||||
uint8_t get_enemics_spawnejats() const;
|
uint8_t get_enemics_spawnejats() const;
|
||||||
|
|
||||||
// [NEW] Set ship position reference for safe spawn
|
// [NEW] Set ship position reference for safe spawn
|
||||||
void set_ship_position(const Punt* ship_pos) { ship_position_ = ship_pos; }
|
void set_ship_position(const Punt* ship_pos) { ship_position_ = ship_pos; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ConfigStage* config_; // Non-owning pointer to current stage config
|
const ConfigStage* config_; // Non-owning pointer to current stage config
|
||||||
std::vector<SpawnEvent> spawn_queue_;
|
std::vector<SpawnEvent> spawn_queue_;
|
||||||
float temps_transcorregut_; // Elapsed time since stage start
|
float temps_transcorregut_; // Elapsed time since stage start
|
||||||
uint8_t index_spawn_actual_; // Next spawn to process
|
uint8_t index_spawn_actual_; // Next spawn to process
|
||||||
|
|
||||||
// Spawn generation
|
// Spawn generation
|
||||||
void generar_spawn_events();
|
void generar_spawn_events();
|
||||||
TipusEnemic seleccionar_tipus_aleatori() const;
|
TipusEnemic seleccionar_tipus_aleatori() const;
|
||||||
void spawn_enemic(Enemic& enemic, TipusEnemic tipus, const Punt* ship_pos = nullptr);
|
void spawn_enemic(Enemic& enemic, TipusEnemic tipus, const Punt* ship_pos = nullptr);
|
||||||
void aplicar_multiplicadors(Enemic& enemic) const;
|
void aplicar_multiplicadors(Enemic& enemic) const;
|
||||||
const Punt* ship_position_; // [NEW] Non-owning pointer to ship position
|
const Punt* ship_position_; // [NEW] Non-owning pointer to ship position
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace StageSystem
|
} // namespace StageSystem
|
||||||
|
|||||||
@@ -19,82 +19,81 @@ enum class ModeSpawn {
|
|||||||
|
|
||||||
// Configuració de spawn
|
// Configuració de spawn
|
||||||
struct ConfigSpawn {
|
struct ConfigSpawn {
|
||||||
ModeSpawn mode;
|
ModeSpawn mode;
|
||||||
float delay_inicial; // Segons abans del primer spawn
|
float delay_inicial; // Segons abans del primer spawn
|
||||||
float interval_spawn; // Segons entre spawns consecutius
|
float interval_spawn; // Segons entre spawns consecutius
|
||||||
};
|
};
|
||||||
|
|
||||||
// Distribució de tipus d'enemics (percentatges)
|
// Distribució de tipus d'enemics (percentatges)
|
||||||
struct DistribucioEnemics {
|
struct DistribucioEnemics {
|
||||||
uint8_t pentagon; // 0-100
|
uint8_t pentagon; // 0-100
|
||||||
uint8_t quadrat; // 0-100
|
uint8_t quadrat; // 0-100
|
||||||
uint8_t molinillo; // 0-100
|
uint8_t molinillo; // 0-100
|
||||||
// Suma ha de ser 100, validat en StageLoader
|
// Suma ha de ser 100, validat en StageLoader
|
||||||
};
|
};
|
||||||
|
|
||||||
// Multiplicadors de dificultat
|
// Multiplicadors de dificultat
|
||||||
struct MultiplicadorsDificultat {
|
struct MultiplicadorsDificultat {
|
||||||
float velocitat; // 0.5-2.0 típic
|
float velocitat; // 0.5-2.0 típic
|
||||||
float rotacio; // 0.5-2.0 típic
|
float rotacio; // 0.5-2.0 típic
|
||||||
float tracking_strength; // 0.0-1.5 (aplicat a Quadrat)
|
float tracking_strength; // 0.0-1.5 (aplicat a Quadrat)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Metadades del fitxer YAML
|
// Metadades del fitxer YAML
|
||||||
struct MetadataStages {
|
struct MetadataStages {
|
||||||
std::string version;
|
std::string version;
|
||||||
uint8_t total_stages;
|
uint8_t total_stages;
|
||||||
std::string descripcio;
|
std::string descripcio;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Configuració completa d'un stage
|
// Configuració completa d'un stage
|
||||||
struct ConfigStage {
|
struct ConfigStage {
|
||||||
uint8_t stage_id; // 1-10
|
uint8_t stage_id; // 1-10
|
||||||
uint8_t total_enemics; // 5-15
|
uint8_t total_enemics; // 5-15
|
||||||
ConfigSpawn config_spawn;
|
ConfigSpawn config_spawn;
|
||||||
DistribucioEnemics distribucio;
|
DistribucioEnemics distribucio;
|
||||||
MultiplicadorsDificultat multiplicadors;
|
MultiplicadorsDificultat multiplicadors;
|
||||||
|
|
||||||
// Validació
|
// Validació
|
||||||
bool es_valid() const {
|
bool es_valid() const {
|
||||||
return stage_id >= 1 && stage_id <= 255 &&
|
return stage_id >= 1 && stage_id <= 255 &&
|
||||||
total_enemics > 0 && total_enemics <= 15 &&
|
total_enemics > 0 && total_enemics <= 15 &&
|
||||||
distribucio.pentagon + distribucio.quadrat + distribucio.molinillo == 100;
|
distribucio.pentagon + distribucio.quadrat + distribucio.molinillo == 100;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Configuració completa del sistema (carregada des de YAML)
|
// Configuració completa del sistema (carregada des de YAML)
|
||||||
struct ConfigSistemaStages {
|
struct ConfigSistemaStages {
|
||||||
MetadataStages metadata;
|
MetadataStages metadata;
|
||||||
std::vector<ConfigStage> stages; // Índex [0] = stage 1
|
std::vector<ConfigStage> stages; // Índex [0] = stage 1
|
||||||
|
|
||||||
// Obtenir configuració d'un stage específic
|
// Obtenir configuració d'un stage específic
|
||||||
const ConfigStage* obte_stage(uint8_t stage_id) const {
|
const ConfigStage* obte_stage(uint8_t stage_id) const {
|
||||||
if (stage_id < 1 || stage_id > stages.size()) {
|
if (stage_id < 1 || stage_id > stages.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &stages[stage_id - 1];
|
||||||
}
|
}
|
||||||
return &stages[stage_id - 1];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constants per missatges de transició
|
// Constants per missatges de transició
|
||||||
namespace Constants {
|
namespace Constants {
|
||||||
// Pool de missatges per inici de level (selecció aleatòria)
|
// Pool de missatges per inici de level (selecció aleatòria)
|
||||||
inline constexpr std::array<const char*, 12> MISSATGES_LEVEL_START = {
|
inline constexpr std::array<const char*, 12> MISSATGES_LEVEL_START = {
|
||||||
"ORNI ALERT!",
|
"ORNI ALERT!",
|
||||||
"INCOMING ORNIS!",
|
"INCOMING ORNIS!",
|
||||||
"ROLLING THREAT!",
|
"ROLLING THREAT!",
|
||||||
"ENEMY WAVE!",
|
"ENEMY WAVE!",
|
||||||
"WAVE OF ORNIS DETECTED!",
|
"WAVE OF ORNIS DETECTED!",
|
||||||
"NEXT SWARM APPROACHING!",
|
"NEXT SWARM APPROACHING!",
|
||||||
"BRACE FOR THE NEXT WAVE!",
|
"BRACE FOR THE NEXT WAVE!",
|
||||||
"ANOTHER ATTACK INCOMING!",
|
"ANOTHER ATTACK INCOMING!",
|
||||||
"SENSORS DETECT HOSTILE ORNIS...",
|
"SENSORS DETECT HOSTILE ORNIS...",
|
||||||
"UNIDENTIFIED ROLLING OBJECTS INBOUND!",
|
"UNIDENTIFIED ROLLING OBJECTS INBOUND!",
|
||||||
"ENEMY FORCES MOBILIZING!",
|
"ENEMY FORCES MOBILIZING!",
|
||||||
"PREPARE FOR IMPACT!"
|
"PREPARE FOR IMPACT!"};
|
||||||
};
|
|
||||||
|
|
||||||
constexpr const char* MISSATGE_LEVEL_COMPLETED = "GOOD JOB COMMANDER!";
|
constexpr const char* MISSATGE_LEVEL_COMPLETED = "GOOD JOB COMMANDER!";
|
||||||
}
|
} // namespace Constants
|
||||||
|
|
||||||
} // namespace StageSystem
|
} // namespace StageSystem
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
#include "stage_loader.hpp"
|
#include "stage_loader.hpp"
|
||||||
|
|
||||||
#include "core/resources/resource_helper.hpp"
|
|
||||||
#include "external/fkyaml_node.hpp"
|
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "core/resources/resource_helper.hpp"
|
||||||
|
#include "external/fkyaml_node.hpp"
|
||||||
|
|
||||||
namespace StageSystem {
|
namespace StageSystem {
|
||||||
|
|
||||||
std::unique_ptr<ConfigSistemaStages> StageLoader::carregar(const std::string& path) {
|
std::unique_ptr<ConfigSistemaStages> StageLoader::carregar(const std::string& path) {
|
||||||
@@ -88,8 +88,8 @@ bool StageLoader::parse_metadata(const fkyaml::node& yaml, MetadataStages& meta)
|
|||||||
meta.version = yaml["version"].get_value<std::string>();
|
meta.version = yaml["version"].get_value<std::string>();
|
||||||
meta.total_stages = yaml["total_stages"].get_value<uint8_t>();
|
meta.total_stages = yaml["total_stages"].get_value<uint8_t>();
|
||||||
meta.descripcio = yaml.contains("description")
|
meta.descripcio = yaml.contains("description")
|
||||||
? yaml["description"].get_value<std::string>()
|
? yaml["description"].get_value<std::string>()
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
|||||||
@@ -5,28 +5,29 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "external/fkyaml_node.hpp"
|
#include "external/fkyaml_node.hpp"
|
||||||
#include "stage_config.hpp"
|
#include "stage_config.hpp"
|
||||||
|
|
||||||
namespace StageSystem {
|
namespace StageSystem {
|
||||||
|
|
||||||
class StageLoader {
|
class StageLoader {
|
||||||
public:
|
public:
|
||||||
// Carregar configuració des de fitxer YAML
|
// Carregar configuració des de fitxer YAML
|
||||||
// Retorna nullptr si hi ha errors
|
// Retorna nullptr si hi ha errors
|
||||||
static std::unique_ptr<ConfigSistemaStages> carregar(const std::string& path);
|
static std::unique_ptr<ConfigSistemaStages> carregar(const std::string& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Parsing helpers (implementats en .cpp)
|
// Parsing helpers (implementats en .cpp)
|
||||||
static bool parse_metadata(const fkyaml::node& yaml, MetadataStages& meta);
|
static bool parse_metadata(const fkyaml::node& yaml, MetadataStages& meta);
|
||||||
static bool parse_stage(const fkyaml::node& yaml, ConfigStage& stage);
|
static bool parse_stage(const fkyaml::node& yaml, ConfigStage& stage);
|
||||||
static bool parse_spawn_config(const fkyaml::node& yaml, ConfigSpawn& config);
|
static bool parse_spawn_config(const fkyaml::node& yaml, ConfigSpawn& config);
|
||||||
static bool parse_distribution(const fkyaml::node& yaml, DistribucioEnemics& dist);
|
static bool parse_distribution(const fkyaml::node& yaml, DistribucioEnemics& dist);
|
||||||
static bool parse_multipliers(const fkyaml::node& yaml, MultiplicadorsDificultat& mult);
|
static bool parse_multipliers(const fkyaml::node& yaml, MultiplicadorsDificultat& mult);
|
||||||
static ModeSpawn parse_spawn_mode(const std::string& mode_str);
|
static ModeSpawn parse_spawn_mode(const std::string& mode_str);
|
||||||
|
|
||||||
// Validació
|
// Validació
|
||||||
static bool validar_config(const ConfigSistemaStages& config);
|
static bool validar_config(const ConfigSistemaStages& config);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace StageSystem
|
} // namespace StageSystem
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ void StageManager::stage_completat() {
|
|||||||
|
|
||||||
bool StageManager::tot_completat() const {
|
bool StageManager::tot_completat() const {
|
||||||
return stage_actual_ >= config_->metadata.total_stages &&
|
return stage_actual_ >= config_->metadata.total_stages &&
|
||||||
estat_ == EstatStage::LEVEL_COMPLETED &&
|
estat_ == EstatStage::LEVEL_COMPLETED &&
|
||||||
timer_transicio_ <= 0.0f;
|
timer_transicio_ <= 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigStage* StageManager::get_config_actual() const {
|
const ConfigStage* StageManager::get_config_actual() const {
|
||||||
@@ -127,8 +127,8 @@ void StageManager::processar_playing(float delta_time, bool pausar_spawn) {
|
|||||||
// Update spawn controller (pauses when pausar_spawn = true)
|
// Update spawn controller (pauses when pausar_spawn = true)
|
||||||
// Note: The actual enemy array update happens in EscenaJoc::actualitzar()
|
// Note: The actual enemy array update happens in EscenaJoc::actualitzar()
|
||||||
// This is just for internal timekeeping
|
// This is just for internal timekeeping
|
||||||
(void)delta_time; // Spawn controller is updated externally
|
(void)delta_time; // Spawn controller is updated externally
|
||||||
(void)pausar_spawn; // Passed to spawn_controller_.actualitzar() by EscenaJoc
|
(void)pausar_spawn; // Passed to spawn_controller_.actualitzar() by EscenaJoc
|
||||||
}
|
}
|
||||||
|
|
||||||
void StageManager::processar_level_completed(float delta_time) {
|
void StageManager::processar_level_completed(float delta_time) {
|
||||||
|
|||||||
@@ -13,51 +13,51 @@ namespace StageSystem {
|
|||||||
|
|
||||||
// Estats del stage system
|
// Estats del stage system
|
||||||
enum class EstatStage {
|
enum class EstatStage {
|
||||||
INIT_HUD, // Animació inicial del HUD (3s)
|
INIT_HUD, // Animació inicial del HUD (3s)
|
||||||
LEVEL_START, // Pantalla "ENEMY INCOMING" (3s)
|
LEVEL_START, // Pantalla "ENEMY INCOMING" (3s)
|
||||||
PLAYING, // Gameplay normal
|
PLAYING, // Gameplay normal
|
||||||
LEVEL_COMPLETED // Pantalla "GOOD JOB COMMANDER!" (3s)
|
LEVEL_COMPLETED // Pantalla "GOOD JOB COMMANDER!" (3s)
|
||||||
};
|
};
|
||||||
|
|
||||||
class StageManager {
|
class StageManager {
|
||||||
public:
|
public:
|
||||||
explicit StageManager(const ConfigSistemaStages* config);
|
explicit StageManager(const ConfigSistemaStages* config);
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
void inicialitzar(); // Reset to stage 1
|
void inicialitzar(); // Reset to stage 1
|
||||||
void actualitzar(float delta_time, bool pausar_spawn = false);
|
void actualitzar(float delta_time, bool pausar_spawn = false);
|
||||||
|
|
||||||
// Stage progression
|
// Stage progression
|
||||||
void stage_completat(); // Call when all enemies destroyed
|
void stage_completat(); // Call when all enemies destroyed
|
||||||
bool tot_completat() const; // All 10 stages done?
|
bool tot_completat() const; // All 10 stages done?
|
||||||
|
|
||||||
// Current state queries
|
// Current state queries
|
||||||
EstatStage get_estat() const { return estat_; }
|
EstatStage get_estat() const { return estat_; }
|
||||||
uint8_t get_stage_actual() const { return stage_actual_; }
|
uint8_t get_stage_actual() const { return stage_actual_; }
|
||||||
const ConfigStage* get_config_actual() const;
|
const ConfigStage* get_config_actual() const;
|
||||||
float get_timer_transicio() const { return timer_transicio_; }
|
float get_timer_transicio() const { return timer_transicio_; }
|
||||||
const std::string& get_missatge_level_start() const { return missatge_level_start_actual_; }
|
const std::string& get_missatge_level_start() const { return missatge_level_start_actual_; }
|
||||||
|
|
||||||
// Spawn control (delegate to SpawnController)
|
// Spawn control (delegate to SpawnController)
|
||||||
SpawnController& get_spawn_controller() { return spawn_controller_; }
|
SpawnController& get_spawn_controller() { return spawn_controller_; }
|
||||||
const SpawnController& get_spawn_controller() const { return spawn_controller_; }
|
const SpawnController& get_spawn_controller() const { return spawn_controller_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ConfigSistemaStages* config_; // Non-owning pointer
|
const ConfigSistemaStages* config_; // Non-owning pointer
|
||||||
SpawnController spawn_controller_;
|
SpawnController spawn_controller_;
|
||||||
|
|
||||||
EstatStage estat_;
|
EstatStage estat_;
|
||||||
uint8_t stage_actual_; // 1-10
|
uint8_t stage_actual_; // 1-10
|
||||||
float timer_transicio_; // Timer for LEVEL_START/LEVEL_COMPLETED (3.0s → 0.0s)
|
float timer_transicio_; // Timer for LEVEL_START/LEVEL_COMPLETED (3.0s → 0.0s)
|
||||||
std::string missatge_level_start_actual_; // Missatge seleccionat per al level actual
|
std::string missatge_level_start_actual_; // Missatge seleccionat per al level actual
|
||||||
|
|
||||||
// State transitions
|
// State transitions
|
||||||
void canviar_estat(EstatStage nou_estat);
|
void canviar_estat(EstatStage nou_estat);
|
||||||
void processar_init_hud(float delta_time);
|
void processar_init_hud(float delta_time);
|
||||||
void processar_level_start(float delta_time);
|
void processar_level_start(float delta_time);
|
||||||
void processar_playing(float delta_time, bool pausar_spawn);
|
void processar_playing(float delta_time, bool pausar_spawn);
|
||||||
void processar_level_completed(float delta_time);
|
void processar_level_completed(float delta_time);
|
||||||
void carregar_stage(uint8_t stage_id);
|
void carregar_stage(uint8_t stage_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace StageSystem
|
} // namespace StageSystem
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ ShipAnimator::ShipAnimator(SDL_Renderer* renderer)
|
|||||||
|
|
||||||
void ShipAnimator::inicialitzar() {
|
void ShipAnimator::inicialitzar() {
|
||||||
// Carregar formes de naus amb perspectiva pre-calculada
|
// Carregar formes de naus amb perspectiva pre-calculada
|
||||||
auto forma_p1 = Graphics::ShapeLoader::load("ship_p1.shp"); // Perspectiva esquerra
|
auto forma_p1 = Graphics::ShapeLoader::load("ship_p1.shp"); // Perspectiva esquerra
|
||||||
auto forma_p2 = Graphics::ShapeLoader::load("ship2_p2.shp"); // Perspectiva dreta
|
auto forma_p2 = Graphics::ShapeLoader::load("ship2_p2.shp"); // Perspectiva dreta
|
||||||
|
|
||||||
// Configurar nau P1
|
// Configurar nau P1
|
||||||
naus_[0].jugador_id = 1;
|
naus_[0].jugador_id = 1;
|
||||||
@@ -59,11 +59,11 @@ void ShipAnimator::dibuixar() const {
|
|||||||
renderer_,
|
renderer_,
|
||||||
nau.forma,
|
nau.forma,
|
||||||
nau.posicio_actual,
|
nau.posicio_actual,
|
||||||
0.0f, // angle (rotació 2D no utilitzada)
|
0.0f, // angle (rotació 2D no utilitzada)
|
||||||
nau.escala_actual,
|
nau.escala_actual,
|
||||||
true, // dibuixar
|
true, // dibuixar
|
||||||
1.0f, // progress (sempre visible)
|
1.0f, // progress (sempre visible)
|
||||||
1.0f // brightness (brillantor màxima)
|
1.0f // brightness (brillantor màxima)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ void ShipAnimator::configurar_nau_p1(NauTitol& nau) {
|
|||||||
nau.temps_estat = 0.0f;
|
nau.temps_estat = 0.0f;
|
||||||
|
|
||||||
// Posicions (clock 8, bottom-left)
|
// Posicions (clock 8, bottom-left)
|
||||||
nau.posicio_objectiu = {P1_TARGET_X, P1_TARGET_Y};
|
nau.posicio_objectiu = {P1_TARGET_X(), P1_TARGET_Y()};
|
||||||
|
|
||||||
// Calcular posició inicial (fora de pantalla)
|
// Calcular posició inicial (fora de pantalla)
|
||||||
nau.posicio_inicial = calcular_posicio_fora_pantalla(CLOCK_8_ANGLE);
|
nau.posicio_inicial = calcular_posicio_fora_pantalla(CLOCK_8_ANGLE);
|
||||||
@@ -262,7 +262,7 @@ void ShipAnimator::configurar_nau_p2(NauTitol& nau) {
|
|||||||
nau.temps_estat = 0.0f;
|
nau.temps_estat = 0.0f;
|
||||||
|
|
||||||
// Posicions (clock 4, bottom-right)
|
// Posicions (clock 4, bottom-right)
|
||||||
nau.posicio_objectiu = {P2_TARGET_X, P2_TARGET_Y};
|
nau.posicio_objectiu = {P2_TARGET_X(), P2_TARGET_Y()};
|
||||||
|
|
||||||
// Calcular posició inicial (fora de pantalla)
|
// Calcular posició inicial (fora de pantalla)
|
||||||
nau.posicio_inicial = calcular_posicio_fora_pantalla(CLOCK_4_ANGLE);
|
nau.posicio_inicial = calcular_posicio_fora_pantalla(CLOCK_4_ANGLE);
|
||||||
@@ -293,7 +293,8 @@ Punt ShipAnimator::calcular_posicio_fora_pantalla(float angle_rellotge) const {
|
|||||||
using namespace Defaults::Title::Ships;
|
using namespace Defaults::Title::Ships;
|
||||||
|
|
||||||
// Convertir angle del rellotge a radians (per exemple: 240° per clock 8)
|
// Convertir angle del rellotge a radians (per exemple: 240° per clock 8)
|
||||||
// Calcular posició en direcció radial des del centre, però més lluny (+ ENTRY_OFFSET)
|
// Calcular posició en direcció radial des del centre, però més lluny
|
||||||
|
// ENTRY_OFFSET es calcula automàticament: (SHIP_MAX_RADIUS * ENTRY_SCALE_START) + ENTRY_OFFSET_MARGIN
|
||||||
float extended_radius = CLOCK_RADIUS + ENTRY_OFFSET;
|
float extended_radius = CLOCK_RADIUS + ENTRY_OFFSET;
|
||||||
|
|
||||||
float x = Defaults::Game::WIDTH / 2.0f + extended_radius * std::cos(angle_rellotge);
|
float x = Defaults::Game::WIDTH / 2.0f + extended_radius * std::cos(angle_rellotge);
|
||||||
|
|||||||
@@ -23,74 +23,74 @@ enum class EstatNau {
|
|||||||
|
|
||||||
// Dades d'una nau individual al títol
|
// Dades d'una nau individual al títol
|
||||||
struct NauTitol {
|
struct NauTitol {
|
||||||
// Identificació
|
// Identificació
|
||||||
int jugador_id; // 1 o 2
|
int jugador_id; // 1 o 2
|
||||||
|
|
||||||
// Estat
|
// Estat
|
||||||
EstatNau estat;
|
EstatNau estat;
|
||||||
float temps_estat; // Temps acumulat en l'estat actual
|
float temps_estat; // Temps acumulat en l'estat actual
|
||||||
|
|
||||||
// Posicions
|
// Posicions
|
||||||
Punt posicio_inicial; // Posició d'inici (fora de pantalla per ENTERING)
|
Punt posicio_inicial; // Posició d'inici (fora de pantalla per ENTERING)
|
||||||
Punt posicio_objectiu; // Posició objectiu (rellotge 8 o 4)
|
Punt posicio_objectiu; // Posició objectiu (rellotge 8 o 4)
|
||||||
Punt posicio_actual; // Posició interpolada actual
|
Punt posicio_actual; // Posició interpolada actual
|
||||||
|
|
||||||
// Escales (simulació eix Z)
|
// Escales (simulació eix Z)
|
||||||
float escala_inicial; // Escala d'inici (més gran = més a prop)
|
float escala_inicial; // Escala d'inici (més gran = més a prop)
|
||||||
float escala_objectiu; // Escala objectiu (mida flotació)
|
float escala_objectiu; // Escala objectiu (mida flotació)
|
||||||
float escala_actual; // Escala interpolada actual
|
float escala_actual; // Escala interpolada actual
|
||||||
|
|
||||||
// Flotació
|
// Flotació
|
||||||
float fase_oscilacio; // Acumulador de fase per moviment sinusoïdal
|
float fase_oscilacio; // Acumulador de fase per moviment sinusoïdal
|
||||||
|
|
||||||
// Paràmetres d'entrada
|
// Paràmetres d'entrada
|
||||||
float entry_delay; // Delay abans d'entrar (0.0 per P1, 0.5 per P2)
|
float entry_delay; // Delay abans d'entrar (0.0 per P1, 0.5 per P2)
|
||||||
|
|
||||||
// Paràmetres d'oscil·lació per nau
|
// Paràmetres d'oscil·lació per nau
|
||||||
float amplitude_x;
|
float amplitude_x;
|
||||||
float amplitude_y;
|
float amplitude_y;
|
||||||
float frequency_x;
|
float frequency_x;
|
||||||
float frequency_y;
|
float frequency_y;
|
||||||
|
|
||||||
// Forma
|
// Forma
|
||||||
std::shared_ptr<Graphics::Shape> forma;
|
std::shared_ptr<Graphics::Shape> forma;
|
||||||
|
|
||||||
// Visibilitat
|
// Visibilitat
|
||||||
bool visible;
|
bool visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gestor d'animació de naus per a l'escena de títol
|
// Gestor d'animació de naus per a l'escena de títol
|
||||||
class ShipAnimator {
|
class ShipAnimator {
|
||||||
public:
|
public:
|
||||||
explicit ShipAnimator(SDL_Renderer* renderer);
|
explicit ShipAnimator(SDL_Renderer* renderer);
|
||||||
|
|
||||||
// Cicle de vida
|
// Cicle de vida
|
||||||
void inicialitzar();
|
void inicialitzar();
|
||||||
void actualitzar(float delta_time);
|
void actualitzar(float delta_time);
|
||||||
void dibuixar() const;
|
void dibuixar() const;
|
||||||
|
|
||||||
// Control d'estat (cridat per EscenaTitol)
|
// Control d'estat (cridat per EscenaTitol)
|
||||||
void start_entry_animation();
|
void start_entry_animation();
|
||||||
void trigger_exit_animation(); // Anima totes les naus
|
void trigger_exit_animation(); // Anima totes les naus
|
||||||
void trigger_exit_animation_for_player(int jugador_id); // Anima només una nau (P1=1, P2=2)
|
void trigger_exit_animation_for_player(int jugador_id); // Anima només una nau (P1=1, P2=2)
|
||||||
|
|
||||||
// Control de visibilitat
|
// Control de visibilitat
|
||||||
void set_visible(bool visible);
|
void set_visible(bool visible);
|
||||||
bool is_animation_complete() const;
|
bool is_animation_complete() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_Renderer* renderer_;
|
SDL_Renderer* renderer_;
|
||||||
std::array<NauTitol, 2> naus_; // Naus P1 i P2
|
std::array<NauTitol, 2> naus_; // Naus P1 i P2
|
||||||
|
|
||||||
// Mètodes d'animació
|
// Mètodes d'animació
|
||||||
void actualitzar_entering(NauTitol& nau, float delta_time);
|
void actualitzar_entering(NauTitol& nau, float delta_time);
|
||||||
void actualitzar_floating(NauTitol& nau, float delta_time);
|
void actualitzar_floating(NauTitol& nau, float delta_time);
|
||||||
void actualitzar_exiting(NauTitol& nau, float delta_time);
|
void actualitzar_exiting(NauTitol& nau, float delta_time);
|
||||||
|
|
||||||
// Configuració
|
// Configuració
|
||||||
void configurar_nau_p1(NauTitol& nau);
|
void configurar_nau_p1(NauTitol& nau);
|
||||||
void configurar_nau_p2(NauTitol& nau);
|
void configurar_nau_p2(NauTitol& nau);
|
||||||
Punt calcular_posicio_fora_pantalla(float angle_rellotge) const;
|
Punt calcular_posicio_fora_pantalla(float angle_rellotge) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Title
|
} // namespace Title
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ constexpr const char* NAME = "@PROJECT_NAME@";
|
|||||||
constexpr const char* LONG_NAME = "@PROJECT_LONG_NAME@";
|
constexpr const char* LONG_NAME = "@PROJECT_LONG_NAME@";
|
||||||
constexpr const char* VERSION = "@PROJECT_VERSION@";
|
constexpr const char* VERSION = "@PROJECT_VERSION@";
|
||||||
constexpr const char* COPYRIGHT = "@PROJECT_COPYRIGHT@";
|
constexpr const char* COPYRIGHT = "@PROJECT_COPYRIGHT@";
|
||||||
|
constexpr const char* COPYRIGHT_ORIGINAL = "@PROJECT_COPYRIGHT_ORIGINAL@";
|
||||||
|
constexpr const char* COPYRIGHT_PORT = "@PROJECT_COPYRIGHT_PORT@";
|
||||||
constexpr const char* GIT_HASH = "@GIT_HASH@";
|
constexpr const char* GIT_HASH = "@GIT_HASH@";
|
||||||
} // namespace Project
|
} // namespace Project
|
||||||
|
|||||||
Reference in New Issue
Block a user