Fase 1e: cierre de naming sweep (#pragma once, locals, comentarios castellano)
Tres tareas de pulido para cerrar la Fase 1 por completo: #pragma once uniforme: - sdl_manager.hpp y game_scene.hpp pasan de #ifndef/#define guards a #pragma once. Los archivos externos (stb_vorbis.h, fkyaml_node.hpp) se mantienen intactos (codigo de terceros). Variables locales y parametros restantes (catalan -> ingles): - fitxer -> file, moviment -> movement, inici -> start - comptador -> counter, escalada -> scaled - missatges -> messages, llista -> list - alçada -> height, amplada -> width, llargada -> length - origen -> origin, distancia -> distance, valor -> value, desti -> target - neteja -> clear, presenta -> present (SDLManager) - total_enemics -> total_enemies, configurar -> configure, iniciar -> start Comentarios catalan -> castellano: - Cabeceras de fichero actualizadas con nombres nuevos (escena_joc.hpp -> game_scene.hpp, etc.) - Palabras tecnicas: trasllacio->traslacion, col-lisio->colision, inicialitzacio->inicializacion, posicio->posicion, rotacio->rotacion, velocitat->velocidad, acceleracio->aceleracion, explosio->explosion, renderitzat->renderizado, calcul->calculo, transicio->transicion, comprovacio->comprobacion, substitucio->sustitucion, utilitzacio->utilizacion, opcio->opcion, configuracio->configuracion, funcio->funcion, distancia, animacio->animacion - Determinantes y conectores: aquest->este, aquesta->esta, amb->con, sense->sin, pero->pero, mai->nunca, nomes->solo, tambe->tambien, sempre->siempre, ja->ya, mateix->mismo, vegada->vez, dintre->dentro, fora->fuera, dreta->derecha, esquerra->izquierda, sortir->salir, sortida->salida, petit->pequeno, gran->grande, nou->nuevo, vell->viejo, molt->mucho, els->los, les->las, totes les->todas las, d'->de, com->como, quan->cuando, mentre->mientras, despres->despues, abans->antes, durant->durante, fins->hasta, encara->aun, llavors->entonces, aixi->asi, perque->porque - Sustantivos: classe->clase, metode->metodo, parametre->parametro, versio->version, entitat->entidad, joc->juego, nivell->nivel, enemic->enemigo, naus->naves, bales->balas, fitxer->archivo, pentagon->pentagono, pun- tuacio->puntuacion, flotant->flotante, titol->titulo, objectiu->objetivo, mostra->muestra, tipus->tipo Strings literales preservados en valenciano segun decision del usuario: el texto del HUD del juego (puntuaciones, mensajes en pantalla, archivo de config) se mantiene en valenciano original. 70 fitxers tocats, +1117 / -1123. Compila i enllaca. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,7 @@ void Audio::playMusic(const std::string& name, const int loop) {
|
||||
// Llamada al motor para reproducir la nueva pista
|
||||
JA_PlayMusic(resource, loop);
|
||||
|
||||
// Actualizar estado y metadatos después de iniciar con éxito
|
||||
// Actualizar estado y metadatos después de start con éxito
|
||||
music_.name = name;
|
||||
music_.loop = new_loop;
|
||||
music_.state = MusicState::PLAYING;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// audio_cache.cpp - Implementació del caché de sons i música
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/audio/audio_cache.hpp"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
|
||||
// Inicialització de variables estàtiques
|
||||
// Inicialización de variables estàtiques
|
||||
std::unordered_map<std::string, JA_Sound_t*> AudioCache::sounds_;
|
||||
std::unordered_map<std::string, JA_Music_t*> AudioCache::musics_;
|
||||
std::string AudioCache::sounds_base_path_ = "data/sounds/";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// audio_cache.hpp - Caché simplificado de sonidos y música
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
||||
}
|
||||
|
||||
inline JA_Music_t* JA_LoadMusic(const char* filename) {
|
||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria y después el descomprimim. Es algo més rapid.
|
||||
FILE* f = fopen(filename, "rb");
|
||||
if (!f) return NULL; // Añadida comprobación de apertura
|
||||
fseek(f, 0, SEEK_END);
|
||||
|
||||
+58
-58
@@ -19,27 +19,27 @@ constexpr float ZOOM_INCREMENT = 0.1F; // 10% steps (F1/F2)
|
||||
constexpr bool FULLSCREEN = true; // Pantalla completa activadapor defecto
|
||||
} // namespace Window
|
||||
|
||||
// Dimensions base del joc (coordenades lògiques)
|
||||
// Dimensions base del juego (coordenades lògiques)
|
||||
namespace Game {
|
||||
constexpr int WIDTH = 640;
|
||||
constexpr int HEIGHT = 480;
|
||||
} // namespace Game
|
||||
|
||||
// Zones del joc (SDL_FRect amb càlculs automàtics basat en percentatges)
|
||||
// Zones del juego (SDL_FRect con cálculos automàtics basat en percentatges)
|
||||
namespace Zones {
|
||||
// --- CONFIGURACIÓ DE PORCENTATGES ---
|
||||
// Totes les zones definides com a percentatges de Game::WIDTH (640) i Game::HEIGHT (480)
|
||||
// Todas las zones definides como a percentatges de Game::WIDTH (640) i Game::HEIGHT (480)
|
||||
|
||||
// Percentatges d'alçada (divisió vertical)
|
||||
// Percentatges de height (divisió vertical)
|
||||
constexpr float SCOREBOARD_TOP_HEIGHT_PERCENT = 0.02F; // 10% superior
|
||||
constexpr float MAIN_PLAYAREA_HEIGHT_PERCENT = 0.88F; // 80% central
|
||||
constexpr float SCOREBOARD_BOTTOM_HEIGHT_PERCENT = 0.10F; // 10% inferior
|
||||
|
||||
// Padding horizontal per a PLAYAREA (dins de MAIN_PLAYAREA)
|
||||
// Padding horizontal para PLAYAREA (dins de MAIN_PLAYAREA)
|
||||
constexpr float PLAYAREA_PADDING_HORIZONTAL_PERCENT = 0.015F; // 5% a cada costat
|
||||
|
||||
// --- CÀLCULS AUTOMÀTICS DE PÍXELS ---
|
||||
// Càlculs automàtics a partir dels percentatges
|
||||
// Cálculos automàtics a partir dels percentatges
|
||||
|
||||
// Alçades
|
||||
constexpr float SCOREBOARD_TOP_H = Game::HEIGHT * SCOREBOARD_TOP_HEIGHT_PERCENT;
|
||||
@@ -56,7 +56,7 @@ constexpr float PLAYAREA_PADDING_H = Game::WIDTH * PLAYAREA_PADDING_HORIZONTAL_P
|
||||
|
||||
// --- ZONES FINALS (SDL_FRect) ---
|
||||
|
||||
// Marcador superior (reservat per a futur ús)
|
||||
// Marcador superior (reservat para futur ús)
|
||||
// Ocupa: 10% superior (0-48px)
|
||||
constexpr SDL_FRect SCOREBOARD_TOP = {
|
||||
0.0F, // x = 0.0
|
||||
@@ -65,7 +65,7 @@ constexpr SDL_FRect SCOREBOARD_TOP = {
|
||||
SCOREBOARD_TOP_H // h = 48.0
|
||||
};
|
||||
|
||||
// Àrea de joc principal (contenidor del 80% central, sense padding)
|
||||
// Àrea de juego principal (contenidor del 80% central, sin padding)
|
||||
// Ocupa: 10-90% (48-432px), ample complet
|
||||
constexpr SDL_FRect MAIN_PLAYAREA = {
|
||||
0.0F, // x = 0.0
|
||||
@@ -74,9 +74,9 @@ constexpr SDL_FRect MAIN_PLAYAREA = {
|
||||
MAIN_PLAYAREA_H // h = 384.0
|
||||
};
|
||||
|
||||
// Zona de joc real (amb padding horizontal del 5%)
|
||||
// Ocupa: dins de MAIN_PLAYAREA, amb marges laterals
|
||||
// S'utilitza per a límits del joc, col·lisions, spawn
|
||||
// Zona de juego real (con padding horizontal del 5%)
|
||||
// Ocupa: dins de MAIN_PLAYAREA, con marges laterals
|
||||
// S'utilitza para límits del juego, colisiones, spawn
|
||||
constexpr SDL_FRect PLAYAREA = {
|
||||
PLAYAREA_PADDING_H, // x = 32.0
|
||||
MAIN_PLAYAREA_Y, // y = 48.0 (igual que MAIN_PLAYAREA)
|
||||
@@ -93,7 +93,7 @@ constexpr SDL_FRect SCOREBOARD = {
|
||||
SCOREBOARD_BOTTOM_H // h = 48.0
|
||||
};
|
||||
|
||||
// Padding horizontal del marcador (per alinear zones esquerra/dreta amb PLAYAREA)
|
||||
// Padding horizontal del marcador (per alinear zones izquierda/derecha con PLAYAREA)
|
||||
constexpr float SCOREBOARD_PADDING_H = 0.0F; // Game::WIDTH * 0.015f;
|
||||
} // namespace Zones
|
||||
|
||||
@@ -211,11 +211,11 @@ constexpr float VELOCITY_SCALE = 20.0F; // factor conversión frame→tiempo
|
||||
|
||||
// Explosions (debris physics)
|
||||
namespace Debris {
|
||||
constexpr float VELOCITAT_BASE = 80.0F; // Velocitat inicial (px/s)
|
||||
constexpr float VELOCITAT_BASE = 80.0F; // Velocidad inicial (px/s)
|
||||
constexpr float VARIACIO_VELOCITAT = 40.0F; // ±variació aleatòria (px/s)
|
||||
constexpr float ACCELERACIO = -60.0F; // Fricció/desacceleració (px/s²)
|
||||
constexpr float ROTACIO_MIN = 0.1F; // Rotació mínima (rad/s ~5.7°/s)
|
||||
constexpr float ROTACIO_MAX = 0.3F; // Rotació màxima (rad/s ~17.2°/s)
|
||||
constexpr float ROTACIO_MIN = 0.1F; // Rotación mínima (rad/s ~5.7°/s)
|
||||
constexpr float ROTACIO_MAX = 0.3F; // Rotación màxima (rad/s ~17.2°/s)
|
||||
constexpr float TEMPS_VIDA = 2.0F; // Duració màxima (segons) - enemy/bullet debris
|
||||
constexpr float TEMPS_VIDA_NAU = 3.0F; // Ship debris lifetime (matches DEATH_DURATION)
|
||||
constexpr float SHRINK_RATE = 0.5F; // Reducció de mida (factor/s)
|
||||
@@ -225,7 +225,7 @@ constexpr float FACTOR_HERENCIA_MIN = 0.7F; // Mínimo 70% del drotacio heredat
|
||||
constexpr float FACTOR_HERENCIA_MAX = 1.0F; // Màxim 100% del drotacio heredat
|
||||
constexpr float FRICCIO_ANGULAR = 0.5F; // Desacceleració angular (rad/s²)
|
||||
|
||||
// Angular velocity cap for trajectory inheritance
|
||||
// Angular velocity sin for trajectory inheritance
|
||||
// Excess above this threshold is converted to tangential linear velocity
|
||||
// Prevents "vortex trap" problem with high-rotation enemies
|
||||
constexpr float VELOCITAT_ROT_MAX = 1.5F; // rad/s (~86°/s)
|
||||
@@ -261,21 +261,21 @@ constexpr uint8_t BACKGROUND_MAX_G = 15;
|
||||
constexpr uint8_t BACKGROUND_MAX_B = 0;
|
||||
} // namespace Color
|
||||
|
||||
// Brillantor (control de intensitat per cada type d'entitat)
|
||||
// Brillantor (control de intensitat per cada type de entidad)
|
||||
namespace Brightness {
|
||||
// Brillantor estàtica per entitats de joc (0.0-1.0)
|
||||
// Brillantor estàtica per entidades de juego (0.0-1.0)
|
||||
constexpr float NAU = 1.0F; // Màxima visibilitat (player)
|
||||
constexpr float ENEMIC = 0.7F; // 30% més tènue (destaca menys)
|
||||
constexpr float BALA = 1.0F; // Brillo a tope (màxima visibilitat)
|
||||
|
||||
// Starfield: gradient segons distància al centre
|
||||
// distancia_centre: 0.0 (centre) → 1.0 (vora pantalla)
|
||||
// Starfield: gradient segons distancia al centro
|
||||
// distancia_centre: 0.0 (centro) → 1.0 (vora pantalla)
|
||||
// brightness = MIN + (MAX - MIN) * distancia_centre
|
||||
constexpr float STARFIELD_MIN = 0.3F; // Estrelles llunyanes (prop del centre)
|
||||
constexpr float STARFIELD_MIN = 0.3F; // Estrelles llunyanes (prop del centro)
|
||||
constexpr float STARFIELD_MAX = 0.8F; // Estrelles properes (vora pantalla)
|
||||
} // namespace Brightness
|
||||
|
||||
// Renderització (V-Sync i altres opcions de render)
|
||||
// Renderització (V-Sync i altres opciones de render)
|
||||
namespace Rendering {
|
||||
constexpr int VSYNC_DEFAULT = 1; // 0=disabled, 1=enabled
|
||||
} // namespace Rendering
|
||||
@@ -327,7 +327,7 @@ constexpr SDL_Keycode SHOOT = SDLK_LSHIFT;
|
||||
} // namespace P2
|
||||
} // namespace Controls
|
||||
|
||||
// Enemy type configuration (type d'enemics)
|
||||
// Enemy type configuration (type de enemigos)
|
||||
namespace Enemies {
|
||||
// Pentagon (esquivador - zigzag evasion)
|
||||
namespace Pentagon {
|
||||
@@ -339,15 +339,15 @@ constexpr float DROTACIO_MAX = 3.75F; // Max visual rotation (rad/s) [+50%]
|
||||
constexpr const char* SHAPE_FILE = "enemy_pentagon.shp";
|
||||
} // namespace Pentagon
|
||||
|
||||
// Quadrat (perseguidor - tracks player)
|
||||
namespace Quadrat {
|
||||
// Cuadrado (perseguidor - tracks player)
|
||||
namespace Cuadrado {
|
||||
constexpr float VELOCITAT = 40.0F; // px/s (medium speed)
|
||||
constexpr float TRACKING_STRENGTH = 0.5F; // Interpolation toward player (0.0-1.0)
|
||||
constexpr float TRACKING_INTERVAL = 1.0F; // Seconds between angle updates
|
||||
constexpr float DROTACIO_MIN = 0.3F; // Slow rotation [+50%]
|
||||
constexpr float DROTACIO_MAX = 1.5F; // [+50%]
|
||||
constexpr const char* SHAPE_FILE = "enemy_square.shp";
|
||||
} // namespace Quadrat
|
||||
} // namespace Cuadrado
|
||||
|
||||
// Molinillo (agressiu - fast straight lines, proximity spin-up)
|
||||
namespace Molinillo {
|
||||
@@ -395,34 +395,34 @@ constexpr float INVULNERABILITY_SCALE_START = 0.0F; // Invisible
|
||||
constexpr float INVULNERABILITY_SCALE_END = 1.0F; // Full size
|
||||
} // namespace Spawn
|
||||
|
||||
// Scoring system (puntuació per type d'enemy)
|
||||
// Scoring system (puntuación per type de enemy)
|
||||
namespace Scoring {
|
||||
constexpr int PENTAGON_SCORE = 100; // Pentàgon (esquivador, 35 px/s)
|
||||
constexpr int QUADRAT_SCORE = 150; // Quadrat (perseguidor, 40 px/s)
|
||||
constexpr int PENTAGON_SCORE = 100; // Pentágono (esquivador, 35 px/s)
|
||||
constexpr int QUADRAT_SCORE = 150; // Cuadrado (perseguidor, 40 px/s)
|
||||
constexpr int MOLINILLO_SCORE = 200; // Molinillo (agressiu, 50 px/s)
|
||||
} // namespace Scoring
|
||||
|
||||
} // namespace Enemies
|
||||
|
||||
// Title scene ship animations (naus 3D flotants a l'escena de títol)
|
||||
// Title scene ship animations (naves 3D flotantes a l'escena de título)
|
||||
namespace Title {
|
||||
namespace Ships {
|
||||
// ============================================================
|
||||
// PARÀMETRES BASE (ajustar aquí per experimentar)
|
||||
// ============================================================
|
||||
|
||||
// 1. Escala global de les naus
|
||||
// 1. Escala global de las naves
|
||||
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
|
||||
// 3. Radio orbital (distance radial desde centro en coordenadas polares)
|
||||
constexpr float CLOCK_RADIUS = 150.0F; // Distancia des del centro
|
||||
|
||||
// 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° = derecha, 90° = baix, 180° = izquierda, 270° = dalt
|
||||
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)
|
||||
|
||||
@@ -436,13 +436,13 @@ constexpr float ENTRY_OFFSET_MARGIN = 227.5F; // Para offset total de ~340px (a
|
||||
// VALORS DERIVATS (calculats automàticament - NO modificar)
|
||||
// ============================================================
|
||||
|
||||
// Centre de la pantalla (point de referència)
|
||||
// Centro de la pantalla (point de referència)
|
||||
constexpr float CENTER_X = Game::WIDTH / 2.0F; // 320.0f
|
||||
constexpr float CENTER_Y = Game::HEIGHT / 2.0F; // 240.0f
|
||||
|
||||
// Posicions target (calculades dinàmicament des dels paràmetres base)
|
||||
// Nota: std::cos/sin no són constexpr en C++20, però funcionen en runtime
|
||||
// Les funcions inline són optimitzades pel compilador (zero overhead)
|
||||
// Posicions target (calculades dinàmicament des dels parámetros base)
|
||||
// Nota: std::cos/sin no són constexpr en C++20, pero funcionen en runtime
|
||||
// Les funciones inline són optimitzades por el compilador (zero overhead)
|
||||
inline float P1_TARGET_X() {
|
||||
return CENTER_X + (CLOCK_RADIUS * std::cos(CLOCK_8_ANGLE));
|
||||
}
|
||||
@@ -456,15 +456,15 @@ 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: scale base
|
||||
// Escales de animación (relatives a SHIP_BASE_SCALE)
|
||||
constexpr float ENTRY_SCALE_START = 1.5F * SHIP_BASE_SCALE; // Entrada: 50% més grande
|
||||
constexpr float FLOATING_SCALE = 1.0F * SHIP_BASE_SCALE; // Flotante: scale base
|
||||
|
||||
// Offset d'entrada (ajustat automàticament a l'scale)
|
||||
// Fórmula: (radi màxim de la ship * scale d'entrada) + marge
|
||||
// Offset de entrada (ajustat automàticament a l'scale)
|
||||
// Fórmula: (radi màxim de la ship * scale de entrada) + marge
|
||||
constexpr float ENTRY_OFFSET = (SHIP_MAX_RADIUS * ENTRY_SCALE_START) + ENTRY_OFFSET_MARGIN;
|
||||
|
||||
// Vec2 de fuga (centre per a l'animació de sortida)
|
||||
// Vec2 de fuga (centro para l'animación de salida)
|
||||
constexpr float VANISHING_POINT_X = CENTER_X; // 320.0f
|
||||
constexpr float VANISHING_POINT_Y = CENTER_Y; // 240.0f
|
||||
|
||||
@@ -472,11 +472,11 @@ constexpr float VANISHING_POINT_Y = CENTER_Y; // 240.0f
|
||||
// ANIMACIONS (durades, oscil·lacions, delays)
|
||||
// ============================================================
|
||||
|
||||
// Durades d'animació
|
||||
// Durades de animación
|
||||
constexpr float ENTRY_DURATION = 2.0F; // Entrada (segons)
|
||||
constexpr float EXIT_DURATION = 1.0F; // Sortida (segons)
|
||||
constexpr float EXIT_DURATION = 1.0F; // Salida (segons)
|
||||
|
||||
// Flotació (oscil·lació reduïda i diferenciada per ship)
|
||||
// Flotació (oscil·lació reduïda y diferenciada per ship)
|
||||
constexpr float FLOAT_AMPLITUDE_X = 4.0F; // Amplitud X (píxels)
|
||||
constexpr float FLOAT_AMPLITUDE_Y = 2.5F; // Amplitud Y (píxels)
|
||||
|
||||
@@ -485,21 +485,21 @@ constexpr float FLOAT_FREQUENCY_X_BASE = 0.5F; // Hz
|
||||
constexpr float FLOAT_FREQUENCY_Y_BASE = 0.7F; // Hz
|
||||
constexpr float FLOAT_PHASE_OFFSET = 1.57F; // π/2 (90°)
|
||||
|
||||
// Delays d'entrada (per a entrada escalonada)
|
||||
// Delays de entrada (per a entrada escalonada)
|
||||
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 después
|
||||
|
||||
// Delay global abans d'iniciar l'animació d'entrada al state MAIN
|
||||
constexpr float ENTRANCE_DELAY = 5.0F; // Temps d'espera abans que les naus entrin
|
||||
// Delay global antes de start l'animación de entrada al state MAIN
|
||||
constexpr float ENTRANCE_DELAY = 5.0F; // Temps de espera antes que las naves entrin
|
||||
|
||||
// Multiplicadors de freqüència per a cada ship (variació sutil ±12%)
|
||||
// Multiplicadors de freqüència para cada ship (variació sutil ±12%)
|
||||
constexpr float P1_FREQUENCY_MULTIPLIER = 0.88F; // 12% més lenta
|
||||
constexpr float P2_FREQUENCY_MULTIPLIER = 1.12F; // 12% més ràpida
|
||||
|
||||
} // namespace Ships
|
||||
|
||||
namespace Layout {
|
||||
// Posicions verticals (anclatges des del TOP de pantalla lògica, 0.0-1.0)
|
||||
// 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.75F; // "PRESS START TO PLAY"
|
||||
constexpr float COPYRIGHT1_POS = 0.90F; // Primera línia copyright
|
||||
@@ -508,21 +508,21 @@ constexpr float COPYRIGHT1_POS = 0.90F; // Primera línia copyright
|
||||
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'scale
|
||||
// Factors de scale
|
||||
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)
|
||||
// Espaiat entre caràcters (usado per VectorText)
|
||||
constexpr float TEXT_SPACING = 2.0F;
|
||||
} // namespace Layout
|
||||
} // namespace Title
|
||||
|
||||
// Floating score numbers (números flotants de puntuació)
|
||||
// Floating score numbers (números flotantes de puntuación)
|
||||
namespace FloatingScore {
|
||||
constexpr float LIFETIME = 2.0F; // Duració màxima (segons)
|
||||
constexpr float VELOCITY_Y = -30.0F; // Velocitat vertical (px/s, negatiu = amunt)
|
||||
constexpr float VELOCITY_X = 0.0F; // Velocitat horizontal (px/s)
|
||||
constexpr float VELOCITY_Y = -30.0F; // Velocidad vertical (px/s, negatiu = amunt)
|
||||
constexpr float VELOCITY_X = 0.0F; // Velocidad horizontal (px/s)
|
||||
constexpr float SCALE = 0.45F; // Escala del text (0.6 = 60% del marcador)
|
||||
constexpr float SPACING = 0.0F; // Espaiat entre caràcters
|
||||
constexpr int MAX_CONCURRENT = 15; // Pool size (= MAX_ORNIS)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// entitat.hpp - Classe base abstracta per a totes les entitats del joc
|
||||
// © 2025 Orni Attack - Arquitectura d'entitats
|
||||
// entity.hpp - Clase base abstracta para todas las entidades del juego
|
||||
// © 2025 Orni Attack - Arquitectura de entidades
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -22,25 +22,25 @@ class Entity {
|
||||
virtual void draw() const = 0;
|
||||
[[nodiscard]] virtual bool isActive() const = 0;
|
||||
|
||||
// Interfície de col·lisió (override opcional)
|
||||
// Interfície de colisión (override opcional)
|
||||
[[nodiscard]] virtual float getCollisionRadius() const { return 0.0F; }
|
||||
[[nodiscard]] virtual bool isCollidable() const { return false; }
|
||||
|
||||
// Getters comuns (inline, sense overhead)
|
||||
// Getters comuns (inline, sin overhead)
|
||||
[[nodiscard]] const Vec2& getCenter() const { return center_; }
|
||||
[[nodiscard]] float getAngle() const { return angle_; }
|
||||
[[nodiscard]] float getBrightness() const { return brightness_; }
|
||||
[[nodiscard]] const std::shared_ptr<Graphics::Shape>& getShape() const { return shape_; }
|
||||
|
||||
protected:
|
||||
// Estat comú (accés directe, sense overhead)
|
||||
// Estat comú (accés directe, sin overhead)
|
||||
SDL_Renderer* renderer_;
|
||||
std::shared_ptr<Graphics::Shape> shape_;
|
||||
Vec2 center_;
|
||||
float angle_{0.0F};
|
||||
float brightness_{1.0F};
|
||||
|
||||
// Constructor protegit (classe abstracta)
|
||||
// Constructor protegit (clase abstracta)
|
||||
Entity(SDL_Renderer* renderer = nullptr)
|
||||
: renderer_(renderer),
|
||||
center_({.x = 0.0F, .y = 0.0F}) {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape.cpp - Implementació del sistema de formes vectorials
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/graphics/shape.hpp"
|
||||
|
||||
@@ -18,14 +18,14 @@ Shape::Shape(const std::string& filepath)
|
||||
}
|
||||
|
||||
bool Shape::load(const std::string& filepath) {
|
||||
// Llegir fitxer
|
||||
// Llegir file
|
||||
std::ifstream file(filepath);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "[Shape] Error: no es pot obrir " << filepath << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Llegir tot el contingut
|
||||
// Llegir todo el contingut
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
std::string contingut = buffer.str();
|
||||
@@ -65,7 +65,7 @@ bool Shape::parseFile(const std::string& contingut) {
|
||||
if (points.size() >= 2) {
|
||||
primitives_.push_back({PrimitiveType::POLYLINE, points});
|
||||
} else {
|
||||
std::cerr << "[Shape] Warning: polyline amb menys de 2 points ignorada"
|
||||
std::cerr << "[Shape] Warning: polyline con menys de 2 points ignorada"
|
||||
<< '\n';
|
||||
}
|
||||
} else if (starts_with(line, "line:")) {
|
||||
@@ -81,7 +81,7 @@ bool Shape::parseFile(const std::string& contingut) {
|
||||
}
|
||||
|
||||
if (primitives_.empty()) {
|
||||
std::cerr << "[Shape] Error: cap primitiva carregada" << '\n';
|
||||
std::cerr << "[Shape] Error: sin primitiva carregada" << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ void Shape::parse_center(const std::string& value) {
|
||||
center_.x = std::stof(trim(val.substr(0, comma)));
|
||||
center_.y = std::stof(trim(val.substr(comma + 1)));
|
||||
} catch (...) {
|
||||
std::cerr << "[Shape] Warning: centre invàlid, usant (0,0)" << '\n';
|
||||
std::cerr << "[Shape] Warning: centro invàlid, usant (0,0)" << '\n';
|
||||
center_ = {.x = 0.0F, .y = 0.0F};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape.hpp - Sistema de formes vectorials
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Tipus de primitiva dins d'una shape
|
||||
// Tipo de primitiva dins de una shape
|
||||
enum class PrimitiveType {
|
||||
POLYLINE, // Seqüència de points connectats
|
||||
POLYLINE, // Secuencia de points connectats
|
||||
LINE // Línia individual (2 points)
|
||||
};
|
||||
|
||||
@@ -22,17 +22,17 @@ struct ShapePrimitive {
|
||||
std::vector<Vec2> points; // 2+ points per polyline, exactament 2 per line
|
||||
};
|
||||
|
||||
// Classe Shape - representa una shape vectorial carregada des de .shp
|
||||
// Clase Shape - representa una shape vectorial carregada desde .shp
|
||||
class Shape {
|
||||
public:
|
||||
// Constructors
|
||||
Shape() = default;
|
||||
explicit Shape(const std::string& filepath);
|
||||
|
||||
// Carregar shape des de fitxer .shp
|
||||
// Carregar shape desde file .shp
|
||||
bool load(const std::string& filepath);
|
||||
|
||||
// Parsejar shape des de buffer de memòria (per al sistema de recursos)
|
||||
// Parsejar shape desde buffer de memòria (per al sistema de recursos)
|
||||
bool parseFile(const std::string& contingut);
|
||||
|
||||
// Getters
|
||||
@@ -49,7 +49,7 @@ class Shape {
|
||||
|
||||
private:
|
||||
std::vector<ShapePrimitive> primitives_;
|
||||
Vec2 center_; // Centre/origen de la shape
|
||||
Vec2 center_; // Centro/origin de la shape
|
||||
float escala_defecte_; // Escala per defecte (normalment 1.0)
|
||||
std::string nom_; // Nom de la shape (per depuració)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape_loader.cpp - Implementació del carregador amb caché
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// shape_loader.cpp - Implementació del carregador con caché
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/graphics/shape_loader.hpp"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Inicialització de variables estàtiques
|
||||
// Inicialización de variables estàtiques
|
||||
std::unordered_map<std::string, std::shared_ptr<Shape>> ShapeLoader::cache_;
|
||||
std::string ShapeLoader::base_path_ = "data/shapes/";
|
||||
|
||||
@@ -69,17 +69,17 @@ void ShapeLoader::clear_cache() {
|
||||
size_t ShapeLoader::get_cache_size() { return cache_.size(); }
|
||||
|
||||
std::string ShapeLoader::resolve_path(const std::string& filename) {
|
||||
// Si és un path absolut (comença amb '/'), usar-lo directament
|
||||
// Si es un path absolut (comença con '/'), usar-lo directament
|
||||
if (!filename.empty() && filename[0] == '/') {
|
||||
return filename;
|
||||
}
|
||||
|
||||
// Si ja conté el prefix base_path, usar-lo directament
|
||||
// Si ya conté el prefix base_path, usar-lo directament
|
||||
if (filename.starts_with(base_path_)) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
// Altrament, afegir base_path (ara suporta subdirectoris)
|
||||
// Altrament, añadir base_path (ara suporta subdirectoris)
|
||||
return base_path_ + filename;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape_loader.hpp - Carregador estàtic de formes amb caché
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// shape_loader.hpp - Carregador estàtic de formes con caché
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Carregador estàtic de formes amb caché
|
||||
// Carregador estàtic de formes con caché
|
||||
class ShapeLoader {
|
||||
public:
|
||||
// No instanciable (tot estàtic)
|
||||
ShapeLoader() = delete;
|
||||
|
||||
// Carregar shape des de fitxer (amb caché)
|
||||
// Carregar shape desde file (con caché)
|
||||
// Retorna punter compartit (nullptr si error)
|
||||
// Exemple: load("ship.shp") → busca a "data/shapes/ship.shp"
|
||||
static std::shared_ptr<Shape> load(const std::string& filename);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// starfield.cpp - Implementació del sistema d'estrelles de fons
|
||||
// starfield.cpp - Implementació del sistema de estrelles de fons
|
||||
// © 2025 Orni Attack
|
||||
|
||||
#include "core/graphics/starfield.hpp"
|
||||
@@ -22,7 +22,7 @@ Starfield::Starfield(SDL_Renderer* renderer,
|
||||
punt_fuga_(punt_fuga),
|
||||
area_(area),
|
||||
densitat_(densitat) {
|
||||
// Carregar shape d'estrella amb ShapeLoader
|
||||
// Carregar shape de estrella con ShapeLoader
|
||||
shape_estrella_ = ShapeLoader::load("star.shp");
|
||||
|
||||
if (!shape_estrella_ || !shape_estrella_->isValid()) {
|
||||
@@ -30,22 +30,22 @@ Starfield::Starfield(SDL_Renderer* renderer,
|
||||
return;
|
||||
}
|
||||
|
||||
// Configurar 3 capes amb diferents velocitats i escales
|
||||
// Capa 0: Fons llunyà (lenta, petita)
|
||||
// Configurar 3 capes con diferents velocitats i escales
|
||||
// Capa 0: Fons llunyà (lenta, pequeña)
|
||||
capes_.push_back({20.0F, 0.3F, 0.8F, densitat / 3});
|
||||
|
||||
// Capa 1: Profunditat mitjana
|
||||
capes_.push_back({40.0F, 0.5F, 1.2F, densitat / 3});
|
||||
|
||||
// Capa 2: Primer pla (ràpida, gran)
|
||||
// Capa 2: Primer pla (ràpida, grande)
|
||||
capes_.push_back({80.0F, 0.8F, 2.0F, densitat / 3});
|
||||
|
||||
// Calcular radi màxim (distància del centre al racó més llunyà)
|
||||
// Calcular radi màxim (distancia del centro al racó més llunyà)
|
||||
float dx = std::max(punt_fuga_.x, area_.w - punt_fuga_.x);
|
||||
float dy = std::max(punt_fuga_.y, area_.h - punt_fuga_.y);
|
||||
radi_max_ = std::sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
// Inicialitzar estrelles amb posicions distribuïdes (pre-omplir pantalla)
|
||||
// Inicialitzar estrelles con posicions distribuïdes (pre-omplir pantalla)
|
||||
for (int capa_idx = 0; capa_idx < 3; capa_idx++) {
|
||||
int num = capes_[capa_idx].num_estrelles;
|
||||
for (int i = 0; i < num; i++) {
|
||||
@@ -55,10 +55,10 @@ Starfield::Starfield(SDL_Renderer* renderer,
|
||||
// Angle aleatori
|
||||
estrella.angle = (static_cast<float>(rand()) / RAND_MAX) * 2.0F * Defaults::Math::PI;
|
||||
|
||||
// Distància aleatòria (0.0 a 1.0) per omplir tota la pantalla
|
||||
// Distancia aleatòria (0.0 a 1.0) per omplir toda la pantalla
|
||||
estrella.distancia_centre = static_cast<float>(rand()) / RAND_MAX;
|
||||
|
||||
// Calcular posició des de la distància
|
||||
// Calcular posición desde la distancia
|
||||
float radi = estrella.distancia_centre * radi_max_;
|
||||
estrella.position.x = punt_fuga_.x + (radi * std::cos(estrella.angle));
|
||||
estrella.position.y = punt_fuga_.y + (radi * std::sin(estrella.angle));
|
||||
@@ -68,21 +68,21 @@ Starfield::Starfield(SDL_Renderer* renderer,
|
||||
}
|
||||
}
|
||||
|
||||
// Inicialitzar una estrella (nova o regenerada)
|
||||
// Inicialitzar una estrella (nueva o regenerada)
|
||||
void Starfield::inicialitzar_estrella(Estrella& estrella) const {
|
||||
// Angle aleatori des del point de fuga cap a fora
|
||||
// Angle aleatori des del point de fuga hacia fuera
|
||||
estrella.angle = (static_cast<float>(rand()) / RAND_MAX) * 2.0F * Defaults::Math::PI;
|
||||
|
||||
// Distància inicial petita (5% del radi màxim) - neix prop del centre
|
||||
// Distancia inicial pequeña (5% del radi màxim) - neix prop del centro
|
||||
estrella.distancia_centre = 0.05F;
|
||||
|
||||
// Posició inicial: molt prop del point de fuga
|
||||
// Posición inicial: mucho prop del point de fuga
|
||||
float radi = estrella.distancia_centre * radi_max_;
|
||||
estrella.position.x = punt_fuga_.x + (radi * std::cos(estrella.angle));
|
||||
estrella.position.y = punt_fuga_.y + (radi * std::sin(estrella.angle));
|
||||
}
|
||||
|
||||
// Verificar si una estrella està fora de l'àrea
|
||||
// Verificar si una estrella está fuera de l'àrea
|
||||
bool Starfield::fora_area(const Estrella& estrella) const {
|
||||
return (estrella.position.x < area_.x ||
|
||||
estrella.position.x > area_.x + area_.w ||
|
||||
@@ -90,20 +90,20 @@ bool Starfield::fora_area(const Estrella& estrella) const {
|
||||
estrella.position.y > area_.y + area_.h);
|
||||
}
|
||||
|
||||
// Calcular scale dinàmica segons distància del centre
|
||||
// Calcular scale dinàmica segons distancia del centro
|
||||
float Starfield::calcular_escala(const Estrella& estrella) const {
|
||||
const CapaConfig& capa = capes_[estrella.capa];
|
||||
|
||||
// Interpolació lineal basada en distància del centre
|
||||
// distancia_centre: 0.0 (centre) → 1.0 (vora)
|
||||
// Interpolació lineal basada en distancia del centro
|
||||
// distancia_centre: 0.0 (centro) → 1.0 (vora)
|
||||
return capa.escala_min +
|
||||
((capa.escala_max - capa.escala_min) * estrella.distancia_centre);
|
||||
}
|
||||
|
||||
// Calcular brightness dinàmica segons distància del centre
|
||||
// Calcular brightness dinàmica segons distancia del centro
|
||||
float Starfield::calcular_brightness(const Estrella& estrella) const {
|
||||
// Interpolació lineal: estrelles properes (vora) més brillants
|
||||
// distancia_centre: 0.0 (centre, llunyanes) → 1.0 (vora, properes)
|
||||
// distancia_centre: 0.0 (centro, llunyanes) → 1.0 (vora, properes)
|
||||
float brightness_base = Defaults::Brightness::STARFIELD_MIN +
|
||||
((Defaults::Brightness::STARFIELD_MAX - Defaults::Brightness::STARFIELD_MIN) *
|
||||
estrella.distancia_centre);
|
||||
@@ -112,13 +112,13 @@ float Starfield::calcular_brightness(const Estrella& estrella) const {
|
||||
return std::min(1.0F, brightness_base * multiplicador_brightness_);
|
||||
}
|
||||
|
||||
// Actualitzar posicions de les estrelles
|
||||
// Actualitzar posicions de las estrelles
|
||||
void Starfield::update(float delta_time) {
|
||||
for (auto& estrella : estrelles_) {
|
||||
// Obtenir configuració de la capa
|
||||
// Obtenir configuración de la capa
|
||||
const CapaConfig& capa = capes_[estrella.capa];
|
||||
|
||||
// Moure cap a fora des del centre
|
||||
// Moure hacia fuera des del centro
|
||||
float velocity = capa.velocitat_base;
|
||||
float dx = velocity * std::cos(estrella.angle) * delta_time;
|
||||
float dy = velocity * std::sin(estrella.angle) * delta_time;
|
||||
@@ -126,7 +126,7 @@ void Starfield::update(float delta_time) {
|
||||
estrella.position.x += dx;
|
||||
estrella.position.y += dy;
|
||||
|
||||
// Actualitzar distància del centre
|
||||
// Actualitzar distancia del centro
|
||||
float dx_centre = estrella.position.x - punt_fuga_.x;
|
||||
float dy_centre = estrella.position.y - punt_fuga_.y;
|
||||
float dist_px = std::sqrt((dx_centre * dx_centre) + (dy_centre * dy_centre));
|
||||
@@ -144,7 +144,7 @@ void Starfield::set_brightness(float multiplier) {
|
||||
multiplicador_brightness_ = std::max(0.0F, multiplier); // Evitar valors negatius
|
||||
}
|
||||
|
||||
// Dibuixar totes les estrelles
|
||||
// Dibuixar todas las estrelles
|
||||
void Starfield::draw() {
|
||||
if (!shape_estrella_->isValid()) {
|
||||
return;
|
||||
@@ -155,14 +155,14 @@ void Starfield::draw() {
|
||||
float scale = calcular_escala(estrella);
|
||||
float brightness = calcular_brightness(estrella);
|
||||
|
||||
// Renderitzar estrella sense rotació
|
||||
// Renderizar estrella sin rotación
|
||||
Rendering::render_shape(
|
||||
renderer_,
|
||||
shape_estrella_,
|
||||
estrella.position,
|
||||
0.0F, // angle (les estrelles no giren)
|
||||
0.0F, // angle (las estrelles no giren)
|
||||
scale, // scale dinàmica
|
||||
1.0F, // progress (sempre visible)
|
||||
1.0F, // progress (siempre visible)
|
||||
brightness // brightness dinàmica
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// starfield.hpp - Sistema d'estrelles de fons amb efecte de profunditat
|
||||
// starfield.hpp - Sistema de estrelles de fons con efecte de profunditat
|
||||
// © 2025 Orni Attack
|
||||
|
||||
#pragma once
|
||||
@@ -13,69 +13,69 @@
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Configuració per cada capa de profunditat
|
||||
// Configuración per cada capa de profunditat
|
||||
struct CapaConfig {
|
||||
float velocitat_base; // Velocitat base d'aquesta capa (px/s)
|
||||
float escala_min; // Escala mínima prop del centre
|
||||
float velocitat_base; // Velocidad base de esta capa (px/s)
|
||||
float escala_min; // Escala mínima prop del centro
|
||||
float escala_max; // Escala màxima al límit de pantalla
|
||||
int num_estrelles; // Nombre d'estrelles en aquesta capa
|
||||
int num_estrelles; // Nombre de estrelles en esta capa
|
||||
};
|
||||
|
||||
// Classe Starfield - camp d'estrelles animat amb efecte de profunditat
|
||||
// Clase Starfield - camp de estrelles animat con efecte de profunditat
|
||||
class Starfield {
|
||||
public:
|
||||
// Constructor
|
||||
// - renderer: SDL renderer
|
||||
// - punt_fuga: point d'origen/fuga des d'on surten les estrelles
|
||||
// - area: rectangle on actuen les estrelles (SDL_FRect)
|
||||
// - densitat: nombre total d'estrelles (es divideix entre capes)
|
||||
// - punt_fuga: point de origin/fuga des de on surten las estrelles
|
||||
// - area: rectangle on actuen las estrelles (SDL_FRect)
|
||||
// - densitat: nombre total de estrelles (es divideix entre capes)
|
||||
Starfield(SDL_Renderer* renderer,
|
||||
const Vec2& punt_fuga,
|
||||
const SDL_FRect& area,
|
||||
int densitat = 150);
|
||||
|
||||
// Actualitzar posicions de les estrelles
|
||||
// Actualitzar posicions de las estrelles
|
||||
void update(float delta_time);
|
||||
|
||||
// Dibuixar totes les estrelles
|
||||
// Dibuixar todas las estrelles
|
||||
void draw();
|
||||
|
||||
// Setters per ajustar paràmetres en time real
|
||||
// Setters per ajustar parámetros en time real
|
||||
void set_punt_fuga(const Vec2& point) { punt_fuga_ = point; }
|
||||
void set_brightness(float multiplier);
|
||||
|
||||
private:
|
||||
// Estructura interna per cada estrella
|
||||
struct Estrella {
|
||||
Vec2 position; // Posició actual
|
||||
float angle; // Angle de moviment (radians)
|
||||
float distancia_centre; // Distància normalitzada del centre (0.0-1.0)
|
||||
Vec2 position; // Posición actual
|
||||
float angle; // Angle de movement (radians)
|
||||
float distancia_centre; // Distancia normalitzada del centro (0.0-1.0)
|
||||
int capa; // Índex de capa (0=lluny, 1=mitjà, 2=prop)
|
||||
};
|
||||
|
||||
// Inicialitzar una estrella (nova o regenerada)
|
||||
// Inicialitzar una estrella (nueva o regenerada)
|
||||
void inicialitzar_estrella(Estrella& estrella) const;
|
||||
|
||||
// Verificar si una estrella està fora de l'àrea
|
||||
// Verificar si una estrella está fuera de l'àrea
|
||||
[[nodiscard]] bool fora_area(const Estrella& estrella) const;
|
||||
|
||||
// Calcular scale dinàmica segons distància del centre
|
||||
// Calcular scale dinàmica segons distancia del centro
|
||||
[[nodiscard]] float calcular_escala(const Estrella& estrella) const;
|
||||
|
||||
// Calcular brightness dinàmica segons distància del centre
|
||||
// Calcular brightness dinàmica segons distancia del centro
|
||||
[[nodiscard]] float calcular_brightness(const Estrella& estrella) const;
|
||||
|
||||
// Dades
|
||||
std::vector<Estrella> estrelles_;
|
||||
std::vector<CapaConfig> capes_; // Configuració de les 3 capes
|
||||
std::vector<CapaConfig> capes_; // Configuración de las 3 capes
|
||||
std::shared_ptr<Shape> shape_estrella_;
|
||||
SDL_Renderer* renderer_;
|
||||
|
||||
// Configuració
|
||||
Vec2 punt_fuga_; // Vec2 d'origen de les estrelles
|
||||
// Configuración
|
||||
Vec2 punt_fuga_; // Vec2 de origin de las estrelles
|
||||
SDL_FRect area_; // Àrea activa
|
||||
float radi_max_; // Distància màxima del centre al límit de pantalla
|
||||
int densitat_; // Nombre total d'estrelles
|
||||
float radi_max_; // Distancia màxima del centro al límit de pantalla
|
||||
int densitat_; // Nombre total de estrelles
|
||||
float multiplicador_brightness_{1.0F}; // Multiplicador de brightness (1.0 = default)
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// vector_text.cpp - Implementació del sistema de text vectorial
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
// Test pre-commit hook
|
||||
|
||||
#include "core/graphics/vector_text.hpp"
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Constants per a mides base dels caràcters
|
||||
// Constants para mides base dels caràcters
|
||||
constexpr float char_width = 20.0F; // Amplada base del caràcter
|
||||
constexpr float char_height = 40.0F; // Altura base del caràcter
|
||||
|
||||
@@ -63,7 +63,7 @@ void VectorText::load_charset() {
|
||||
}
|
||||
|
||||
// Cargar símbolo de copyright (©) - UTF-8 U+00A9
|
||||
// Usem el segon byte (0xA9) com a key interna
|
||||
// Usem el segon byte (0xA9) como a key interna
|
||||
{
|
||||
char c = '\xA9'; // 169 decimal
|
||||
std::string filename = "font/char_copyright.shp";
|
||||
@@ -82,7 +82,7 @@ void VectorText::load_charset() {
|
||||
}
|
||||
|
||||
std::string VectorText::get_shape_filename(char c) const {
|
||||
// Mapeo carácter → nombre de archivo (amb prefix "font/")
|
||||
// Mapeo carácter → nombre de archivo (con prefix "font/")
|
||||
switch (c) {
|
||||
case '0':
|
||||
case '1':
|
||||
@@ -168,7 +168,7 @@ std::string VectorText::get_shape_filename(char c) const {
|
||||
case '?':
|
||||
return "font/char_question.shp";
|
||||
case ' ':
|
||||
return ""; // Espai es maneja sense load shape
|
||||
return ""; // Espai es maneja sin load shape
|
||||
|
||||
case '\xA9': // Copyright symbol (©) - UTF-8 U+00A9
|
||||
return "font/char_copyright.shp";
|
||||
@@ -207,7 +207,7 @@ void VectorText::render(const std::string& text, const Vec2& position, float sca
|
||||
// Detectar copyright UTF-8 (0xC2 0xA9)
|
||||
if (c == 0xC2 && i + 1 < text.length() &&
|
||||
static_cast<unsigned char>(text[i + 1]) == 0xA9) {
|
||||
c = 0xA9; // Usar segon byte com a key
|
||||
c = 0xA9; // Usar segon byte como a key
|
||||
i++; // Saltar el següent byte
|
||||
}
|
||||
|
||||
@@ -242,13 +242,13 @@ void VectorText::renderCentered(const std::string& text, const Vec2& centre_punt
|
||||
float text_width = get_text_width(text, scale, spacing);
|
||||
float text_height = get_text_height(scale);
|
||||
|
||||
// Calcular posició de l'esquina superior esquerra
|
||||
// restant la meitat de les dimensions del point central
|
||||
// Calcular posición de l'esquina superior izquierda
|
||||
// restant la meitat de las dimensions del point central
|
||||
Vec2 posicio_esquerra = {
|
||||
.x = centre_punt.x - (text_width / 2.0F),
|
||||
.y = centre_punt.y - (text_height / 2.0F)};
|
||||
|
||||
// Delegar al mètode render() existent
|
||||
// Delegar al método render() existent
|
||||
render(text, posicio_esquerra, scale, spacing, brightness);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// vector_text.hpp - Sistema de texto vectorial con display de 7-segmentos
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ bool cursor_visible = false; // Estado del cursor (inicia ocult)
|
||||
// SDLManager controla esto mediante llamadas a setForceHidden().
|
||||
bool force_hidden = false;
|
||||
|
||||
// Temps d'inicialització per ignorar esdeveniments fantasma de SDL
|
||||
// Temps de inicialización per ignorar esdeveniments fantasma de SDL
|
||||
Uint32 initialization_time = 0;
|
||||
constexpr Uint32 IGNORE_MOTION_DURATION = 1000; // Ignorar primers 1000ms
|
||||
|
||||
@@ -24,7 +24,7 @@ void forceHide() {
|
||||
cursor_visible = false;
|
||||
last_mouse_move_time = 0;
|
||||
initialization_time = SDL_GetTicks(); // Marcar time per ignorar esdeveniments inicials
|
||||
std::cout << "[Mouse::forceHide] Ignorant moviments durant " << IGNORE_MOTION_DURATION << "ms" << '\n';
|
||||
std::cout << "[Mouse::forceHide] Ignorant moviments durante " << IGNORE_MOTION_DURATION << "ms" << '\n';
|
||||
}
|
||||
|
||||
void setForceHidden(bool force) {
|
||||
@@ -56,16 +56,16 @@ void handleEvent(const SDL_Event& event) {
|
||||
if (event.type == SDL_EVENT_MOUSE_MOTION) {
|
||||
Uint32 current_time = SDL_GetTicks();
|
||||
|
||||
// Ignorar esdeveniments fantasma de SDL durant el període inicial
|
||||
// Ignorar esdeveniments fantasma de SDL durante el període inicial
|
||||
if (initialization_time > 0 && (current_time - initialization_time < IGNORE_MOTION_DURATION)) {
|
||||
std::cout << "[Mouse::handleEvent] Ignorant moviment fantasma de SDL. time=" << current_time
|
||||
<< " (inicialització fa " << (current_time - initialization_time) << "ms)" << '\n';
|
||||
std::cout << "[Mouse::handleEvent] Ignorant movement fantasma de SDL. time=" << current_time
|
||||
<< " (inicialización hace " << (current_time - initialization_time) << "ms)" << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
last_mouse_move_time = current_time;
|
||||
if (!cursor_visible) {
|
||||
std::cout << "[Mouse::handleEvent] Mostrant cursor per moviment REAL. time=" << last_mouse_move_time << '\n';
|
||||
std::cout << "[Mouse::handleEvent] Mostrant cursor per movement REAL. time=" << last_mouse_move_time << '\n';
|
||||
SDL_ShowCursor();
|
||||
cursor_visible = true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// easing.hpp - Funcions d'interpolació i easing
|
||||
// easing.hpp - Funciones de interpolació i easing
|
||||
// © 2025 Orni Attack
|
||||
|
||||
#pragma once
|
||||
@@ -7,21 +7,21 @@ namespace Easing {
|
||||
|
||||
// Ease-out quadratic: empieza rápido, desacelera suavemente
|
||||
// t = progreso normalizado [0.0 - 1.0]
|
||||
// retorna valor interpolado [0.0 - 1.0]
|
||||
// retorna value interpolado [0.0 - 1.0]
|
||||
inline float ease_out_quad(float t) {
|
||||
return 1.0F - ((1.0F - t) * (1.0F - t));
|
||||
}
|
||||
|
||||
// Ease-in quadratic: empieza lento, acelera
|
||||
// t = progreso normalizado [0.0 - 1.0]
|
||||
// retorna valor interpolado [0.0 - 1.0]
|
||||
// retorna value interpolado [0.0 - 1.0]
|
||||
inline float ease_in_quad(float t) {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
// Ease-in-out quadratic: acelera al inicio, desacelera al final
|
||||
// t = progreso normalizado [0.0 - 1.0]
|
||||
// retorna valor interpolado [0.0 - 1.0]
|
||||
// retorna value interpolado [0.0 - 1.0]
|
||||
inline float ease_in_out_quad(float t) {
|
||||
return (t < 0.5F)
|
||||
? 2.0F * t * t
|
||||
@@ -30,7 +30,7 @@ inline float ease_in_out_quad(float t) {
|
||||
|
||||
// Ease-out cubic: desaceleración más suave que quadratic
|
||||
// t = progreso normalizado [0.0 - 1.0]
|
||||
// retorna valor interpolado [0.0 - 1.0]
|
||||
// retorna value interpolado [0.0 - 1.0]
|
||||
inline float ease_out_cubic(float t) {
|
||||
float t1 = 1.0F - t;
|
||||
return 1.0F - (t1 * t1 * t1);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// collision.hpp - Utilitats de detecció de col·lisions
|
||||
// collision.hpp - Utilitats de detecció de colisiones
|
||||
// © 2025 Orni Attack - Sistema de física
|
||||
|
||||
#pragma once
|
||||
@@ -8,18 +8,18 @@
|
||||
|
||||
namespace Physics {
|
||||
|
||||
// Comprovació genèrica de col·lisió entre dues entitats
|
||||
// Comprobación genèrica de colisión entre dues entidades
|
||||
inline bool check_collision(const Entities::Entity& a, const Entities::Entity& b, float amplifier = 1.0F) {
|
||||
// Comprovar si ambdós són col·lisionables
|
||||
if (!a.isCollidable() || !b.isCollidable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calcular radi combinat (amb amplificador per hitbox generós)
|
||||
// Calcular radi combinat (con amplificador per hitbox generós)
|
||||
float suma_radis = (a.getCollisionRadius() + b.getCollisionRadius()) * amplifier;
|
||||
float suma_radis_sq = suma_radis * suma_radis;
|
||||
|
||||
// Comprovació distància al quadrat (sense sqrt)
|
||||
// Comprobación distancia al cuadrado (sin sqrt)
|
||||
const Vec2& pos_a = a.getCenter();
|
||||
const Vec2& pos_b = b.getCenter();
|
||||
float dx = pos_a.x - pos_b.x;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// color_oscillator.cpp - Implementació d'oscil·lació de color
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// color_oscillator.cpp - Implementació de oscil·lació de color
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/rendering/color_oscillator.hpp"
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Rendering {
|
||||
|
||||
ColorOscillator::ColorOscillator()
|
||||
: accumulated_time_(0.0F) {
|
||||
// Inicialitzar amb el color mínim
|
||||
// Inicialitzar con el color mínim
|
||||
current_line_color_ = {.r = Defaults::Color::LINE_MIN_R,
|
||||
.g = Defaults::Color::LINE_MIN_G,
|
||||
.b = Defaults::Color::LINE_MIN_B,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// color_oscillator.hpp - Sistema d'oscil·lació de color per efecte CRT
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// color_oscillator.hpp - Sistema de oscil·lació de color per efecte CRT
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// coordinate_transform.cpp - Inicialització de variables globals
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// coordinate_transform.cpp - Inicialización de variables globals
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/rendering/coordinate_transform.hpp"
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
// Factor d'scale global (inicialitzat a 1.0 per defecte)
|
||||
// Factor de scale global (inicialitzat a 1.0 per defecte)
|
||||
float g_current_scale_factor = 1.0F;
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// coordinate_transform.hpp - Transformació de coordenades lògiques a físiques
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
// Factor d'scale global (actualitzat cada frame per SDLManager)
|
||||
// Factor de scale global (actualitzat cada frame per SDLManager)
|
||||
extern float g_current_scale_factor;
|
||||
|
||||
// Transforma coordenada lògica a física amb arrodoniment
|
||||
// Transforma coordenada lógica a física con arrodoniment
|
||||
inline int transform_x(int logical_x, float scale) {
|
||||
return static_cast<int>(std::round(logical_x * scale));
|
||||
}
|
||||
@@ -19,7 +19,7 @@ inline int transform_y(int logical_y, float scale) {
|
||||
return static_cast<int>(std::round(logical_y * scale));
|
||||
}
|
||||
|
||||
// Variant que usa el factor d'scale global
|
||||
// Variant que usa el factor de scale global
|
||||
inline int transform_x(int logical_x) {
|
||||
return transform_x(logical_x, g_current_scale_factor);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// line_renderer.cpp - Implementació de renderitzat de línies
|
||||
// © 1999 Visente i Sergi (versió Pascal)
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// line_renderer.cpp - Implementació de renderizado de línies
|
||||
// © 1999 Visente i Sergi (versión Pascal)
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/rendering/line_renderer.hpp"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// line_renderer.hpp - Renderitzat de línies
|
||||
// © 1999 Visente i Sergi (versió Pascal)
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// line_renderer.hpp - Renderizado de línies
|
||||
// © 1999 Visente i Sergi (versión Pascal)
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
#include <SDL3/SDL.h>
|
||||
@@ -11,7 +11,7 @@ namespace Rendering {
|
||||
// brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness).
|
||||
void linea(SDL_Renderer* renderer, int x1, int y1, int x2, int y2, float brightness = 1.0F);
|
||||
|
||||
// Estableix el color global de les línies (utilitzat per ColorOscillator).
|
||||
// Estableix el color global de las línies (utilitzat per ColorOscillator).
|
||||
void setLineColor(SDL_Color color);
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// sdl_manager.cpp - Implementació del gestor SDL3
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "sdl_manager.hpp"
|
||||
|
||||
@@ -38,13 +38,13 @@ SDLManager::SDLManager()
|
||||
// Calcular mida màxima des del display
|
||||
calculateMaxWindowSize();
|
||||
|
||||
// Construir títol dinàmic
|
||||
// Construir título dinàmic
|
||||
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, Project::VERSION, Project::COPYRIGHT);
|
||||
|
||||
// Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
|
||||
// Crear finestra CENTRADA (SDL ho hace automàticament con CENTERED)
|
||||
finestra_ =
|
||||
SDL_CreateWindow(window_title.c_str(), current_width_, current_height_,
|
||||
SDL_WINDOW_RESIZABLE // Permetre resize manual també
|
||||
SDL_WINDOW_RESIZABLE // Permetre resize manual también
|
||||
);
|
||||
|
||||
if (finestra_ == nullptr) {
|
||||
@@ -56,7 +56,7 @@ SDLManager::SDLManager()
|
||||
// IMPORTANT: Centrar explícitament la finestra
|
||||
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
|
||||
// Crear renderer amb acceleració
|
||||
// Crear renderer con aceleración
|
||||
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
|
||||
|
||||
if (renderer_ == nullptr) {
|
||||
@@ -66,7 +66,7 @@ SDLManager::SDLManager()
|
||||
return;
|
||||
}
|
||||
|
||||
// Aplicar configuració de V-Sync
|
||||
// Aplicar configuración de V-Sync
|
||||
SDL_SetRenderVSync(renderer_, Options::rendering.vsync);
|
||||
|
||||
// CRÍTIC: Configurar viewport scaling
|
||||
@@ -77,7 +77,7 @@ SDLManager::SDLManager()
|
||||
<< Defaults::Game::HEIGHT << ")" << '\n';
|
||||
}
|
||||
|
||||
// Constructor amb configuració
|
||||
// Constructor con configuración
|
||||
SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
: finestra_(nullptr),
|
||||
renderer_(nullptr),
|
||||
@@ -102,7 +102,7 @@ SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
// Calcular mida màxima des del display
|
||||
calculateMaxWindowSize();
|
||||
|
||||
// Construir títol dinàmic
|
||||
// Construir título dinàmic
|
||||
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, Project::VERSION, Project::COPYRIGHT);
|
||||
|
||||
// Configurar flags de la finestra
|
||||
@@ -120,12 +120,12 @@ SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
return;
|
||||
}
|
||||
|
||||
// Centrar explícitament la finestra (si no és fullscreen)
|
||||
// Centrar explícitament la finestra (si no es fullscreen)
|
||||
if (!is_fullscreen_) {
|
||||
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
// Crear renderer amb acceleració
|
||||
// Crear renderer con aceleración
|
||||
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
|
||||
|
||||
if (renderer_ == nullptr) {
|
||||
@@ -135,7 +135,7 @@ SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
return;
|
||||
}
|
||||
|
||||
// Aplicar configuració de V-Sync
|
||||
// Aplicar configuración de V-Sync
|
||||
SDL_SetRenderVSync(renderer_, Options::rendering.vsync);
|
||||
|
||||
// Configurar viewport scaling
|
||||
@@ -176,7 +176,7 @@ void SDLManager::calculateMaxWindowSize() {
|
||||
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display);
|
||||
|
||||
if (mode != nullptr) {
|
||||
// Deixar marge de 100px per a decoracions de l'OS
|
||||
// Deixar marge de 100px para decoracions de l'OS
|
||||
max_width_ = mode->w - 100;
|
||||
max_height_ = mode->h - 100;
|
||||
std::cout << "Display detectat: " << mode->w << "x" << mode->h
|
||||
@@ -253,9 +253,9 @@ void SDLManager::applyZoom(float new_zoom) {
|
||||
}
|
||||
|
||||
void SDLManager::updateLogicalPresentation() {
|
||||
// CANVIAT: Ja no usem SDL_SetRenderLogicalPresentation
|
||||
// CANVIAT: Ya no usem SDL_SetRenderLogicalPresentation
|
||||
// Ara renderitzem directament a resolució física per evitar pixelació irregular
|
||||
// El viewport amb letterbox es configura a updateViewport()
|
||||
// El viewport con letterbox es configura a updateViewport()
|
||||
updateViewport();
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ void SDLManager::updateViewport() {
|
||||
int scaled_width = static_cast<int>(std::round(Defaults::Game::WIDTH * scale));
|
||||
int scaled_height = static_cast<int>(std::round(Defaults::Game::HEIGHT * scale));
|
||||
|
||||
// Càlcul de letterbox (centrar l'àrea escalada)
|
||||
// Cálculo de letterbox (centrar l'àrea scaled)
|
||||
int offset_x = (current_width_ - scaled_width) / 2;
|
||||
int offset_y = (current_height_ - scaled_height) / 2;
|
||||
|
||||
@@ -273,7 +273,7 @@ void SDLManager::updateViewport() {
|
||||
offset_x = std::max(offset_x, 0);
|
||||
offset_y = std::max(offset_y, 0);
|
||||
|
||||
// Configurar viewport per al renderitzat
|
||||
// Configurar viewport per al renderizado
|
||||
SDL_Rect viewport = {offset_x, offset_y, scaled_width, scaled_height};
|
||||
SDL_SetRenderViewport(renderer_, &viewport);
|
||||
|
||||
@@ -283,7 +283,7 @@ void SDLManager::updateViewport() {
|
||||
}
|
||||
|
||||
void SDLManager::updateRenderingContext() const {
|
||||
// Actualitzar el factor d'scale global per a totes les funcions de renderitzat
|
||||
// Actualitzar el factor de scale global para todas las funciones de renderizado
|
||||
Rendering::g_current_scale_factor = zoom_factor_;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ void SDLManager::decreaseWindowSize() {
|
||||
}
|
||||
|
||||
void SDLManager::applyWindowSize(int new_width, int new_height) {
|
||||
// Obtenir posició actual ABANS del resize
|
||||
// Obtenir posición actual ABANS del resize
|
||||
int old_x;
|
||||
int old_y;
|
||||
SDL_GetWindowPosition(finestra_, &old_x, &old_y);
|
||||
@@ -324,7 +324,7 @@ void SDLManager::applyWindowSize(int new_width, int new_height) {
|
||||
current_height_ = new_height;
|
||||
|
||||
// CENTRADO INTEL·LIGENT (algoritme de pollo)
|
||||
// Calcular nova posició per mantenir la finestra centrada sobre si mateixa
|
||||
// Calcular nueva posición per mantenir la finestra centrada sobre si misma
|
||||
int delta_width = old_width - new_width;
|
||||
int delta_height = old_height - new_height;
|
||||
|
||||
@@ -332,13 +332,13 @@ void SDLManager::applyWindowSize(int new_width, int new_height) {
|
||||
int new_y = old_y + (delta_height / 2);
|
||||
|
||||
// Evitar que la finestra surti de la pantalla
|
||||
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
|
||||
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de título
|
||||
new_x = std::max(new_x, 0);
|
||||
new_y = std::max(new_y, TITLEBAR_HEIGHT);
|
||||
|
||||
SDL_SetWindowPosition(finestra_, new_x, new_y);
|
||||
|
||||
// Actualitzar viewport després del resize
|
||||
// Actualitzar viewport después del resize
|
||||
updateViewport();
|
||||
}
|
||||
|
||||
@@ -368,7 +368,7 @@ void SDLManager::toggleFullscreen() {
|
||||
Options::window.fullscreen = is_fullscreen_;
|
||||
|
||||
// Notificar al mòdul Mouse: Fullscreen requereix ocultació permanent del cursor.
|
||||
// Quan es surt de fullscreen, restaurar el comportament normal d'auto-ocultació.
|
||||
// Cuando es surt de fullscreen, restaurar el comportament normal de auto-ocultació.
|
||||
Mouse::setForceHidden(is_fullscreen_);
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ bool SDLManager::handleWindowEvent(const SDL_Event& event) {
|
||||
windowed_height_ = current_height_;
|
||||
}
|
||||
|
||||
// Actualitzar viewport després del resize manual
|
||||
// Actualitzar viewport después del resize manual
|
||||
updateViewport();
|
||||
|
||||
std::cout << "Finestra redimensionada: " << current_width_
|
||||
@@ -398,12 +398,12 @@ bool SDLManager::handleWindowEvent(const SDL_Event& event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) {
|
||||
void SDLManager::clear(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (renderer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// [MODIFICAT] Usar color oscil·lat del fons en lloc dels paràmetres
|
||||
// [MODIFICAT] Usar color oscil·lat del fons en lloc dels parámetros
|
||||
(void)r;
|
||||
(void)g;
|
||||
(void)b; // Suprimir warnings
|
||||
@@ -412,7 +412,7 @@ void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) {
|
||||
SDL_RenderClear(renderer_);
|
||||
}
|
||||
|
||||
void SDLManager::presenta() {
|
||||
void SDLManager::present() {
|
||||
if (renderer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +420,7 @@ void SDLManager::presenta() {
|
||||
SDL_RenderPresent(renderer_);
|
||||
}
|
||||
|
||||
// [NUEVO] Actualitzar colors amb oscil·lació
|
||||
// [NUEVO] Actualitzar colors con oscil·lació
|
||||
void SDLManager::updateColors(float delta_time) {
|
||||
color_oscillator_.update(delta_time);
|
||||
|
||||
@@ -428,7 +428,7 @@ void SDLManager::updateColors(float delta_time) {
|
||||
Rendering::setLineColor(color_oscillator_.getCurrentLineColor());
|
||||
}
|
||||
|
||||
// [NUEVO] Actualitzar comptador de FPS
|
||||
// [NUEVO] Actualitzar counter de FPS
|
||||
void SDLManager::updateFPS(float delta_time) {
|
||||
// Acumular time i frames
|
||||
fps_accumulator_ += delta_time;
|
||||
@@ -440,7 +440,7 @@ void SDLManager::updateFPS(float delta_time) {
|
||||
fps_frame_count_ = 0;
|
||||
fps_accumulator_ = 0.0F;
|
||||
|
||||
// Actualitzar títol de la finestra
|
||||
// Actualitzar título de la finestra
|
||||
std::string vsync_state = (Options::rendering.vsync == 1) ? "ON" : "OFF";
|
||||
std::string title = std::format("{} v{} ({}) - {} FPS - VSync: {}",
|
||||
Project::LONG_NAME,
|
||||
@@ -455,7 +455,7 @@ void SDLManager::updateFPS(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
// [NUEVO] Actualitzar títol de la finestra
|
||||
// [NUEVO] Actualitzar título de la finestra
|
||||
void SDLManager::setWindowTitle(const std::string& title) {
|
||||
if (finestra_ != nullptr) {
|
||||
SDL_SetWindowTitle(finestra_, title.c_str());
|
||||
@@ -476,6 +476,6 @@ void SDLManager::toggleVSync() {
|
||||
fps_accumulator_ = 0.0F;
|
||||
fps_frame_count_ = 0;
|
||||
|
||||
// Guardar configuració
|
||||
// Guardar configuración
|
||||
Options::saveToFile();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// sdl_manager.hpp - Gestor d'inicialització de SDL3
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// sdl_manager.hpp - Gestor de inicialización de SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#ifndef SDL_MANAGER_HPP
|
||||
#define SDL_MANAGER_HPP
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
@@ -14,7 +13,7 @@
|
||||
class SDLManager {
|
||||
public:
|
||||
SDLManager(); // Constructor per defecte (usa Defaults::)
|
||||
SDLManager(int width, int height, bool fullscreen); // Constructor amb configuració
|
||||
SDLManager(int width, int height, bool fullscreen); // Constructor con configuración
|
||||
~SDLManager();
|
||||
|
||||
// No permetre còpia ni assignació
|
||||
@@ -28,24 +27,24 @@ class SDLManager {
|
||||
void toggleVSync(); // F4
|
||||
bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED
|
||||
|
||||
// Funcions principals (renderitzat)
|
||||
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
||||
void presenta();
|
||||
// Funciones principals (renderizado)
|
||||
void clear(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
||||
void present();
|
||||
|
||||
// [NUEVO] Actualització de colors (oscil·lació)
|
||||
void updateColors(float delta_time);
|
||||
|
||||
// [NUEVO] Actualitzar comptador de FPS
|
||||
// [NUEVO] Actualitzar counter de FPS
|
||||
void updateFPS(float delta_time);
|
||||
|
||||
// Getters
|
||||
SDL_Renderer* getRenderer() { return renderer_; }
|
||||
[[nodiscard]] float getScaleFactor() const { return zoom_factor_; }
|
||||
|
||||
// [NUEVO] Actualitzar títol de la finestra
|
||||
// [NUEVO] Actualitzar título de la finestra
|
||||
void setWindowTitle(const std::string& title);
|
||||
|
||||
// [NUEVO] Actualitzar context de renderitzat (factor d'scale global)
|
||||
// [NUEVO] Actualitzar context de renderizado (factor de scale global)
|
||||
void updateRenderingContext() const;
|
||||
|
||||
private:
|
||||
@@ -70,16 +69,14 @@ class SDLManager {
|
||||
int windowed_height_; // Saved size before fullscreen
|
||||
float max_zoom_; // Maximum zoom (calculated from display)
|
||||
|
||||
// [NUEVO] Funcions internes
|
||||
// [NUEVO] Funciones internes
|
||||
void calculateMaxWindowSize(); // Llegir resolució del display
|
||||
void calculateMaxZoom(); // Calculate max zoom from display
|
||||
void applyZoom(float new_zoom); // Apply zoom and resize window
|
||||
void applyWindowSize(int width, int height); // Canviar mida + centrar
|
||||
void updateLogicalPresentation(); // Actualitzar viewport
|
||||
void updateViewport(); // Configurar viewport amb letterbox
|
||||
void updateViewport(); // Configurar viewport con letterbox
|
||||
|
||||
// [NUEVO] Oscil·lador de colors
|
||||
Rendering::ColorOscillator color_oscillator_;
|
||||
};
|
||||
|
||||
#endif // SDL_MANAGER_HPP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape_renderer.cpp - Implementació del renderitzat de formes
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// shape_renderer.cpp - Implementació del renderizado de formes
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "core/rendering/shape_renderer.hpp"
|
||||
|
||||
@@ -10,65 +10,65 @@
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
// Helper: aplicar rotació 3D a un point 2D (assumeix Z=0)
|
||||
// Helper: aplicar rotación 3D a un point 2D (assumeix Z=0)
|
||||
static Vec2 apply_3d_rotation(float x, float y, const Rotation3D& rot) {
|
||||
float z = 0.0F; // Tots els points 2D comencen a Z=0
|
||||
float z = 0.0F; // Todos los points 2D comencen a Z=0
|
||||
|
||||
// Pitch (rotació eix X): cabeceo arriba/baix
|
||||
// Pitch (rotación eix X): cabeceo arriba/baix
|
||||
float cos_pitch = std::cos(rot.pitch);
|
||||
float sin_pitch = std::sin(rot.pitch);
|
||||
float y1 = (y * cos_pitch) - (z * sin_pitch);
|
||||
float z1 = (y * sin_pitch) + (z * cos_pitch);
|
||||
|
||||
// Yaw (rotació eix Y): guiñada esquerra/dreta
|
||||
// Yaw (rotación eix Y): guiñada izquierda/derecha
|
||||
float cos_yaw = std::cos(rot.yaw);
|
||||
float sin_yaw = std::sin(rot.yaw);
|
||||
float x2 = (x * cos_yaw) + (z1 * sin_yaw);
|
||||
float z2 = (-x * sin_yaw) + (z1 * cos_yaw);
|
||||
|
||||
// Roll (rotació eix Z): alabeo lateral
|
||||
// Roll (rotación eix Z): alabeo lateral
|
||||
float cos_roll = std::cos(rot.roll);
|
||||
float sin_roll = std::sin(rot.roll);
|
||||
float x3 = (x2 * cos_roll) - (y1 * sin_roll);
|
||||
float y3 = (x2 * sin_roll) + (y1 * cos_roll);
|
||||
|
||||
// Proyecció perspectiva (Z-divide simple)
|
||||
// Naus volen cap al point de fuga (320, 240) a "infinit" (Z → +∞)
|
||||
// Z més gran = més lluny = més petit a pantalla
|
||||
// Naves quieren hacia el point de fuga (320, 240) a "infinit" (Z → +∞)
|
||||
// Z més grande = més lluny = més pequeño a pantalla
|
||||
constexpr float perspective_factor = 500.0F;
|
||||
float scale_factor = perspective_factor / (perspective_factor + z2);
|
||||
|
||||
return {.x = x3 * scale_factor, .y = y3 * scale_factor};
|
||||
}
|
||||
|
||||
// Helper: transformar un point amb rotació, scale i trasllació
|
||||
// Helper: transformar un point con rotación, scale i traslación
|
||||
static Vec2 transform_point(const Vec2& point, const Vec2& shape_centre, const Vec2& position, float angle, float scale, const Rotation3D* rotation_3d) {
|
||||
// 1. Centrar el point respecte al centre de la shape
|
||||
// 1. Centrar el point respecte al centro de la shape
|
||||
float centered_x = point.x - shape_centre.x;
|
||||
float centered_y = point.y - shape_centre.y;
|
||||
|
||||
// 2. Aplicar rotació 3D (si es proporciona)
|
||||
// 2. Aplicar rotación 3D (si es proporciona)
|
||||
if ((rotation_3d != nullptr) && rotation_3d->has_rotation()) {
|
||||
Vec2 rotated_3d = apply_3d_rotation(centered_x, centered_y, *rotation_3d);
|
||||
centered_x = rotated_3d.x;
|
||||
centered_y = rotated_3d.y;
|
||||
}
|
||||
|
||||
// 3. Aplicar scale al point (després de rotació 3D)
|
||||
// 3. Aplicar scale al point (después de rotación 3D)
|
||||
float scaled_x = centered_x * scale;
|
||||
float scaled_y = centered_y * scale;
|
||||
|
||||
// 4. Aplicar rotació 2D (Z-axis, tradicional)
|
||||
// IMPORTANT: En el sistema original, angle=0 apunta AMUNT (no dreta)
|
||||
// 4. Aplicar rotación 2D (Z-axis, tradicional)
|
||||
// IMPORTANT: En el sistema original, angle=0 apunta AMUNT (no derecha)
|
||||
// Per això usem (angle - PI/2) per compensar
|
||||
// Però aquí angle ja ve en el sistema correcte del joc
|
||||
// Pero aquí angle ya ve en el sistema correcte del juego
|
||||
float cos_a = std::cos(angle);
|
||||
float sin_a = std::sin(angle);
|
||||
|
||||
float rotated_x = (scaled_x * cos_a) - (scaled_y * sin_a);
|
||||
float rotated_y = (scaled_x * sin_a) + (scaled_y * cos_a);
|
||||
|
||||
// 5. Aplicar trasllació a posició mundial
|
||||
// 5. Aplicar traslación a posición mundial
|
||||
return {.x = rotated_x + position.x, .y = rotated_y + position.y};
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ void render_shape(SDL_Renderer* renderer,
|
||||
float progress,
|
||||
float brightness,
|
||||
const Rotation3D* rotation_3d) {
|
||||
// Verificar que la shape és vàlida
|
||||
// Verificar que la shape es vàlida
|
||||
if (!shape || !shape->isValid()) {
|
||||
return;
|
||||
}
|
||||
@@ -90,10 +90,10 @@ void render_shape(SDL_Renderer* renderer,
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtenir el centre de la shape per a transformacions
|
||||
// Obtenir el centro de la shape para transformacions
|
||||
const Vec2& shape_centre = shape->getCenter();
|
||||
|
||||
// Iterar sobre totes les primitives
|
||||
// Iterar sobre todas las primitives
|
||||
for (const auto& primitive : shape->get_primitives()) {
|
||||
if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
|
||||
// POLYLINE: connectar points consecutius
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// shape_renderer.hpp - Renderitzat de formes vectorials
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// shape_renderer.hpp - Renderizado de formes vectorials
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace Rendering {
|
||||
|
||||
// Estructura per rotacions 3D (pitch, yaw, roll)
|
||||
struct Rotation3D {
|
||||
float pitch; // Rotació eix X (cabeceo arriba/baix)
|
||||
float yaw; // Rotació eix Y (guiñada esquerra/dreta)
|
||||
float roll; // Rotació eix Z (alabeo lateral)
|
||||
float pitch; // Rotación eix X (cabeceo arriba/baix)
|
||||
float yaw; // Rotación eix Y (guiñada izquierda/derecha)
|
||||
float roll; // Rotación eix Z (alabeo lateral)
|
||||
|
||||
Rotation3D()
|
||||
: pitch(0.0F),
|
||||
@@ -32,13 +32,13 @@ struct Rotation3D {
|
||||
}
|
||||
};
|
||||
|
||||
// Renderitzar shape amb transformacions
|
||||
// Renderizar shape con transformacions
|
||||
// - renderer: SDL renderer
|
||||
// - shape: shape vectorial a draw
|
||||
// - position: posició del centre en coordenades mundials
|
||||
// - angle: rotació en radians (0 = amunt, sentit horari)
|
||||
// - scale: factor d'scale (1.0 = mida original)
|
||||
// - progress: progrés de l'animació (0.0-1.0, default 1.0 = tot visible)
|
||||
// - position: posición del centro en coordenades mundials
|
||||
// - angle: rotación en radians (0 = amunt, sentit horari)
|
||||
// - scale: factor de scale (1.0 = mida original)
|
||||
// - progress: progrés de l'animación (0.0-1.0, default 1.0 = tot visible)
|
||||
// - brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness)
|
||||
void render_shape(SDL_Renderer* renderer,
|
||||
const std::shared_ptr<Graphics::Shape>& shape,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// resource_helper.cpp - Implementació de funcions d'ajuda
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// resource_helper.cpp - Implementació de funciones de ajuda
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "resource_helper.hpp"
|
||||
|
||||
@@ -15,7 +15,7 @@ bool initializeResourceSystem(const std::string& pack_file, bool fallback) {
|
||||
return Loader::get().initialize(pack_file, fallback);
|
||||
}
|
||||
|
||||
// Carregar un fitxer
|
||||
// Carregar un file
|
||||
std::vector<uint8_t> loadFile(const std::string& filepath) {
|
||||
// Normalitzar la ruta
|
||||
std::string normalized = normalizePath(filepath);
|
||||
@@ -24,7 +24,7 @@ std::vector<uint8_t> loadFile(const std::string& filepath) {
|
||||
return Loader::get().loadResource(normalized);
|
||||
}
|
||||
|
||||
// Comprovar si existeix un fitxer
|
||||
// Comprovar si existeix un file
|
||||
bool fileExists(const std::string& filepath) {
|
||||
std::string normalized = normalizePath(filepath);
|
||||
return Loader::get().resourceExists(normalized);
|
||||
@@ -37,7 +37,7 @@ std::string getPackPath(const std::string& asset_path) {
|
||||
|
||||
// Eliminar rutes absolutes (detectar / o C:\ al principi)
|
||||
if (!path.empty() && path[0] == '/') {
|
||||
// Buscar "data/" i agafar el que ve després
|
||||
// Buscar "data/" i agafar el que ve después
|
||||
size_t data_pos = path.find("/data/");
|
||||
if (data_pos != std::string::npos) {
|
||||
path = path.substr(data_pos + 6); // Saltar "/data/"
|
||||
@@ -73,7 +73,7 @@ std::string normalizePath(const std::string& path) {
|
||||
return getPackPath(path);
|
||||
}
|
||||
|
||||
// Comprovar si hi ha paquet carregat
|
||||
// Comprovar si hay paquet carregat
|
||||
bool isPackLoaded() {
|
||||
return Loader::get().isPackLoaded();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// resource_helper.hpp - Funcions d'ajuda per gestió de recursos
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// resource_helper.hpp - Funciones de ajuda per gestió de recursos
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
// API simplificada i normalització de rutes
|
||||
|
||||
#pragma once
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
namespace Resource::Helper {
|
||||
|
||||
// Inicialització del sistema
|
||||
// Inicialización del sistema
|
||||
bool initializeResourceSystem(const std::string& pack_file, bool fallback);
|
||||
|
||||
// Càrrega de fitxers
|
||||
// Càrrega de archivos
|
||||
std::vector<uint8_t> loadFile(const std::string& filepath);
|
||||
bool fileExists(const std::string& filepath);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// resource_loader.cpp - Implementació del carregador de recursos
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "resource_loader.hpp"
|
||||
|
||||
@@ -25,12 +25,12 @@ bool Loader::initialize(const std::string& pack_file, bool enable_fallback) {
|
||||
if (!pack_->loadPack(pack_file)) {
|
||||
if (!fallback_enabled_) {
|
||||
std::cerr << "[ResourceLoader] ERROR FATAL: No es pot load " << pack_file
|
||||
<< " i el fallback està desactivat\n";
|
||||
<< " y el fallback está desactivat\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "[ResourceLoader] Paquet no trobat, usant fallback al sistema de fitxers\n";
|
||||
pack_.reset(); // No hi ha paquet
|
||||
std::cout << "[ResourceLoader] Paquet no trobat, usant fallback al sistema de archivos\n";
|
||||
pack_.reset(); // No hay paquet
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ std::vector<uint8_t> Loader::loadResource(const std::string& filename) {
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Si no està al paquet i no hi ha fallback, falla
|
||||
// Si no está al paquet y no hay fallback, falla
|
||||
if (!fallback_enabled_) {
|
||||
std::cerr << "[ResourceLoader] ERROR: Recurs no trobat al paquet i fallback desactivat: "
|
||||
<< filename << "\n";
|
||||
@@ -59,7 +59,7 @@ std::vector<uint8_t> Loader::loadResource(const std::string& filename) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback al sistema de fitxers
|
||||
// Fallback al sistema de archivos
|
||||
if (fallback_enabled_) {
|
||||
return loadFromFilesystem(filename);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ bool Loader::resourceExists(const std::string& filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Comprovar al sistema de fitxers si està activat el fallback
|
||||
// Comprovar al sistema de archivos si está activat el fallback
|
||||
if (fallback_enabled_) {
|
||||
std::string fullpath = base_path_.empty() ? "data/" + filename : base_path_ + "/data/" + filename;
|
||||
return std::filesystem::exists(fullpath);
|
||||
@@ -86,14 +86,14 @@ bool Loader::resourceExists(const std::string& filename) {
|
||||
// Validar el paquet
|
||||
bool Loader::validatePack() {
|
||||
if (!pack_) {
|
||||
std::cerr << "[ResourceLoader] Advertència: no hi ha paquet carregat per validar\n";
|
||||
std::cerr << "[ResourceLoader] Advertència: no hay paquet carregat per validar\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return pack_->validatePack();
|
||||
}
|
||||
|
||||
// Comprovar si hi ha paquet carregat
|
||||
// Comprovar si hay paquet carregat
|
||||
bool Loader::isPackLoaded() const {
|
||||
return pack_ != nullptr;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ std::string Loader::getBasePath() const {
|
||||
return base_path_;
|
||||
}
|
||||
|
||||
// Carregar des del sistema de fitxers (fallback)
|
||||
// Carregar des del sistema de archivos (fallback)
|
||||
std::vector<uint8_t> Loader::loadFromFilesystem(const std::string& filename) {
|
||||
// The filename is already normalized (e.g., "shapes/logo/letra_j.shp")
|
||||
// We need to prepend base_path + "data/"
|
||||
@@ -136,7 +136,7 @@ std::vector<uint8_t> Loader::loadFromFilesystem(const std::string& filename) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::cout << "[ResourceLoader] Carregat des del sistema de fitxers: " << fullpath << "\n";
|
||||
std::cout << "[ResourceLoader] Carregat des del sistema de archivos: " << fullpath << "\n";
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// resource_loader.hpp - Carregador de recursos (Singleton)
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// Coordina càrrega des del paquet i/o sistema de fitxers
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
// Coordina càrrega des del paquet i/o sistema de archivos
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -18,7 +18,7 @@ class Loader {
|
||||
// Singleton
|
||||
static Loader& get();
|
||||
|
||||
// Inicialització
|
||||
// Inicialización
|
||||
bool initialize(const std::string& pack_file, bool enable_fallback);
|
||||
|
||||
// Càrrega de recursos
|
||||
@@ -46,7 +46,7 @@ class Loader {
|
||||
bool fallback_enabled_ = false;
|
||||
std::string base_path_;
|
||||
|
||||
// Funcions auxiliars
|
||||
// Funciones auxiliars
|
||||
std::vector<uint8_t> loadFromFilesystem(const std::string& filename);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// resource_pack.cpp - Implementació del sistema d'empaquetament
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// resource_pack.cpp - Implementació del sistema de empaquetament
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "resource_pack.hpp"
|
||||
|
||||
@@ -30,11 +30,11 @@ void Pack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
|
||||
}
|
||||
|
||||
void Pack::decryptData(std::vector<uint8_t>& data, const std::string& key) {
|
||||
// XOR és simètric
|
||||
// XOR es simètric
|
||||
encryptData(data, key);
|
||||
}
|
||||
|
||||
// Llegir fitxer complet a memòria
|
||||
// Llegir file complet a memòria
|
||||
std::vector<uint8_t> Pack::readFile(const std::string& filepath) {
|
||||
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
@@ -54,7 +54,7 @@ std::vector<uint8_t> Pack::readFile(const std::string& filepath) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// Afegir un fitxer individual al paquet
|
||||
// Añadir un file individual al paquet
|
||||
bool Pack::addFile(const std::string& filepath, const std::string& pack_name) {
|
||||
auto file_data = readFile(filepath);
|
||||
if (file_data.empty()) {
|
||||
@@ -67,17 +67,17 @@ bool Pack::addFile(const std::string& filepath, const std::string& pack_name) {
|
||||
.size = file_data.size(),
|
||||
.checksum = calculateChecksum(file_data)};
|
||||
|
||||
// Afegir dades al bloc de dades
|
||||
// Añadir dades al bloc de dades
|
||||
data_.insert(data_.end(), file_data.begin(), file_data.end());
|
||||
|
||||
resources_[pack_name] = entry;
|
||||
|
||||
std::cout << "[ResourcePack] Afegit: " << pack_name << " (" << file_data.size()
|
||||
std::cout << "[ResourcePack] Añadido: " << pack_name << " (" << file_data.size()
|
||||
<< " bytes)\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Afegir tots els fitxers d'un directori recursivament
|
||||
// Añadir todos los archivos de un directori recursivament
|
||||
bool Pack::addDirectory(const std::string& dir_path,
|
||||
const std::string& base_path) {
|
||||
namespace fs = std::filesystem;
|
||||
@@ -100,7 +100,7 @@ bool Pack::addDirectory(const std::string& dir_path,
|
||||
// Convertir barres invertides a normals (Windows)
|
||||
std::ranges::replace(relative_path, '\\', '/');
|
||||
|
||||
// Saltar fitxers de desenvolupament
|
||||
// Saltar archivos de desenvolupament
|
||||
if (relative_path.find(".world") != std::string::npos ||
|
||||
relative_path.find(".tsx") != std::string::npos ||
|
||||
relative_path.find(".DS_Store") != std::string::npos ||
|
||||
@@ -134,7 +134,7 @@ bool Pack::savePack(const std::string& pack_file) {
|
||||
|
||||
// Escriure metadades de recursos
|
||||
for (const auto& [name, entry] : resources_) {
|
||||
// Nom del fitxer
|
||||
// Nom del file
|
||||
auto name_len = static_cast<uint32_t>(entry.filename.length());
|
||||
file.write(reinterpret_cast<const char*>(&name_len), sizeof(name_len));
|
||||
file.write(entry.filename.c_str(), name_len);
|
||||
@@ -149,7 +149,7 @@ bool Pack::savePack(const std::string& pack_file) {
|
||||
std::vector<uint8_t> encrypted_data = data_;
|
||||
encryptData(encrypted_data, DEFAULT_ENCRYPT_KEY);
|
||||
|
||||
// Escriure mida de dades i dades encriptades
|
||||
// Escriure mida de dades y dades encriptades
|
||||
auto data_size = static_cast<uint64_t>(encrypted_data.size());
|
||||
file.write(reinterpret_cast<const char*>(&data_size), sizeof(data_size));
|
||||
file.write(reinterpret_cast<const char*>(encrypted_data.data()), encrypted_data.size());
|
||||
@@ -160,7 +160,7 @@ bool Pack::savePack(const std::string& pack_file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Carregar paquet des de disc
|
||||
// Carregar paquet desde disc
|
||||
bool Pack::loadPack(const std::string& pack_file) {
|
||||
std::ifstream file(pack_file, std::ios::binary);
|
||||
if (!file) {
|
||||
@@ -180,7 +180,7 @@ bool Pack::loadPack(const std::string& pack_file) {
|
||||
uint32_t version;
|
||||
file.read(reinterpret_cast<char*>(&version), sizeof(version));
|
||||
if (version != VERSION) {
|
||||
std::cerr << "[ResourcePack] Error: versió incompatible (esperava " << VERSION
|
||||
std::cerr << "[ResourcePack] Error: versión incompatible (esperava " << VERSION
|
||||
<< ", trobat " << version << ")\n";
|
||||
return false;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ bool Pack::loadPack(const std::string& pack_file) {
|
||||
// Llegir metadades de recursos
|
||||
resources_.clear();
|
||||
for (uint32_t i = 0; i < resource_count; ++i) {
|
||||
// Nom del fitxer
|
||||
// Nom del file
|
||||
uint32_t name_len;
|
||||
file.read(reinterpret_cast<char*>(&name_len), sizeof(name_len));
|
||||
|
||||
@@ -250,7 +250,7 @@ std::vector<uint8_t> Pack::getResource(const std::string& filename) {
|
||||
std::cerr << "[ResourcePack] ADVERTÈNCIA: checksum invàlid per " << filename
|
||||
<< " (esperat " << entry.checksum << ", calculat " << computed_checksum
|
||||
<< ")\n";
|
||||
// No falla, però adverteix
|
||||
// No falla, pero adverteix
|
||||
}
|
||||
|
||||
return resource_data;
|
||||
@@ -261,7 +261,7 @@ bool Pack::hasResource(const std::string& filename) const {
|
||||
return resources_.contains(filename);
|
||||
}
|
||||
|
||||
// Obtenir llista de tots els recursos
|
||||
// Obtenir list de todos los recursos
|
||||
std::vector<std::string> Pack::getResourceList() const {
|
||||
std::vector<std::string> list;
|
||||
list.reserve(resources_.size());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// resource_pack.hpp - Sistema d'empaquetament de recursos
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// Basat en el sistema de "pollo" amb adaptacions per Orni Attack
|
||||
// resource_pack.hpp - Sistema de empaquetament de recursos
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
// Basat en el sistema de "pollo" con adaptacions per Orni Attack
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -11,27 +11,27 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Capçalera del fitxer de paquet
|
||||
// Capçalera del file de paquet
|
||||
struct PackHeader {
|
||||
char magic[4]; // "ORNI"
|
||||
uint32_t version; // Versió del format (1)
|
||||
uint32_t version; // Versión del format (1)
|
||||
};
|
||||
|
||||
// Entrada de recurs dins el paquet
|
||||
struct ResourceEntry {
|
||||
std::string filename; // Nom del recurs (amb barres normals)
|
||||
uint64_t offset; // Posició dins el bloc de dades
|
||||
std::string filename; // Nom del recurs (con barres normals)
|
||||
uint64_t offset; // Posición dins el bloc de dades
|
||||
uint64_t size; // Mida en bytes
|
||||
uint32_t checksum; // Checksum CRC32 per verificació
|
||||
};
|
||||
|
||||
// Classe principal per gestionar paquets de recursos
|
||||
// Clase principal per gestionar paquets de recursos
|
||||
class Pack {
|
||||
public:
|
||||
Pack() = default;
|
||||
~Pack() = default;
|
||||
|
||||
// Afegir fitxers al paquet
|
||||
// Añadir archivos al paquet
|
||||
bool addFile(const std::string& filepath, const std::string& pack_name);
|
||||
bool addDirectory(const std::string& dir_path, const std::string& base_path = "");
|
||||
|
||||
@@ -57,7 +57,7 @@ class Pack {
|
||||
std::unordered_map<std::string, ResourceEntry> resources_;
|
||||
std::vector<uint8_t> data_;
|
||||
|
||||
// Funcions auxiliars
|
||||
// Funciones auxiliars
|
||||
std::vector<uint8_t> readFile(const std::string& filepath);
|
||||
[[nodiscard]] uint32_t calculateChecksum(const std::vector<uint8_t>& data) const;
|
||||
void encryptData(std::vector<uint8_t>& data, const std::string& key);
|
||||
|
||||
@@ -36,7 +36,7 @@ using SceneType = SceneContext::SceneType;
|
||||
Director::Director(std::vector<std::string> const& args) {
|
||||
std::cout << "Orni Attack - Inici\n";
|
||||
|
||||
// Inicialitzar opcions amb valors per defecte
|
||||
// Inicialitzar opciones con valors per defecte
|
||||
Options::init();
|
||||
|
||||
// Comprovar arguments del programa
|
||||
@@ -50,28 +50,28 @@ Director::Director(std::vector<std::string> const& args) {
|
||||
|
||||
// Inicialitzar sistema de recursos
|
||||
#ifdef RELEASE_BUILD
|
||||
// Mode release: paquet obligatori, sense fallback
|
||||
// Mode release: paquet obligatori, sin fallback
|
||||
std::string pack_path = resource_base + "/resources.pack";
|
||||
if (!Resource::Helper::initializeResourceSystem(pack_path, false)) {
|
||||
std::cerr << "ERROR FATAL: No es pot load " << pack_path << "\n";
|
||||
std::cerr << "El joc no pot continuar sense els recursos.\n";
|
||||
std::cerr << "El juego no pot continuar sin los recursos.\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Validar integritat del paquet
|
||||
if (!Resource::Loader::get().validatePack()) {
|
||||
std::cerr << "ERROR FATAL: El paquet de recursos està corromput\n";
|
||||
std::cerr << "ERROR FATAL: El paquet de recursos está corromput\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
std::cout << "Sistema de recursos inicialitzat (mode release)\n";
|
||||
#else
|
||||
// Mode desenvolupament: intentar paquet amb fallback a data/
|
||||
// Mode desenvolupament: intentar paquet con fallback a data/
|
||||
std::string pack_path = resource_base + "/resources.pack";
|
||||
Resource::Helper::initializeResourceSystem(pack_path, true);
|
||||
|
||||
if (Resource::Helper::isPackLoaded()) {
|
||||
std::cout << "Sistema de recursos inicialitzat (mode dev amb paquet)\n";
|
||||
std::cout << "Sistema de recursos inicialitzat (mode dev con paquet)\n";
|
||||
} else {
|
||||
std::cout << "Sistema de recursos inicialitzat (mode dev, fallback a data/)\n";
|
||||
}
|
||||
@@ -84,21 +84,21 @@ Director::Director(std::vector<std::string> const& args) {
|
||||
createSystemFolder("jailgames");
|
||||
createSystemFolder(std::string("jailgames/") + Project::NAME);
|
||||
|
||||
// Establir ruta del fitxer de configuració
|
||||
// Establir ruta del file de configuración
|
||||
Options::setConfigFile(system_folder_ + "/config.yaml");
|
||||
|
||||
// Carregar o crear configuració
|
||||
// Carregar o crear configuración
|
||||
Options::loadFromFile();
|
||||
|
||||
// Inicialitzar sistema d'input
|
||||
// Inicialitzar sistema de input
|
||||
Input::init("data/gamecontrollerdb.txt");
|
||||
|
||||
// Aplicar configuració de controls dels jugadors
|
||||
// Aplicar configuración de controls dels jugadors
|
||||
Input::get()->applyPlayer1BindingsFromOptions();
|
||||
Input::get()->applyPlayer2BindingsFromOptions();
|
||||
|
||||
if (Options::console) {
|
||||
std::cout << "Configuració carregada\n";
|
||||
std::cout << "Configuración carregada\n";
|
||||
std::cout << " Finestra: " << Options::window.width << "×"
|
||||
<< Options::window.height << '\n';
|
||||
std::cout << " Física: rotation=" << Options::physics.rotation_speed
|
||||
@@ -111,7 +111,7 @@ Director::Director(std::vector<std::string> const& args) {
|
||||
}
|
||||
|
||||
Director::~Director() {
|
||||
// Guardar opcions
|
||||
// Guardar opciones
|
||||
Options::saveToFile();
|
||||
|
||||
// Cleanup input
|
||||
@@ -138,7 +138,7 @@ auto Director::checkProgramArguments(std::vector<std::string> const& args)
|
||||
} else if (argument == "--reset-config") {
|
||||
Options::init();
|
||||
Options::saveToFile();
|
||||
std::cout << "Configuració restablida als valors per defecte\n";
|
||||
std::cout << "Configuración restablida als valors per defecte\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ void Director::createSystemFolder(const std::string& folder) {
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case EEXIST:
|
||||
// La carpeta ja existeix (race condition), continuar
|
||||
// La carpeta ya existeix (race condition), continuar
|
||||
break;
|
||||
|
||||
case ENAMETOOLONG:
|
||||
@@ -207,7 +207,7 @@ void Director::createSystemFolder(const std::string& folder) {
|
||||
}
|
||||
}
|
||||
|
||||
// Bucle principal del joc
|
||||
// Bucle principal del juego
|
||||
auto Director::run() -> int {
|
||||
// Calculate initial size from saved zoom_factor
|
||||
int initial_width = static_cast<int>(std::round(
|
||||
@@ -215,16 +215,16 @@ auto Director::run() -> int {
|
||||
int initial_height = static_cast<int>(std::round(
|
||||
Defaults::Window::HEIGHT * Options::window.zoom_factor));
|
||||
|
||||
// Crear gestor SDL amb configuració de Options
|
||||
// Crear gestor SDL con configuración de Options
|
||||
SDLManager sdl(initial_width, initial_height, Options::window.fullscreen);
|
||||
|
||||
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de tota la inicialització SDL
|
||||
// Això evita que SDL mostre el cursor automàticament durant la creació de la finestra
|
||||
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de toda la inicialización SDL
|
||||
// Això evita que SDL mostre el cursor automàticament durante la creació de la finestra
|
||||
if (!Options::window.fullscreen) {
|
||||
Mouse::forceHide();
|
||||
}
|
||||
|
||||
// Inicialitzar sistema d'audio
|
||||
// Inicialitzar sistema de audio
|
||||
Audio::init();
|
||||
Audio::get()->setMusicVolume(1.0);
|
||||
Audio::get()->setSoundVolume(0.4);
|
||||
@@ -234,10 +234,10 @@ auto Director::run() -> int {
|
||||
AudioCache::getMusic("game.ogg");
|
||||
if (Options::console) {
|
||||
std::cout << "Música precachejada: "
|
||||
<< AudioCache::getMusicCacheSize() << " fitxers\n";
|
||||
<< AudioCache::getMusicCacheSize() << " archivos\n";
|
||||
}
|
||||
|
||||
// Crear context d'escenes
|
||||
// Crear context de escenes
|
||||
SceneContext context;
|
||||
#ifdef _DEBUG
|
||||
context.setNextScene(SceneType::TITLE);
|
||||
@@ -245,10 +245,10 @@ auto Director::run() -> int {
|
||||
context.setNextScene(SceneType::LOGO);
|
||||
#endif
|
||||
|
||||
// Bucle principal de gestió d'escenes
|
||||
// Bucle principal de gestió de escenes
|
||||
while (context.nextScene() != SceneType::EXIT) {
|
||||
// Sincronitzar SceneManager::actual amb context
|
||||
// (altres sistemes encara poden llegir SceneManager::actual)
|
||||
// Sincronitzar SceneManager::actual con context
|
||||
// (altres sistemes aún poden llegir SceneManager::actual)
|
||||
SceneManager::actual = context.nextScene();
|
||||
|
||||
switch (context.nextScene()) {
|
||||
@@ -265,8 +265,8 @@ auto Director::run() -> int {
|
||||
}
|
||||
|
||||
case SceneType::GAME: {
|
||||
GameScene joc(sdl, context);
|
||||
joc.run();
|
||||
GameScene juego(sdl, context);
|
||||
juego.run();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ auto Director::run() -> int {
|
||||
}
|
||||
}
|
||||
|
||||
// Sincronitzar final amb SceneManager::actual
|
||||
// Sincronitzar final con SceneManager::actual
|
||||
SceneManager::actual = SceneType::EXIT;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -4,32 +4,32 @@
|
||||
|
||||
namespace GameConfig {
|
||||
|
||||
// Mode de joc
|
||||
// Mode de juego
|
||||
enum class Mode {
|
||||
NORMAL, // Partida normal
|
||||
DEMO // Mode demostració (futur)
|
||||
};
|
||||
|
||||
// Configuració d'una match
|
||||
// Configuración de una match
|
||||
struct MatchConfig {
|
||||
bool jugador1_actiu{false}; // És active el player 1?
|
||||
bool jugador2_actiu{false}; // És active el player 2?
|
||||
Mode mode{Mode::NORMAL}; // Mode de joc
|
||||
bool jugador1_actiu{false}; // Es active el player 1?
|
||||
bool jugador2_actiu{false}; // Es active el player 2?
|
||||
Mode mode{Mode::NORMAL}; // Mode de juego
|
||||
|
||||
// Mètodes auxiliars
|
||||
// Métodos auxiliars
|
||||
|
||||
// Retorna true si només hi ha un player active
|
||||
// Retorna true si solo hay un player active
|
||||
[[nodiscard]] bool es_un_jugador() const {
|
||||
return (jugador1_actiu && !jugador2_actiu) ||
|
||||
(!jugador1_actiu && jugador2_actiu);
|
||||
}
|
||||
|
||||
// Retorna true si hi ha dos jugadors active
|
||||
// Retorna true si hay dos jugadors active
|
||||
[[nodiscard]] bool son_dos_jugadors() const {
|
||||
return jugador1_actiu && jugador2_actiu;
|
||||
}
|
||||
|
||||
// Retorna true si no hi ha cap player active
|
||||
// Retorna true si no hay sin player active
|
||||
[[nodiscard]] bool cap_jugador() const {
|
||||
return !jugador1_actiu && !jugador2_actiu;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ struct MatchConfig {
|
||||
}
|
||||
|
||||
// Retorna l'ID de l'únic player active (0 o 1)
|
||||
// Només vàlid si es_un_jugador() retorna true
|
||||
// Solo vàlid si es_un_jugador() retorna true
|
||||
[[nodiscard]] uint8_t id_unic_jugador() const {
|
||||
if (jugador1_actiu && !jugador2_actiu) {
|
||||
return 0;
|
||||
@@ -48,7 +48,7 @@ struct MatchConfig {
|
||||
if (!jugador1_actiu && jugador2_actiu) {
|
||||
return 1;
|
||||
}
|
||||
return 0; // Fallback (cal comprovar es_un_jugador() primer)
|
||||
return 0; // Fallback (necesario comprovar es_un_jugador() primer)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// global_events.hpp - Events globals del joc
|
||||
// global_events.hpp - Events globals del juego
|
||||
// Basat en el patró del projecte "pollo"
|
||||
// © 2025 Port a C++20
|
||||
|
||||
@@ -14,6 +14,6 @@ class SceneContext;
|
||||
|
||||
namespace GlobalEvents {
|
||||
// Processa events globals (F1/F2/F3/ESC/QUIT)
|
||||
// Retorna true si l'event ha state processat i no cal seguir processant-lo
|
||||
// Retorna true si l'event ha state processat y no necesario seguir processant-lo
|
||||
bool handle(const SDL_Event& event, SDLManager& sdl, SceneManager::SceneContext& context);
|
||||
} // namespace GlobalEvents
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// context_escenes.hpp - Sistema de gestió d'escenes i context de transicions
|
||||
// scene_context.hpp - Sistema de gestió de escenes i context de transiciones
|
||||
// © 2025 Port a C++20
|
||||
|
||||
#pragma once
|
||||
@@ -7,29 +7,29 @@
|
||||
|
||||
namespace SceneManager {
|
||||
|
||||
// Context de transició entre escenes
|
||||
// Conté l'escena destinació i opcions específiques per aquella escena
|
||||
// Context de transición entre escenes
|
||||
// Conté l'escena destinació i opciones específiques per aquella escena
|
||||
class SceneContext {
|
||||
public:
|
||||
// Tipus d'escena del joc
|
||||
// Tipo de escena del juego
|
||||
enum class SceneType {
|
||||
LOGO, // Pantalla d'inici (logo JAILGAMES)
|
||||
TITLE, // Pantalla de títol amb menú
|
||||
GAME, // Joc principal (Asteroids)
|
||||
EXIT // Sortir del programa
|
||||
LOGO, // Pantalla de start (logo JAILGAMES)
|
||||
TITLE, // Pantalla de título con menú
|
||||
GAME, // Juego principal (Asteroids)
|
||||
EXIT // Salir del programa
|
||||
};
|
||||
|
||||
// Opcions específiques per a cada escena
|
||||
// Opciones específiques para cada escena
|
||||
enum class Option {
|
||||
NONE, // Sense opcions especials (comportament per defecte)
|
||||
NONE, // Sin opciones especials (comportament per defecte)
|
||||
JUMP_TO_TITLE_MAIN, // TITLE: Saltar directament a MAIN (starfield instantani)
|
||||
// MODE_DEMO, // GAME: Mode demostració amb IA (futur)
|
||||
// MODE_DEMO, // GAME: Mode demostració con IA (futur)
|
||||
};
|
||||
|
||||
// Constructor inicial amb escena LOGO i sense opcions
|
||||
// Constructor inicial con escena LOGO i sin opciones
|
||||
SceneContext() = default;
|
||||
|
||||
// Canviar escena amb opció específica
|
||||
// Canviar escena con opción específica
|
||||
void setNextScene(SceneType next_scene, Option option = Option::NONE) {
|
||||
next_scene_ = next_scene;
|
||||
option_ = option;
|
||||
@@ -40,42 +40,42 @@ class SceneContext {
|
||||
return next_scene_;
|
||||
}
|
||||
|
||||
// Consultar opció actual
|
||||
// Consultar opción actual
|
||||
[[nodiscard]] auto option() const -> Option {
|
||||
return option_;
|
||||
}
|
||||
|
||||
// Consumir opció (retorna valor i reseteja a NONE)
|
||||
// Utilitzar quan l'escena processa l'opció
|
||||
// Consumir opción (retorna value i reseteja a NONE)
|
||||
// Utilitzar cuando l'escena processa l'opción
|
||||
[[nodiscard]] auto consumeOption() -> Option {
|
||||
Option valor = option_;
|
||||
Option value = option_;
|
||||
option_ = Option::NONE;
|
||||
return valor;
|
||||
return value;
|
||||
}
|
||||
|
||||
// Reset opció a NONE (sense retornar valor)
|
||||
// Reset opción a NONE (sin retornar value)
|
||||
void resetOption() {
|
||||
option_ = Option::NONE;
|
||||
}
|
||||
|
||||
// Configurar match abans de transicionar a GAME
|
||||
// Configurar match antes de transicionar a GAME
|
||||
void setMatchConfig(const GameConfig::MatchConfig& config) {
|
||||
match_config_ = config;
|
||||
}
|
||||
|
||||
// Obtenir configuració de match (consumit per GameScene)
|
||||
// Obtenir configuración de match (consumit per GameScene)
|
||||
[[nodiscard]] const GameConfig::MatchConfig& getMatchConfig() const {
|
||||
return match_config_;
|
||||
}
|
||||
|
||||
private:
|
||||
SceneType next_scene_{SceneType::LOGO}; // SceneType a la qual transicionar
|
||||
Option option_{Option::NONE}; // Opció específica per l'escena
|
||||
GameConfig::MatchConfig match_config_; // Configuració de match (jugadors active, mode)
|
||||
Option option_{Option::NONE}; // Opción específica per l'escena
|
||||
GameConfig::MatchConfig match_config_; // Configuración de match (jugadors active, mode)
|
||||
};
|
||||
|
||||
// Variable global inline per gestionar l'escena actual (backward compatibility)
|
||||
// Sincronitzada amb context.nextScene() pel Director
|
||||
// Sincronitzada con context.nextScene() por el Director
|
||||
inline SceneContext::SceneType actual = SceneContext::SceneType::LOGO;
|
||||
|
||||
} // namespace SceneManager
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// path_utils.cpp - Implementació de utilitats de rutes
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
|
||||
#include "path_utils.hpp"
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace Utils {
|
||||
static std::string executable_path_;
|
||||
static std::string executable_directory_;
|
||||
|
||||
// Inicialitzar el sistema de rutes amb argv[0]
|
||||
// Inicialitzar el sistema de rutes con argv[0]
|
||||
void initializePathSystem(const char* argv0) {
|
||||
if (argv0 == nullptr) {
|
||||
std::cerr << "[PathUtils] ADVERTÈNCIA: argv[0] és nullptr\n";
|
||||
std::cerr << "[PathUtils] ADVERTÈNCIA: argv[0] es nullptr\n";
|
||||
executable_path_ = "";
|
||||
executable_directory_ = ".";
|
||||
return;
|
||||
@@ -50,7 +50,7 @@ bool isMacOSBundle() {
|
||||
#ifdef MACOS_BUNDLE
|
||||
return true;
|
||||
#else
|
||||
// Detecció en time d'execució
|
||||
// Detecció en time de execució
|
||||
// Cercar ".app/Contents/MacOS" a la ruta de l'executable
|
||||
std::string exe_dir = getExecutableDirectory();
|
||||
return exe_dir.find(".app/Contents/MacOS") != std::string::npos;
|
||||
@@ -62,10 +62,10 @@ std::string getResourceBasePath() {
|
||||
std::string exe_dir = getExecutableDirectory();
|
||||
|
||||
if (isMacOSBundle()) {
|
||||
// Bundle de macOS: recursos a ../Resources des de MacOS/
|
||||
// Bundle de macOS: recursos a ../Resources desde MacOS/
|
||||
std::cout << "[PathUtils] Detectat bundle de macOS\n";
|
||||
return exe_dir + "/../Resources";
|
||||
} // Executable normal: recursos al mateix directori
|
||||
} // Executable normal: recursos al mismo directori
|
||||
return exe_dir;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ std::string normalizePath(const std::string& path) {
|
||||
// Convertir barres invertides a normals
|
||||
std::ranges::replace(normalized, '\\', '/');
|
||||
|
||||
// Simplificar rutes amb filesystem
|
||||
// Simplificar rutes con filesystem
|
||||
try {
|
||||
std::filesystem::path fs_path(normalized);
|
||||
normalized = fs_path.lexically_normal().string();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// path_utils.hpp - Utilitats de gestió de rutes
|
||||
// © 2025 Port a C++20 amb SDL3
|
||||
// © 2025 Port a C++20 con SDL3
|
||||
// Detecció de directoris i bundles multiplataforma
|
||||
|
||||
#pragma once
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// Inicialització amb argv[0]
|
||||
// Inicialización con argv[0]
|
||||
void initializePathSystem(const char* argv0);
|
||||
|
||||
// Obtenció de rutes
|
||||
|
||||
Reference in New Issue
Block a user