afegides musiques

afegit control de brillo al starfield
This commit is contained in:
2025-12-03 19:27:36 +01:00
parent 3b0354da54
commit a3aeed4b7c
11 changed files with 109 additions and 29 deletions

View File

@@ -318,7 +318,7 @@ endif
# Backup to remote server
backup:
@echo "Backing up project to maverick:/home/sergio/git-backup/asteroids..."
@echo "Backing up project to maverick:/home/sergio/git-backup/orni..."
rsync -a --delete \
--exclude='build/' \
--exclude='*.o' \
@@ -326,7 +326,7 @@ backup:
--exclude='orni' \
--exclude='orni_debug' \
--exclude='*_release/' \
$(DIR_ROOT) maverick:/home/sergio/git-backup/asteroids/
$(DIR_ROOT) maverick:/home/sergio/git-backup/orni/
@echo "Backup completed successfully"
# Help target

BIN
data/music/game.ogg Normal file

Binary file not shown.

BIN
data/music/title.ogg Normal file

Binary file not shown.

View File

@@ -103,9 +103,12 @@ float Starfield::calcular_escala(const Estrella& estrella) const {
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)
return Defaults::Brightness::STARFIELD_MIN +
float brightness_base = Defaults::Brightness::STARFIELD_MIN +
(Defaults::Brightness::STARFIELD_MAX - Defaults::Brightness::STARFIELD_MIN) *
estrella.distancia_centre;
// Aplicar multiplicador i limitar a 1.0
return std::min(1.0f, brightness_base * multiplicador_brightness_);
}
// Actualitzar posicions de les estrelles
@@ -135,6 +138,11 @@ void Starfield::actualitzar(float delta_time) {
}
}
// Establir multiplicador de brightness
void Starfield::set_brightness(float multiplier) {
multiplicador_brightness_ = std::max(0.0f, multiplier); // Evitar valors negatius
}
// Dibuixar totes les estrelles
void Starfield::dibuixar() {
if (!shape_estrella_->es_valida()) {

View File

@@ -42,6 +42,7 @@ class Starfield {
// Setters per ajustar paràmetres en temps real
void set_punt_fuga(const Punt& punt) { punt_fuga_ = punt; }
void set_brightness(float multiplier);
private:
// Estructura interna per cada estrella
@@ -75,6 +76,7 @@ class Starfield {
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 multiplicador_brightness_{1.0f}; // Multiplicador de brillantor (1.0 = default)
};
} // namespace Graphics

View File

@@ -8,6 +8,7 @@
#include <iostream>
#include "core/audio/audio.hpp"
#include "core/audio/audio_cache.hpp"
#include "core/defaults.hpp"
#include "core/rendering/sdl_manager.hpp"
#include "game/escenes/escena_joc.hpp"
@@ -161,6 +162,13 @@ auto Director::run() -> int {
// Inicialitzar sistema d'audio
Audio::init();
// Precachejar música per evitar lag al començar
AudioCache::getMusic("title.ogg");
if (Options::console) {
std::cout << "Música precachejada: "
<< AudioCache::getMusicCacheSize() << " fitxers\n";
}
// Bucle principal de gestió d'escenes
while (GestorEscenes::actual != GestorEscenes::Escena::EIXIR) {
switch (GestorEscenes::actual) {

View File

@@ -141,6 +141,9 @@ void EscenaJoc::inicialitzar() {
for (auto& bala : bales_) {
bala.inicialitzar();
}
// Iniciar música de joc (sense stopMusic, ja s'ha parat en destructor de TITOL)
Audio::get()->playMusic("game.ogg");
}
void EscenaJoc::actualitzar(float delta_time) {
@@ -150,6 +153,8 @@ void EscenaJoc::actualitzar(float delta_time) {
game_over_timer_ -= delta_time;
if (game_over_timer_ <= 0.0f) {
// Aturar música de joc abans de tornar al títol
Audio::get()->stopMusic();
// Auto-transition to title screen
GestorEscenes::actual = GestorEscenes::Escena::TITOL;
return;

View File

@@ -200,6 +200,10 @@ void EscenaLogo::canviar_estat(EstatAnimacio nou_estat) {
std::mt19937 g(rd());
std::shuffle(ordre_explosio_.begin(), ordre_explosio_.end(), g);
}
else if (nou_estat == EstatAnimacio::POST_EXPLOSION)
{
Audio::get()->playMusic("title.ogg");
}
std::cout << "[EscenaLogo] Canvi a estat: " << static_cast<int>(nou_estat)
<< "\n";
@@ -288,6 +292,7 @@ void EscenaLogo::actualitzar(float delta_time) {
case EstatAnimacio::POST_EXPLOSION:
if (temps_estat_actual_ >= DURACIO_POST_EXPLOSION) {
// Iniciar música de títol abans de la transició
GestorEscenes::actual = GestorEscenes::Escena::TITOL;
}
break;

View File

@@ -9,7 +9,7 @@
#include <memory>
#include <vector>
#include "../effects/debris_manager.hpp"
#include "game/effects/debris_manager.hpp"
#include "core/defaults.hpp"
#include "core/graphics/shape.hpp"
#include "core/rendering/sdl_manager.hpp"

View File

@@ -4,6 +4,7 @@
#include "escena_titol.hpp"
#include <cfloat>
#include <cmath>
#include <iostream>
#include <string>
@@ -15,6 +16,11 @@
#include "core/system/global_events.hpp"
#include "project.h"
namespace {
// Brightness del starfield (1.0 = default, >1.0 més brillant, <1.0 menys brillant)
constexpr float BRIGHTNESS_STARFIELD = 1.2f;
} // namespace
EscenaTitol::EscenaTitol(SDLManager& sdl)
: sdl_(sdl),
text_(sdl.obte_renderer()),
@@ -40,8 +46,21 @@ EscenaTitol::EscenaTitol(SDLManager& sdl)
150 // densitat: 150 estrelles (50 per capa)
);
// Configurar brightness del starfield
starfield_->set_brightness(BRIGHTNESS_STARFIELD);
// Inicialitzar lletres del títol "ORNI ATTACK!"
inicialitzar_titol();
// Iniciar música de títol si no està sonant
if (Audio::get()->getMusicState() != Audio::MusicState::PLAYING) {
Audio::get()->playMusic("title.ogg");
}
}
EscenaTitol::~EscenaTitol() {
// Aturar música de títol quan es destrueix l'escena
Audio::get()->stopMusic();
}
void EscenaTitol::inicialitzar_titol() {
@@ -256,9 +275,18 @@ void EscenaTitol::actualitzar(float delta_time) {
estat_actual_ = EstatTitol::MAIN;
}
break;
case EstatTitol::MAIN:
// No hi ha lògica d'actualització en l'estat MAIN
break;
case EstatTitol::TRANSITION:
temps_acumulat_ += delta_time;
if (temps_acumulat_ >= DURACIO_TRANSITION) {
// Transició a JOC (la música ja s'ha parat en el fade)
GestorEscenes::actual = GestorEscenes::Escena::JOC;
}
break;
}
}
@@ -273,8 +301,8 @@ void EscenaTitol::dibuixar() {
return;
}
// Estat MAIN: Dibuixar títol i text (sobre el starfield)
if (estat_actual_ == EstatTitol::MAIN) {
// Estat MAIN i TRANSITION: Dibuixar títol i text (sobre el starfield)
if (estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::TRANSITION) {
// === Dibuixar lletres del títol "ORNI ATTACK!" ===
// Dibuixar "ORNI" (línia 1)
@@ -303,19 +331,31 @@ void EscenaTitol::dibuixar() {
);
}
// === Text "PRESS BUTTON TO PLAY" (a sota del títol) ===
// === Text "PRESS BUTTON TO PLAY" ===
// En estat MAIN: sempre visible
// En estat TRANSITION: parpellejant (blink amb sinusoide)
const float spacing = 2.0f; // Espai entre caràcters (usat també per copyright)
bool mostrar_text = true;
if (estat_actual_ == EstatTitol::TRANSITION) {
// Parpelleig: sin oscil·la entre -1 i 1, volem ON quan > 0
float fase = temps_acumulat_ * BLINK_FREQUENCY * 2.0f * 3.14159f; // 2π × freq × temps
mostrar_text = (std::sin(fase) > 0.0f);
}
if (mostrar_text) {
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 x_center = (Defaults::Game::WIDTH - text_width) / 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!"
float y_center = y_attack_dinamica_ + altura_attack + 70.0f;
text_.render(main_text, Punt{x_center, y_center}, escala_main, spacing);
}
// === Copyright a la part inferior (centrat horitzontalment) ===
// Convert to uppercase since VectorText only supports A-Z
@@ -346,9 +386,16 @@ void EscenaTitol::processar_events(const SDL_Event& event) {
// Saltar a MAIN
estat_actual_ = EstatTitol::MAIN;
break;
case EstatTitol::MAIN:
// Anar al joc
GestorEscenes::actual = GestorEscenes::Escena::JOC;
// Iniciar transició amb fade-out de música
estat_actual_ = EstatTitol::TRANSITION;
temps_acumulat_ = 0.0f; // Reset del comptador
Audio::get()->fadeOutMusic(MUSIC_FADE); // Fade de 300ms
break;
case EstatTitol::TRANSITION:
// Ignorar inputs durant la transició
break;
}
}

View File

@@ -19,13 +19,15 @@
class EscenaTitol {
public:
explicit EscenaTitol(SDLManager& sdl);
~EscenaTitol(); // Destructor per aturar música
void executar(); // Bucle principal de l'escena
private:
// Màquina d'estats per la pantalla de títol
enum class EstatTitol {
INIT, // Pantalla negra inicial (2 segons)
MAIN // Pantalla de títol amb text
MAIN, // Pantalla de títol amb text
TRANSITION // Transició amb fade-out de música i text parpellejant
};
// Estructura per emmagatzemar informació de cada lletra del títol
@@ -49,11 +51,14 @@ class EscenaTitol {
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 = 4.0f; // Duració de l'estat INIT (2 segons)
static constexpr float DURACIO_TRANSITION = 1.5f; // Duració de la transició (1.5 segons)
static constexpr float ESCALA_TITULO = 0.6f; // Escala per les lletres del títol (50%)
static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espai entre lletres
static constexpr float Y_ORNI = 150.0f; // Posició Y de "ORNI"
static constexpr float SEPARACION_LINEAS = 10.0f; // Separació entre "ORNI" i "ATTACK!" (0.0f = pegades)
static constexpr float BLINK_FREQUENCY = 3.0f; // Freqüència de parpelleig (3 Hz)
static constexpr int MUSIC_FADE = 1000; // Duracio del fade de la musica del titol al començar a jugar
// Mètodes privats
void actualitzar(float delta_time);