Compare commits
7 Commits
1a0cc504c4
..
v0.8.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 491992a4d7 | |||
| e5b727216c | |||
| f03e337b9a | |||
| 99e99e7e08 | |||
| b93761eb1e | |||
| 4f5421191d | |||
| 71ed9dc24f |
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(orni VERSION 0.8.0 LANGUAGES CXX)
|
project(orni VERSION 0.8.1 LANGUAGES CXX)
|
||||||
|
|
||||||
# Info del projecte (font de veritat per a project.h)
|
# Info del projecte (font de veritat per a project.h)
|
||||||
set(PROJECT_LONG_NAME "Orni Attack")
|
set(PROJECT_LONG_NAME "Orni Attack")
|
||||||
|
|||||||
@@ -84,9 +84,18 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all debug release _windows-release _macos-release _linux-release \
|
.PHONY: all debug release _windows-release _macos-release _linux-release \
|
||||||
run run-debug clean rebuild show-version pack \
|
run run-debug clean rebuild show-version pack controllerdb \
|
||||||
format format-check tidy tidy-fix cppcheck hooks-install help
|
format format-check tidy tidy-fix cppcheck hooks-install help
|
||||||
|
|
||||||
|
# Còpia del gamecontrollerdb.txt (si existeix) al directori de build, perquè
|
||||||
|
# director.cpp el resolgui via resource_base = directori de l'executable.
|
||||||
|
# Silenciós si el fitxer no existeix (l'usuari encara no ha fet `make controllerdb`).
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
CP_CONTROLLERDB = @powershell -Command "if (Test-Path 'gamecontrollerdb.txt') { Copy-Item 'gamecontrollerdb.txt' -Destination '$(BUILDDIR)' -Force }"
|
||||||
|
else
|
||||||
|
CP_CONTROLLERDB = @if [ -f gamecontrollerdb.txt ]; then cp gamecontrollerdb.txt $(BUILDDIR)/; fi
|
||||||
|
endif
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# COMPILACIÓ
|
# COMPILACIÓ
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -98,10 +107,12 @@ endif
|
|||||||
all:
|
all:
|
||||||
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
|
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
|
||||||
@cmake --build $(BUILDDIR) -j$(JOBS)
|
@cmake --build $(BUILDDIR) -j$(JOBS)
|
||||||
|
$(CP_CONTROLLERDB)
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Debug $(CMAKE_DEFS)
|
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Debug $(CMAKE_DEFS)
|
||||||
@cmake --build $(BUILDDIR) -j$(JOBS)
|
@cmake --build $(BUILDDIR) -j$(JOBS)
|
||||||
|
$(CP_CONTROLLERDB)
|
||||||
|
|
||||||
run: all
|
run: all
|
||||||
@./$(BUILDDIR)/$(PROJECT)
|
@./$(BUILDDIR)/$(PROJECT)
|
||||||
@@ -138,6 +149,7 @@ _linux-release:
|
|||||||
|
|
||||||
# Còpia de fitxers
|
# Còpia de fitxers
|
||||||
cp $(BUILDDIR)/resources.pack "$(RELEASE_FOLDER)"
|
cp $(BUILDDIR)/resources.pack "$(RELEASE_FOLDER)"
|
||||||
|
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)"
|
||||||
cp README.md "$(RELEASE_FOLDER)"
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
|
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
|
||||||
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
|
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
|
||||||
@@ -166,6 +178,7 @@ _windows-release:
|
|||||||
@powershell -Command "if (-not (Test-Path '$(RELEASE_FOLDER)')) {New-Item '$(RELEASE_FOLDER)' -ItemType Directory}"
|
@powershell -Command "if (-not (Test-Path '$(RELEASE_FOLDER)')) {New-Item '$(RELEASE_FOLDER)' -ItemType Directory}"
|
||||||
|
|
||||||
@powershell -Command "Copy-Item -Path '$(BUILDDIR)/resources.pack' -Destination '$(RELEASE_FOLDER)'"
|
@powershell -Command "Copy-Item -Path '$(BUILDDIR)/resources.pack' -Destination '$(RELEASE_FOLDER)'"
|
||||||
|
@powershell -Command "Copy-Item 'gamecontrollerdb.txt' -Destination '$(RELEASE_FOLDER)'"
|
||||||
@powershell -Command "if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' -Destination '$(RELEASE_FOLDER)' }"
|
@powershell -Command "if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' -Destination '$(RELEASE_FOLDER)' }"
|
||||||
@powershell -Command "Copy-Item 'README.md' -Destination '$(RELEASE_FOLDER)'"
|
@powershell -Command "Copy-Item 'README.md' -Destination '$(RELEASE_FOLDER)'"
|
||||||
@powershell -Command "if (Test-Path 'release\windows\dll') { Copy-Item 'release\windows\dll\*.dll' -Destination '$(RELEASE_FOLDER)' }"
|
@powershell -Command "if (Test-Path 'release\windows\dll') { Copy-Item 'release\windows\dll\*.dll' -Destination '$(RELEASE_FOLDER)' }"
|
||||||
@@ -206,6 +219,7 @@ _macos-release:
|
|||||||
|
|
||||||
# Còpia de recursos i metadades del bundle
|
# Còpia de recursos i metadades del bundle
|
||||||
cp $(BUILDDIR)/arm/resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
cp $(BUILDDIR)/arm/resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
|
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||||
cp release/icons/icon.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
cp release/icons/icon.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
|
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
|
||||||
@@ -274,6 +288,19 @@ pack:
|
|||||||
@cmake --build $(BUILDDIR) --target pack_resources
|
@cmake --build $(BUILDDIR) --target pack_resources
|
||||||
@./$(BUILDDIR)/pack_resources data $(BUILDDIR)/resources.pack
|
@./$(BUILDDIR)/pack_resources data $(BUILDDIR)/resources.pack
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# DESCÀRREGA DE GAMECONTROLLERDB
|
||||||
|
# ==============================================================================
|
||||||
|
# Descarrega l'última versió de gamecontrollerdb.txt (mappings de gamepads
|
||||||
|
# mantinguts per la comunitat) a l'arrel del projecte. SDL el carrega via
|
||||||
|
# filesystem real (no dins resources.pack) i s'ha de copiar al costat del binari
|
||||||
|
# en cada build (gestionat per CP_CONTROLLERDB a `all`/`debug` i pels release targets).
|
||||||
|
controllerdb:
|
||||||
|
@echo "Descargando gamecontrollerdb.txt..."
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt \
|
||||||
|
-o gamecontrollerdb.txt
|
||||||
|
@echo "gamecontrollerdb.txt actualizado"
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# CODE QUALITY (delegats a cmake)
|
# CODE QUALITY (delegats a cmake)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,17 @@ namespace Defaults::Hud {
|
|||||||
constexpr float SCOREBOARD_TEXT_SCALE = 0.85F;
|
constexpr float SCOREBOARD_TEXT_SCALE = 0.85F;
|
||||||
constexpr float SCOREBOARD_TEXT_SPACING = 0.0F;
|
constexpr float SCOREBOARD_TEXT_SPACING = 0.0F;
|
||||||
|
|
||||||
|
// Colors per segment del marcador. Jerarquia per funció (score/vides/nivell)
|
||||||
|
// + diferenciació de jugador (P1 blanc vs P2 rosa) sense xocar amb els
|
||||||
|
// colors d'enemics (cyan/roig). Amb alpha=255 el line_renderer usa el color
|
||||||
|
// directament sense caure al fallback verd (Rendering::DEFAULT_LINE_COLOR).
|
||||||
|
namespace Colors {
|
||||||
|
constexpr SDL_Color SCORE_P1 = {.r = 255, .g = 255, .b = 255, .a = 255}; // blanc
|
||||||
|
constexpr SDL_Color SCORE_P2 = {.r = 255, .g = 130, .b = 200, .a = 255}; // rosa magenta
|
||||||
|
constexpr SDL_Color LIVES = {.r = 255, .g = 180, .b = 60, .a = 255}; // ambre / or
|
||||||
|
constexpr SDL_Color LEVEL = {.r = 155, .g = 255, .b = 175, .a = 255}; // verd sistema
|
||||||
|
} // namespace Colors
|
||||||
|
|
||||||
// Animación de entrada del HUD (init_hud_animator).
|
// Animación de entrada del HUD (init_hud_animator).
|
||||||
namespace InitAnim {
|
namespace InitAnim {
|
||||||
// Spawn vertical de la nave: 50 px bajo la PLAYAREA (sale desde fuera).
|
// Spawn vertical de la nave: 50 px bajo la PLAYAREA (sale desde fuera).
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
// Paleta semántica por tipo de entidad. Si una entity declara color, lo
|
// Paleta semántica por tipo de entidad. Si una entity declara color, lo
|
||||||
// pasa al pipeline con alpha=255 (sentinela "color válido"); si no, se
|
// pasa al pipeline con alpha=255 (sentinela "color válido"); si no,
|
||||||
// usa el color global del oscilador (g_current_line_color).
|
// line_renderer::linea() cau a DEFAULT_LINE_COLOR (verd fòsfor fallback).
|
||||||
namespace Defaults::Palette {
|
namespace Defaults::Palette {
|
||||||
|
|
||||||
// Paleta neon: pujada lleugera dels canals secundaris per millorar la
|
// Paleta neon: pujada lleugera dels canals secundaris per millorar la
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ namespace Graphics {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Lerp de l'oscil·lador (color base actual) cap a un color "flash" en
|
// Lerp del color base verd fòsfor cap a un color "flash" en funció de
|
||||||
// funció de f ∈ [0, 1]. Retorna sempre amb alpha>0 perquè el line_renderer
|
// f ∈ [0, 1]. Retorna sempre amb alpha>0 perquè el line_renderer l'usi
|
||||||
// l'use directament (sense barrejar amb el global).
|
// directament (sense caure al fallback DEFAULT_LINE_COLOR).
|
||||||
auto lerpColor(SDL_Color flash, float f) -> SDL_Color {
|
auto lerpColor(SDL_Color flash, float f) -> SDL_Color {
|
||||||
const float CLAMPED = std::clamp(f, 0.0F, 1.0F);
|
const float CLAMPED = std::clamp(f, 0.0F, 1.0F);
|
||||||
const SDL_Color BASE = Rendering::getLineColor();
|
constexpr SDL_Color BASE = Rendering::DEFAULT_LINE_COLOR;
|
||||||
const auto LERP_U8 = [&](unsigned char a, unsigned char b) {
|
const auto LERP_U8 = [&](unsigned char a, unsigned char b) {
|
||||||
const float OUT = (static_cast<float>(a) * (1.0F - CLAMPED)) + (static_cast<float>(b) * CLAMPED);
|
const float OUT = (static_cast<float>(a) * (1.0F - CLAMPED)) + (static_cast<float>(b) * CLAMPED);
|
||||||
return static_cast<unsigned char>(OUT);
|
return static_cast<unsigned char>(OUT);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Graphics {
|
|||||||
// - scale: factor de scale (1.0 = 20×40 px por carácter)
|
// - scale: factor de scale (1.0 = 20×40 px por carácter)
|
||||||
// - spacing: espacio entre caracteres en píxeles (a scale 1.0)
|
// - spacing: espacio entre caracteres en píxeles (a scale 1.0)
|
||||||
// - brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness)
|
// - brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness)
|
||||||
// - color: color RGBA explícit; si alpha==0 (default) s'usa l'oscil·lador global
|
// - color: color RGBA explícit; si alpha==0 (default) es fa fallback a Rendering::DEFAULT_LINE_COLOR
|
||||||
void render(const std::string& text, const Vec2& position, float scale = 1.0F, float spacing = 2.0F, float brightness = 1.0F, SDL_Color color = {0, 0, 0, 0}) const;
|
void render(const std::string& text, const Vec2& position, float scale = 1.0F, float spacing = 2.0F, float brightness = 1.0F, SDL_Color color = {0, 0, 0, 0}) const;
|
||||||
|
|
||||||
// Renderizar string centrado en un punto
|
// Renderizar string centrado en un punto
|
||||||
@@ -35,7 +35,7 @@ namespace Graphics {
|
|||||||
// - scale: factor de scale (1.0 = 20×40 px por carácter)
|
// - scale: factor de scale (1.0 = 20×40 px por carácter)
|
||||||
// - spacing: espacio entre caracteres en píxeles (a scale 1.0)
|
// - spacing: espacio entre caracteres en píxeles (a scale 1.0)
|
||||||
// - brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness)
|
// - brightness: factor de brightness (0.0-1.0, default 1.0 = màxima brightness)
|
||||||
// - color: color RGBA explícit; si alpha==0 (default) s'usa l'oscil·lador global
|
// - color: color RGBA explícit; si alpha==0 (default) es fa fallback a Rendering::DEFAULT_LINE_COLOR
|
||||||
void renderCentered(const std::string& text, const Vec2& centre_point, float scale = 1.0F, float spacing = 2.0F, float brightness = 1.0F, SDL_Color color = {0, 0, 0, 0}) const;
|
void renderCentered(const std::string& text, const Vec2& centre_point, float scale = 1.0F, float spacing = 2.0F, float brightness = 1.0F, SDL_Color color = {0, 0, 0, 0}) const;
|
||||||
|
|
||||||
// Calcular ancho total de un string (útil para centrado).
|
// Calcular ancho total de un string (útil para centrado).
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// Mesh3D = llista de vèrtexs Vec3 + llista d'arestes (parells d'índexs).
|
// Mesh3D = llista de vèrtexs Vec3 + llista d'arestes (parells d'índexs).
|
||||||
// drawWireframe() aplica una Transform3D al mesh, projecta amb Camera3D i
|
// drawWireframe() aplica una Transform3D al mesh, projecta amb Camera3D i
|
||||||
// emet cada aresta com una línia 2D pel pipeline `Rendering::linea` (mateix
|
// emet cada aresta com una línia 2D pel pipeline `Rendering::linea` (mateix
|
||||||
// pipeline que la resta del joc: glow verd via ColorOscillator si color.a==0).
|
// pipeline que la resta del joc: verd fòsfor via Rendering::DEFAULT_LINE_COLOR si color.a==0).
|
||||||
//
|
//
|
||||||
// Sense depth buffer: el caller és responsable d'ordenar els meshos per
|
// Sense depth buffer: el caller és responsable d'ordenar els meshos per
|
||||||
// profunditat decreixent si vol oclusió coherent (la pipeline és LINE_LIST
|
// profunditat decreixent si vol oclusió coherent (la pipeline és LINE_LIST
|
||||||
|
|||||||
@@ -309,8 +309,11 @@ auto Input::checkTriggerInput(Action action, const std::shared_ptr<Gamepad>& gam
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Input::addGamepadMappingsFromFile() {
|
void Input::addGamepadMappingsFromFile() {
|
||||||
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
const int COUNT = SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str());
|
||||||
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << '\n';
|
if (COUNT < 0) {
|
||||||
|
std::cerr << "[Input] Error carregant " << gamepad_mappings_file_ << ": " << SDL_GetError() << '\n';
|
||||||
|
} else {
|
||||||
|
std::cout << "[Input] " << gamepad_mappings_file_ << " carregat (" << COUNT << " mappings)\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +331,7 @@ void Input::initSDLGamePad() {
|
|||||||
} else {
|
} else {
|
||||||
addGamepadMappingsFromFile();
|
addGamepadMappingsFromFile();
|
||||||
discoverGamepads();
|
discoverGamepads();
|
||||||
std::cout << "\n** INPUT SYSTEM **\n";
|
std::cout << "[Input] inicialitzat\n";
|
||||||
std::cout << "Input System initialized successfully\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,6 @@
|
|||||||
|
|
||||||
namespace Rendering {
|
namespace Rendering {
|
||||||
|
|
||||||
// Color global compartido para líneas sin paleta propia (HUD, debug, texto
|
|
||||||
// genérico). Equivale al "color máximo" de la antigua oscilación CPU: verde
|
|
||||||
// fósforo CRT. El pulso de brillo lo aplica ahora el shader de postpro.
|
|
||||||
SDL_Color g_current_line_color = {100, 255, 100, 255};
|
|
||||||
|
|
||||||
// Grosor global por defecto. Configurable via setLineThickness.
|
// Grosor global por defecto. Configurable via setLineThickness.
|
||||||
float g_current_line_thickness = Defaults::Rendering::LINE_THICKNESS_DEFAULT;
|
float g_current_line_thickness = Defaults::Rendering::LINE_THICKNESS_DEFAULT;
|
||||||
|
|
||||||
@@ -36,8 +31,8 @@ namespace Rendering {
|
|||||||
const auto FX2 = static_cast<float>(x2);
|
const auto FX2 = static_cast<float>(x2);
|
||||||
const auto FY2 = static_cast<float>(y2);
|
const auto FY2 = static_cast<float>(y2);
|
||||||
|
|
||||||
// color.alpha==0 → usar color global (verde fósforo). alpha>0 → color directo.
|
// color.alpha==0 → fallback a DEFAULT_LINE_COLOR (verd fòsfor). alpha>0 → color directo.
|
||||||
const SDL_Color SOURCE = (color.a > 0) ? color : g_current_line_color;
|
const SDL_Color SOURCE = (color.a > 0) ? color : DEFAULT_LINE_COLOR;
|
||||||
const float R = (static_cast<float>(SOURCE.r) * brightness) / 255.0F;
|
const float R = (static_cast<float>(SOURCE.r) * brightness) / 255.0F;
|
||||||
const float G = (static_cast<float>(SOURCE.g) * brightness) / 255.0F;
|
const float G = (static_cast<float>(SOURCE.g) * brightness) / 255.0F;
|
||||||
const float B = (static_cast<float>(SOURCE.b) * brightness) / 255.0F;
|
const float B = (static_cast<float>(SOURCE.b) * brightness) / 255.0F;
|
||||||
@@ -68,10 +63,6 @@ namespace Rendering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLineColor(SDL_Color color) { g_current_line_color = color; }
|
|
||||||
|
|
||||||
auto getLineColor() -> SDL_Color { return g_current_line_color; }
|
|
||||||
|
|
||||||
void setLineThickness(float thickness) {
|
void setLineThickness(float thickness) {
|
||||||
if (thickness > 0.0F) {
|
if (thickness > 0.0F) {
|
||||||
g_current_line_thickness = thickness;
|
g_current_line_thickness = thickness;
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
//
|
//
|
||||||
// El dibujo de líneas pasa por el pipeline GPU. Las coordenadas (x1,y1,x2,y2)
|
// El dibujo de líneas pasa por el pipeline GPU. Las coordenadas (x1,y1,x2,y2)
|
||||||
// son lógicas (1280×720); el shader las mapea a NDC y el viewport del SDLManager
|
// son lógicas (1280×720); el shader las mapea a NDC y el viewport del SDLManager
|
||||||
// hace el letterbox a píxeles físicos. El brillo modula el color global de
|
// hace el letterbox a píxeles físicos. El pulse de brillo lo aplica el shader
|
||||||
// línea (lo gestiona ColorOscillator). El grosor es configurable por línea
|
// de postpro (ya no hi ha un ColorOscillator a CPU). El grosor es configurable
|
||||||
// (parámetro thickness>0) o global (g_current_line_thickness vía setLineThickness).
|
// per línia (parámetro thickness>0) o global (g_current_line_thickness vía
|
||||||
|
// setLineThickness).
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -15,12 +16,17 @@
|
|||||||
|
|
||||||
namespace Rendering {
|
namespace Rendering {
|
||||||
|
|
||||||
|
// Color verd fòsfor CRT per defecte: s'usa quan el caller passa color amb
|
||||||
|
// alpha==0 (sentinella "sense color propi"). Constant immutable: la
|
||||||
|
// semàntica de "color global" ja no existeix (era de l'antic ColorOscillator).
|
||||||
|
constexpr SDL_Color DEFAULT_LINE_COLOR = {.r = 100, .g = 255, .b = 100, .a = 255};
|
||||||
|
|
||||||
// Dibuja una línea entre dos puntos en coordenadas lógicas (1280×720).
|
// Dibuja una línea entre dos puntos en coordenadas lógicas (1280×720).
|
||||||
// brightness: factor de brillo (0.0..1.0, default 1.0 = brillo máximo).
|
// brightness: factor de brillo (0.0..1.0, default 1.0 = brillo máximo).
|
||||||
// Pre-multiplica el RGB del color (color dim sobre fons negre).
|
// Pre-multiplica el RGB del color (color dim sobre fons negre).
|
||||||
// thickness: grosor en píxeles lógicos. Si <= 0 usa g_current_line_thickness.
|
// thickness: grosor en píxeles lógicos. Si <= 0 usa g_current_line_thickness.
|
||||||
// color: si alpha==0, se usa el color global del oscilador; si alpha>0 se
|
// color: si alpha==0, se usa DEFAULT_LINE_COLOR (verd fòsfor fallback);
|
||||||
// usa este color directo (paleta semántica por entidad).
|
// si alpha>0 se usa este color directo (paleta semántica por entidad).
|
||||||
// alpha: alpha que arriba al GPU (default 1.0 = opac, behavior original).
|
// alpha: alpha que arriba al GPU (default 1.0 = opac, behavior original).
|
||||||
// Valors <1.0 fan que la línia es barregi de veritat sobre el dest
|
// Valors <1.0 fan que la línia es barregi de veritat sobre el dest
|
||||||
// en comptes de sobrepintar-lo (útil per halos translúcids).
|
// en comptes de sobrepintar-lo (útil per halos translúcids).
|
||||||
@@ -49,10 +55,6 @@ namespace Rendering {
|
|||||||
SDL_Color color = {0, 0, 0, 0},
|
SDL_Color color = {0, 0, 0, 0},
|
||||||
SDL_Color glow_color = {0, 0, 0, 0});
|
SDL_Color glow_color = {0, 0, 0, 0});
|
||||||
|
|
||||||
// Color global de las líneas (lo actualiza ColorOscillator vía SDLManager).
|
|
||||||
void setLineColor(SDL_Color color);
|
|
||||||
[[nodiscard]] auto getLineColor() -> SDL_Color;
|
|
||||||
|
|
||||||
// Grosor global por defecto (en píxeles lógicos). Default: 1.5.
|
// Grosor global por defecto (en píxeles lógicos). Default: 1.5.
|
||||||
void setLineThickness(float thickness);
|
void setLineThickness(float thickness);
|
||||||
[[nodiscard]] auto getLineThickness() -> float;
|
[[nodiscard]] auto getLineThickness() -> float;
|
||||||
|
|||||||
@@ -106,8 +106,11 @@ Director::Director(int argc, char* argv[])
|
|||||||
// falla, Locale::text() retorna la clau crua i el joc segueix funcionant.
|
// falla, Locale::text() retorna la clau crua i el joc segueix funcionant.
|
||||||
Locale::get().load(std::string("locale/") + cfg_->locale + ".yaml");
|
Locale::get().load(std::string("locale/") + cfg_->locale + ".yaml");
|
||||||
|
|
||||||
// Inicialitzar sistema de input
|
// Inicialitzar sistema de input. El gamecontrollerdb.txt viu al costat del
|
||||||
Input::init("data/gamecontrollerdb.txt");
|
// binari (no dins de resources.pack, perquè SDL_AddGamepadMappingsFromFile
|
||||||
|
// necessita una ruta real de filesystem). resource_base ja apunta al directori
|
||||||
|
// de l'executable (o a Contents/Resources en bundles de macOS).
|
||||||
|
Input::init(resource_base + "/gamecontrollerdb.txt");
|
||||||
|
|
||||||
// Autoassignacio de primer arranque: si cap dels dos jugadors te mando
|
// Autoassignacio de primer arranque: si cap dels dos jugadors te mando
|
||||||
// assignat al config, repartim els que hi haja detectats (P1 = pad 0,
|
// assignat al config, repartim els que hi haja detectats (P1 = pad 0,
|
||||||
|
|||||||
@@ -710,7 +710,7 @@ void GameScene::drawInitHudState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (score_progress > 0.0F) {
|
if (score_progress > 0.0F) {
|
||||||
Systems::InitHud::drawScoreboardAnimated(text_, buildScoreboard(), score_progress);
|
Systems::InitHud::drawScoreboardAnimated(text_, buildScoreboardSegments(), score_progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ship1_progress > 0.0F && match_config_.player1_active && ships_[0].isActive()) {
|
if (ship1_progress > 0.0F && match_config_.player1_active && ships_[0].isActive()) {
|
||||||
@@ -816,59 +816,49 @@ void GameScene::tocado(uint8_t player_id, const Vec2& bullet_velocity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameScene::drawScoreboard() {
|
void GameScene::drawScoreboard() {
|
||||||
// Construir text del marcador
|
|
||||||
std::string text = buildScoreboard();
|
|
||||||
|
|
||||||
// Parámetros de renderització
|
|
||||||
const float SCALE = Defaults::Hud::SCOREBOARD_TEXT_SCALE;
|
const float SCALE = Defaults::Hud::SCOREBOARD_TEXT_SCALE;
|
||||||
const float SPACING = Defaults::Hud::SCOREBOARD_TEXT_SPACING;
|
const float SPACING = Defaults::Hud::SCOREBOARD_TEXT_SPACING;
|
||||||
|
|
||||||
// Calcular centro de la zone del marcador
|
|
||||||
const SDL_FRect& scoreboard_zone = Defaults::Zones::SCOREBOARD;
|
const SDL_FRect& scoreboard_zone = Defaults::Zones::SCOREBOARD;
|
||||||
float center_x = scoreboard_zone.w / 2.0F;
|
const Vec2 CENTER = {
|
||||||
float center_y = scoreboard_zone.y + (scoreboard_zone.h / 2.0F);
|
.x = scoreboard_zone.w / 2.0F,
|
||||||
|
.y = scoreboard_zone.y + (scoreboard_zone.h / 2.0F),
|
||||||
// Renderizar centrat
|
};
|
||||||
text_.renderCentered(text, {.x = center_x, .y = center_y}, SCALE, SPACING);
|
Systems::InitHud::drawScoreboardSegmentsAt(text_, buildScoreboardSegments(), CENTER, SCALE, SPACING);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GameScene::buildScoreboard() const -> std::string {
|
auto GameScene::buildScoreboardSegments() const -> Systems::InitHud::ScoreboardSegments {
|
||||||
// Puntuación P1 (6 dígits) - mostrar zeros si inactiu
|
Systems::InitHud::ScoreboardSegments out;
|
||||||
std::string score_p1;
|
|
||||||
std::string vides_p1;
|
// Puntuació P1 (6 dígits) - zeros si inactiu
|
||||||
if (match_config_.player1_active) {
|
if (match_config_.player1_active) {
|
||||||
score_p1 = std::to_string(score_per_player_[0]);
|
std::string s = std::to_string(score_per_player_[0]);
|
||||||
score_p1 = std::string(6 - std::min(6, static_cast<int>(score_p1.length())), '0') + score_p1;
|
out.score_p1 = std::string(6 - std::min(6, static_cast<int>(s.length())), '0') + s;
|
||||||
vides_p1 = (lives_per_player_[0] < 10)
|
out.lives_p1 = (lives_per_player_[0] < 10)
|
||||||
? "0" + std::to_string(lives_per_player_[0])
|
? "0" + std::to_string(lives_per_player_[0])
|
||||||
: std::to_string(lives_per_player_[0]);
|
: std::to_string(lives_per_player_[0]);
|
||||||
} else {
|
} else {
|
||||||
score_p1 = "000000";
|
out.score_p1 = "000000";
|
||||||
vides_p1 = "00";
|
out.lives_p1 = "00";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nivel (2 dígits)
|
// Nivell (2 dígits) amb label localitzat
|
||||||
uint8_t stage_num = stage_manager_->getCurrentStage();
|
const uint8_t STAGE_NUM = stage_manager_->getCurrentStage();
|
||||||
std::string stage_str = (stage_num < 10) ? "0" + std::to_string(stage_num)
|
const std::string STAGE_STR = (STAGE_NUM < 10) ? "0" + std::to_string(STAGE_NUM)
|
||||||
: std::to_string(stage_num);
|
: std::to_string(STAGE_NUM);
|
||||||
|
out.level = Locale::get().text("hud.level") + STAGE_STR;
|
||||||
|
|
||||||
// Puntuación P2 (6 dígits) - mostrar zeros si inactiu
|
// Puntuació P2 (6 dígits) - zeros si inactiu
|
||||||
std::string score_p2;
|
|
||||||
std::string vides_p2;
|
|
||||||
if (match_config_.player2_active) {
|
if (match_config_.player2_active) {
|
||||||
score_p2 = std::to_string(score_per_player_[1]);
|
std::string s = std::to_string(score_per_player_[1]);
|
||||||
score_p2 = std::string(6 - std::min(6, static_cast<int>(score_p2.length())), '0') + score_p2;
|
out.score_p2 = std::string(6 - std::min(6, static_cast<int>(s.length())), '0') + s;
|
||||||
vides_p2 = (lives_per_player_[1] < 10)
|
out.lives_p2 = (lives_per_player_[1] < 10)
|
||||||
? "0" + std::to_string(lives_per_player_[1])
|
? "0" + std::to_string(lives_per_player_[1])
|
||||||
: std::to_string(lives_per_player_[1]);
|
: std::to_string(lives_per_player_[1]);
|
||||||
} else {
|
} else {
|
||||||
score_p2 = "000000";
|
out.score_p2 = "000000";
|
||||||
vides_p2 = "00";
|
out.lives_p2 = "00";
|
||||||
}
|
}
|
||||||
|
return out;
|
||||||
// Format: "123456 03 LEVEL 01 654321 02"
|
|
||||||
// Nota: dos espais entre seccions, mantenir ambdós slots siempre visibles
|
|
||||||
return score_p1 + " " + vides_p1 + " " + Locale::get().text("hud.level") + stage_str + " " + score_p2 + " " + vides_p2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [NEW] Stage system helper methods
|
// [NEW] Stage system helper methods
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "game/stage_system/stage_config.hpp"
|
#include "game/stage_system/stage_config.hpp"
|
||||||
#include "game/stage_system/stage_manager.hpp"
|
#include "game/stage_system/stage_manager.hpp"
|
||||||
#include "game/systems/collision_system.hpp"
|
#include "game/systems/collision_system.hpp"
|
||||||
|
#include "game/systems/init_hud_animator.hpp"
|
||||||
|
|
||||||
// Game over state machine
|
// Game over state machine
|
||||||
enum class GameOverState : uint8_t {
|
enum class GameOverState : uint8_t {
|
||||||
@@ -128,8 +129,9 @@ class GameScene final : public Scene {
|
|||||||
void drawPlayingState();
|
void drawPlayingState();
|
||||||
void drawLevelCompletedState();
|
void drawLevelCompletedState();
|
||||||
|
|
||||||
// [NEW] Función helper del marcador
|
// [NEW] Helper del marcador: construeix els 5 segments (score_p1, vides_p1,
|
||||||
[[nodiscard]] auto buildScoreboard() const -> std::string;
|
// level, score_p2, vides_p2) per a render colorit per segment.
|
||||||
|
[[nodiscard]] auto buildScoreboardSegments() const -> Systems::InitHud::ScoreboardSegments;
|
||||||
|
|
||||||
// Sub-pasos de update() (descompuestos en Fase 9d para reducir
|
// Sub-pasos de update() (descompuestos en Fase 9d para reducir
|
||||||
// complejidad cognitiva; cada uno es responsable de una sección).
|
// complejidad cognitiva; cada uno es responsable de una sección).
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "core/defaults.hpp"
|
#include "core/defaults.hpp"
|
||||||
|
#include "core/defaults/hud.hpp"
|
||||||
#include "core/math/easing.hpp"
|
#include "core/math/easing.hpp"
|
||||||
#include "core/rendering/line_renderer.hpp"
|
#include "core/rendering/line_renderer.hpp"
|
||||||
|
|
||||||
@@ -77,8 +78,40 @@ namespace Systems::InitHud {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawScoreboardSegmentsAt(const Graphics::VectorText& text,
|
||||||
|
const ScoreboardSegments& segments,
|
||||||
|
const Vec2& center,
|
||||||
|
float scale,
|
||||||
|
float spacing) {
|
||||||
|
// Separadors entre segments (preservant el layout legacy: " ", " ", " ", " ").
|
||||||
|
const float W_SEP1 = Graphics::VectorText::getTextWidth(" ", scale, spacing);
|
||||||
|
const float W_SEP2 = Graphics::VectorText::getTextWidth(" ", scale, spacing);
|
||||||
|
|
||||||
|
const float W_SP1 = Graphics::VectorText::getTextWidth(segments.score_p1, scale, spacing);
|
||||||
|
const float W_LP1 = Graphics::VectorText::getTextWidth(segments.lives_p1, scale, spacing);
|
||||||
|
const float W_LV = Graphics::VectorText::getTextWidth(segments.level, scale, spacing);
|
||||||
|
const float W_SP2 = Graphics::VectorText::getTextWidth(segments.score_p2, scale, spacing);
|
||||||
|
const float W_LP2 = Graphics::VectorText::getTextWidth(segments.lives_p2, scale, spacing);
|
||||||
|
|
||||||
|
const float TOTAL = W_SP1 + W_SEP1 + W_LP1 + W_SEP2 + W_LV + W_SEP2 + W_SP2 + W_SEP1 + W_LP2;
|
||||||
|
|
||||||
|
const float HEIGHT = Graphics::VectorText::getTextHeight(scale);
|
||||||
|
const float TOP_Y = center.y - (HEIGHT / 2.0F);
|
||||||
|
float x = center.x - (TOTAL / 2.0F);
|
||||||
|
|
||||||
|
text.render(segments.score_p1, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::SCORE_P1);
|
||||||
|
x += W_SP1 + W_SEP1;
|
||||||
|
text.render(segments.lives_p1, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LIVES);
|
||||||
|
x += W_LP1 + W_SEP2;
|
||||||
|
text.render(segments.level, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LEVEL);
|
||||||
|
x += W_LV + W_SEP2;
|
||||||
|
text.render(segments.score_p2, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::SCORE_P2);
|
||||||
|
x += W_SP2 + W_SEP1;
|
||||||
|
text.render(segments.lives_p2, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LIVES);
|
||||||
|
}
|
||||||
|
|
||||||
void drawScoreboardAnimated(const Graphics::VectorText& text,
|
void drawScoreboardAnimated(const Graphics::VectorText& text,
|
||||||
const std::string& scoreboard_text,
|
const ScoreboardSegments& segments,
|
||||||
float progress) {
|
float progress) {
|
||||||
const float EASED = Easing::easeOutQuad(progress);
|
const float EASED = Easing::easeOutQuad(progress);
|
||||||
|
|
||||||
@@ -91,10 +124,7 @@ namespace Systems::InitHud {
|
|||||||
const auto Y_INI = static_cast<float>(Defaults::Game::HEIGHT);
|
const auto Y_INI = static_cast<float>(Defaults::Game::HEIGHT);
|
||||||
const float Y_ANIM = Y_INI + ((Y_FINAL - Y_INI) * EASED);
|
const float Y_ANIM = Y_INI + ((Y_FINAL - Y_INI) * EASED);
|
||||||
|
|
||||||
text.renderCentered(scoreboard_text,
|
drawScoreboardSegmentsAt(text, segments, {.x = CENTRE_X, .y = Y_ANIM}, SCALE, SPACING);
|
||||||
Vec2{.x = CENTRE_X, .y = Y_ANIM},
|
|
||||||
SCALE,
|
|
||||||
SPACING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Systems::InitHud
|
} // namespace Systems::InitHud
|
||||||
|
|||||||
@@ -21,6 +21,17 @@
|
|||||||
|
|
||||||
namespace Systems::InitHud {
|
namespace Systems::InitHud {
|
||||||
|
|
||||||
|
// Segments del marcador. Cada segment es renderitza amb el seu propi color
|
||||||
|
// (vegeu Defaults::Hud::Colors). El layout final concatena en aquest ordre
|
||||||
|
// amb separadors d'1, 2, 2, 1 espais respectivament (igual que el legacy).
|
||||||
|
struct ScoreboardSegments {
|
||||||
|
std::string score_p1;
|
||||||
|
std::string lives_p1;
|
||||||
|
std::string level; // ex: "NIVELL 01"
|
||||||
|
std::string score_p2;
|
||||||
|
std::string lives_p2;
|
||||||
|
};
|
||||||
|
|
||||||
// Convierte un progreso global 0..1 al sub-progreso de un elemento que solo
|
// Convierte un progreso global 0..1 al sub-progreso de un elemento que solo
|
||||||
// se anima en la ventana [ratio_init, ratio_end].
|
// se anima en la ventana [ratio_init, ratio_end].
|
||||||
// < ratio_init → 0.0 (no empezó)
|
// < ratio_init → 0.0 (no empezó)
|
||||||
@@ -40,10 +51,19 @@ namespace Systems::InitHud {
|
|||||||
// 66..100% → línea inferior crece desde los lados hacia el centro.
|
// 66..100% → línea inferior crece desde los lados hacia el centro.
|
||||||
void drawBordersAnimated(Rendering::Renderer* renderer, float progress);
|
void drawBordersAnimated(Rendering::Renderer* renderer, float progress);
|
||||||
|
|
||||||
// Dibuja el scoreboard centrado, subiendo desde fuera de la pantalla
|
// Dibuixa els 5 segments del scoreboard centrats al voltant de `center`,
|
||||||
// hasta su posición final con easing.
|
// cadascun amb el seu color (Defaults::Hud::Colors). Separadors de 1/2/2/1
|
||||||
|
// espais entre segments per preservar el layout legacy.
|
||||||
|
void drawScoreboardSegmentsAt(const Graphics::VectorText& text,
|
||||||
|
const ScoreboardSegments& segments,
|
||||||
|
const Vec2& center,
|
||||||
|
float scale,
|
||||||
|
float spacing);
|
||||||
|
|
||||||
|
// Dibuixa el scoreboard centrat, pujant des de fora de la pantalla fins a
|
||||||
|
// la seva posició final amb easing. Delega a drawScoreboardSegmentsAt.
|
||||||
void drawScoreboardAnimated(const Graphics::VectorText& text,
|
void drawScoreboardAnimated(const Graphics::VectorText& text,
|
||||||
const std::string& scoreboard_text,
|
const ScoreboardSegments& segments,
|
||||||
float progress);
|
float progress);
|
||||||
|
|
||||||
} // namespace Systems::InitHud
|
} // namespace Systems::InitHud
|
||||||
|
|||||||
Reference in New Issue
Block a user