afegit titol al TITOL
This commit is contained in:
@@ -362,10 +362,10 @@ void EscenaJoc::tocado() {
|
||||
float ship_angle = nau_.get_angle();
|
||||
|
||||
debris_manager_.explotar(
|
||||
nau_.get_forma(), // Ship shape (3 lines)
|
||||
ship_pos, // Center position
|
||||
ship_angle, // Ship orientation
|
||||
1.0f, // Normal scale
|
||||
nau_.get_forma(), // Ship shape (3 lines)
|
||||
ship_pos, // Center position
|
||||
ship_angle, // Ship orientation
|
||||
1.0f, // Normal scale
|
||||
Defaults::Physics::Debris::VELOCITAT_BASE // 80 px/s
|
||||
);
|
||||
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include "core/graphics/vector_text.hpp"
|
||||
#include "core/rendering/sdl_manager.hpp"
|
||||
#include "core/types.hpp"
|
||||
#include "../constants.hpp"
|
||||
#include "../effects/debris_manager.hpp"
|
||||
#include "../entities/bala.hpp"
|
||||
#include "../entities/enemic.hpp"
|
||||
#include "../entities/nau.hpp"
|
||||
#include "core/graphics/vector_text.hpp"
|
||||
#include "core/rendering/sdl_manager.hpp"
|
||||
#include "core/types.hpp"
|
||||
|
||||
// Classe principal del joc (escena)
|
||||
class EscenaJoc {
|
||||
@@ -45,10 +45,10 @@ class EscenaJoc {
|
||||
float itocado_; // Death timer (seconds)
|
||||
|
||||
// Lives and game over system
|
||||
int num_vides_; // Current lives count
|
||||
bool game_over_; // Game over state flag
|
||||
float game_over_timer_; // Countdown timer for auto-return (seconds)
|
||||
Punt punt_spawn_; // Configurable spawn point
|
||||
int num_vides_; // Current lives count
|
||||
bool game_over_; // Game over state flag
|
||||
float game_over_timer_; // Countdown timer for auto-return (seconds)
|
||||
Punt punt_spawn_; // Configurable spawn point
|
||||
|
||||
// Text vectorial
|
||||
Graphics::VectorText text_;
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "../effects/debris_manager.hpp"
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/graphics/shape.hpp"
|
||||
#include "core/rendering/sdl_manager.hpp"
|
||||
#include "core/types.hpp"
|
||||
#include "../effects/debris_manager.hpp"
|
||||
#include "core/defaults.hpp"
|
||||
|
||||
class EscenaLogo {
|
||||
public:
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
#include "escena_titol.hpp"
|
||||
|
||||
#include <cfloat>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "core/audio/audio.hpp"
|
||||
#include "core/graphics/shape_loader.hpp"
|
||||
#include "core/input/mouse.hpp"
|
||||
#include "core/rendering/shape_renderer.hpp"
|
||||
#include "core/system/gestor_escenes.hpp"
|
||||
#include "core/system/global_events.hpp"
|
||||
#include "project.h"
|
||||
@@ -25,7 +28,8 @@ EscenaTitol::EscenaTitol(SDLManager& sdl)
|
||||
Defaults::Game::HEIGHT / 2.0f};
|
||||
|
||||
SDL_FRect area_completa{
|
||||
0, 0,
|
||||
0,
|
||||
0,
|
||||
static_cast<float>(Defaults::Game::WIDTH),
|
||||
static_cast<float>(Defaults::Game::HEIGHT)};
|
||||
|
||||
@@ -35,6 +39,146 @@ EscenaTitol::EscenaTitol(SDLManager& sdl)
|
||||
area_completa,
|
||||
150 // densitat: 150 estrelles (50 per capa)
|
||||
);
|
||||
|
||||
// Inicialitzar lletres del títol "ORNI ATTACK!"
|
||||
inicialitzar_titol();
|
||||
}
|
||||
|
||||
void EscenaTitol::inicialitzar_titol() {
|
||||
using namespace Graphics;
|
||||
|
||||
// === LÍNIA 1: "ORNI" ===
|
||||
std::vector<std::string> fitxers_orni = {
|
||||
"title/letra_o.shp",
|
||||
"title/letra_r.shp",
|
||||
"title/letra_n.shp",
|
||||
"title/letra_i.shp"};
|
||||
|
||||
// Pas 1: Carregar formes i calcular amplades per "ORNI"
|
||||
float ancho_total_orni = 0.0f;
|
||||
|
||||
for (const auto& fitxer : fitxers_orni) {
|
||||
auto forma = ShapeLoader::load(fitxer);
|
||||
if (!forma || !forma->es_valida()) {
|
||||
std::cerr << "[EscenaTitol] Error carregant " << fitxer << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calcular bounding box de la forma (trobar ancho i altura)
|
||||
float min_x = FLT_MAX;
|
||||
float max_x = -FLT_MAX;
|
||||
float min_y = FLT_MAX;
|
||||
float max_y = -FLT_MAX;
|
||||
|
||||
for (const auto& prim : forma->get_primitives()) {
|
||||
for (const auto& punt : prim.points) {
|
||||
min_x = std::min(min_x, punt.x);
|
||||
max_x = std::max(max_x, punt.x);
|
||||
min_y = std::min(min_y, punt.y);
|
||||
max_y = std::max(max_y, punt.y);
|
||||
}
|
||||
}
|
||||
|
||||
float ancho_sin_escalar = max_x - min_x;
|
||||
float altura_sin_escalar = max_y - min_y;
|
||||
|
||||
// Escalar ancho, altura i offset amb ESCALA_TITULO
|
||||
float ancho = ancho_sin_escalar * ESCALA_TITULO;
|
||||
float altura = altura_sin_escalar * ESCALA_TITULO;
|
||||
float offset_centre = (forma->get_centre().x - min_x) * ESCALA_TITULO;
|
||||
|
||||
lletres_orni_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
||||
|
||||
ancho_total_orni += ancho;
|
||||
}
|
||||
|
||||
// Afegir espaiat entre lletres
|
||||
ancho_total_orni += ESPAI_ENTRE_LLETRES * (lletres_orni_.size() - 1);
|
||||
|
||||
// Calcular posició inicial (centrat horitzontal) per "ORNI"
|
||||
float x_inicial_orni = (Defaults::Game::WIDTH - ancho_total_orni) / 2.0f;
|
||||
float x_actual = x_inicial_orni;
|
||||
|
||||
for (auto& lletra : lletres_orni_) {
|
||||
lletra.posicio.x = x_actual + lletra.offset_centre;
|
||||
lletra.posicio.y = Y_ORNI;
|
||||
x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES;
|
||||
}
|
||||
|
||||
std::cout << "[EscenaTitol] Línia 1 (ORNI): " << lletres_orni_.size()
|
||||
<< " lletres, ancho total: " << ancho_total_orni << " px\n";
|
||||
|
||||
// === Calcular posició Y dinàmica per "ATTACK!" ===
|
||||
// Totes les lletres ORNI tenen la mateixa altura, utilitzem la primera
|
||||
float altura_orni = lletres_orni_.empty() ? 50.0f : lletres_orni_[0].altura;
|
||||
y_attack_dinamica_ = Y_ORNI + altura_orni + SEPARACION_LINEAS;
|
||||
|
||||
std::cout << "[EscenaTitol] Altura ORNI: " << altura_orni
|
||||
<< " px, Y_ATTACK dinàmica: " << y_attack_dinamica_ << " px\n";
|
||||
|
||||
// === LÍNIA 2: "ATTACK!" ===
|
||||
std::vector<std::string> fitxers_attack = {
|
||||
"title/letra_a.shp",
|
||||
"title/letra_t.shp",
|
||||
"title/letra_t.shp", // T repetida
|
||||
"title/letra_a.shp", // A repetida
|
||||
"title/letra_c.shp",
|
||||
"title/letra_k.shp",
|
||||
"title/letra_exclamacion.shp"};
|
||||
|
||||
// Pas 1: Carregar formes i calcular amplades per "ATTACK!"
|
||||
float ancho_total_attack = 0.0f;
|
||||
|
||||
for (const auto& fitxer : fitxers_attack) {
|
||||
auto forma = ShapeLoader::load(fitxer);
|
||||
if (!forma || !forma->es_valida()) {
|
||||
std::cerr << "[EscenaTitol] Error carregant " << fitxer << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calcular bounding box de la forma (trobar ancho i altura)
|
||||
float min_x = FLT_MAX;
|
||||
float max_x = -FLT_MAX;
|
||||
float min_y = FLT_MAX;
|
||||
float max_y = -FLT_MAX;
|
||||
|
||||
for (const auto& prim : forma->get_primitives()) {
|
||||
for (const auto& punt : prim.points) {
|
||||
min_x = std::min(min_x, punt.x);
|
||||
max_x = std::max(max_x, punt.x);
|
||||
min_y = std::min(min_y, punt.y);
|
||||
max_y = std::max(max_y, punt.y);
|
||||
}
|
||||
}
|
||||
|
||||
float ancho_sin_escalar = max_x - min_x;
|
||||
float altura_sin_escalar = max_y - min_y;
|
||||
|
||||
// Escalar ancho, altura i offset amb ESCALA_TITULO
|
||||
float ancho = ancho_sin_escalar * ESCALA_TITULO;
|
||||
float altura = altura_sin_escalar * ESCALA_TITULO;
|
||||
float offset_centre = (forma->get_centre().x - min_x) * ESCALA_TITULO;
|
||||
|
||||
lletres_attack_.push_back({forma, {0.0f, 0.0f}, ancho, altura, offset_centre});
|
||||
|
||||
ancho_total_attack += ancho;
|
||||
}
|
||||
|
||||
// Afegir espaiat entre lletres
|
||||
ancho_total_attack += ESPAI_ENTRE_LLETRES * (lletres_attack_.size() - 1);
|
||||
|
||||
// Calcular posició inicial (centrat horitzontal) per "ATTACK!"
|
||||
float x_inicial_attack = (Defaults::Game::WIDTH - ancho_total_attack) / 2.0f;
|
||||
x_actual = x_inicial_attack;
|
||||
|
||||
for (auto& lletra : lletres_attack_) {
|
||||
lletra.posicio.x = x_actual + lletra.offset_centre;
|
||||
lletra.posicio.y = y_attack_dinamica_; // Usar posició dinàmica
|
||||
x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES;
|
||||
}
|
||||
|
||||
std::cout << "[EscenaTitol] Línia 2 (ATTACK!): " << lletres_attack_.size()
|
||||
<< " lletres, ancho total: " << ancho_total_attack << " px\n";
|
||||
}
|
||||
|
||||
void EscenaTitol::executar() {
|
||||
@@ -129,22 +273,51 @@ void EscenaTitol::dibuixar() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Estat MAIN: Dibuixar text de títol i copyright (sobre el starfield)
|
||||
// Estat MAIN: Dibuixar títol i text (sobre el starfield)
|
||||
if (estat_actual_ == EstatTitol::MAIN) {
|
||||
// Text principal centrat (vertical i horitzontalment)
|
||||
// === Dibuixar lletres del títol "ORNI ATTACK!" ===
|
||||
|
||||
// Dibuixar "ORNI" (línia 1)
|
||||
for (const auto& lletra : lletres_orni_) {
|
||||
Rendering::render_shape(
|
||||
sdl_.obte_renderer(),
|
||||
lletra.forma,
|
||||
lletra.posicio,
|
||||
0.0f, // sense rotació
|
||||
ESCALA_TITULO, // escala 80%
|
||||
true, // dibuixar
|
||||
1.0f // progrés complet (totalment visible)
|
||||
);
|
||||
}
|
||||
|
||||
// Dibuixar "ATTACK!" (línia 2)
|
||||
for (const auto& lletra : lletres_attack_) {
|
||||
Rendering::render_shape(
|
||||
sdl_.obte_renderer(),
|
||||
lletra.forma,
|
||||
lletra.posicio,
|
||||
0.0f, // sense rotació
|
||||
ESCALA_TITULO, // escala 80%
|
||||
true, // dibuixar
|
||||
1.0f // progrés complet (totalment visible)
|
||||
);
|
||||
}
|
||||
|
||||
// === Text "PRESS BUTTON TO PLAY" (a sota del títol) ===
|
||||
const std::string main_text = "PRESS BUTTON TO PLAY";
|
||||
const float escala_main = 1.0f;
|
||||
const float spacing = 2.0f;
|
||||
|
||||
float text_width = text_.get_text_width(main_text, escala_main, spacing);
|
||||
float text_height = text_.get_text_height(escala_main);
|
||||
|
||||
float x_center = (Defaults::Game::WIDTH - text_width) / 2.0f;
|
||||
float y_center = (Defaults::Game::HEIGHT - text_height) / 2.0f;
|
||||
// Usar posició dinàmica: ATTACK + altura lletres + separació
|
||||
float altura_attack = lletres_attack_.empty() ? 50.0f : lletres_attack_[0].altura;
|
||||
float y_center = y_attack_dinamica_ + altura_attack + 70.0f; // 70px sota "ATTACK!"
|
||||
|
||||
text_.render(main_text, Punt{x_center, y_center}, escala_main, spacing);
|
||||
|
||||
// Copyright a la part inferior (centrat horitzontalment)
|
||||
// === Copyright a la part inferior (centrat horitzontalment) ===
|
||||
// Convert to uppercase since VectorText only supports A-Z
|
||||
std::string copyright = Project::COPYRIGHT;
|
||||
for (char& c : copyright) {
|
||||
@@ -168,7 +341,6 @@ void EscenaTitol::processar_events(const SDL_Event& event) {
|
||||
// Qualsevol tecla o clic de ratolí
|
||||
if (event.type == SDL_EVENT_KEY_DOWN ||
|
||||
event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||
|
||||
switch (estat_actual_) {
|
||||
case EstatTitol::INIT:
|
||||
// Saltar a MAIN
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/graphics/shape.hpp"
|
||||
#include "core/graphics/starfield.hpp"
|
||||
#include "core/graphics/vector_text.hpp"
|
||||
#include "core/rendering/sdl_manager.hpp"
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/types.hpp"
|
||||
|
||||
class EscenaTitol {
|
||||
public:
|
||||
@@ -25,17 +28,36 @@ class EscenaTitol {
|
||||
MAIN // Pantalla de títol amb text
|
||||
};
|
||||
|
||||
// Estructura per emmagatzemar informació de cada lletra del títol
|
||||
struct LetraLogo {
|
||||
std::shared_ptr<Graphics::Shape> forma; // Forma vectorial de la lletra
|
||||
Punt posicio; // Posició en pantalla
|
||||
float ancho; // Amplada escalada
|
||||
float altura; // Altura escalada
|
||||
float offset_centre; // Offset del centre per posicionament
|
||||
};
|
||||
|
||||
SDLManager& sdl_;
|
||||
Graphics::VectorText text_; // Sistema de text vectorial
|
||||
Graphics::VectorText text_; // Sistema de text vectorial
|
||||
std::unique_ptr<Graphics::Starfield> starfield_; // Camp d'estrelles de fons
|
||||
EstatTitol estat_actual_; // Estat actual de la màquina
|
||||
float temps_acumulat_; // Temps acumulat per l'estat INIT
|
||||
EstatTitol estat_actual_; // Estat actual de la màquina
|
||||
float temps_acumulat_; // Temps acumulat per l'estat INIT
|
||||
|
||||
// Lletres del títol "ORNI ATTACK!"
|
||||
std::vector<LetraLogo> lletres_orni_; // Lletres de "ORNI" (línia 1)
|
||||
std::vector<LetraLogo> lletres_attack_; // Lletres de "ATTACK!" (línia 2)
|
||||
float y_attack_dinamica_; // Posició Y calculada dinàmicament per "ATTACK!"
|
||||
|
||||
// Constants
|
||||
static constexpr float DURACIO_INIT = 2.0f; // Duració de l'estat INIT (2 segons)
|
||||
static constexpr float DURACIO_INIT = 2.0f; // Duració de l'estat INIT (2 segons)
|
||||
static constexpr float ESCALA_TITULO = 0.6f; // Escala per les lletres del títol (50%)
|
||||
static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espai entre lletres
|
||||
static constexpr float Y_ORNI = 150.0f; // Posició Y de "ORNI"
|
||||
static constexpr float SEPARACION_LINEAS = 10.0f; // Separació entre "ORNI" i "ATTACK!" (0.0f = pegades)
|
||||
|
||||
// Mètodes privats
|
||||
void actualitzar(float delta_time);
|
||||
void dibuixar();
|
||||
void processar_events(const SDL_Event& event);
|
||||
void inicialitzar_titol(); // Carrega i posiciona les lletres del títol
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user