bf83f161b0
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>
183 lines
5.2 KiB
C++
183 lines
5.2 KiB
C++
#include "audio.hpp"
|
|
|
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_G...
|
|
|
|
#include <algorithm> // Para clamp
|
|
#include <iostream> // Para std::cout
|
|
|
|
// Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp)
|
|
// clang-format off
|
|
#undef STB_VORBIS_HEADER_ONLY
|
|
#include "external/stb_vorbis.h"
|
|
// clang-format on
|
|
|
|
#include "core/audio/audio_cache.hpp" // Para AudioCache
|
|
#include "core/audio/jail_audio.hpp" // Para JA_FadeOutMusic, JA_Init, JA_PauseM...
|
|
#include "game/options.hpp" // Para AudioOptions, audio, MusicOptions
|
|
|
|
// Singleton
|
|
Audio* Audio::instance = nullptr;
|
|
|
|
// Inicializa la instancia única del singleton
|
|
void Audio::init() { Audio::instance = new Audio(); }
|
|
|
|
// Libera la instancia
|
|
void Audio::destroy() { delete Audio::instance; }
|
|
|
|
// Obtiene la instancia
|
|
auto Audio::get() -> Audio* { return Audio::instance; }
|
|
|
|
// Constructor
|
|
Audio::Audio() { initSDLAudio(); }
|
|
|
|
// Destructor
|
|
Audio::~Audio() {
|
|
JA_Quit();
|
|
}
|
|
|
|
// Método principal
|
|
void Audio::update() {
|
|
JA_Update();
|
|
}
|
|
|
|
// Reproduce la música
|
|
void Audio::playMusic(const std::string& name, const int loop) {
|
|
bool new_loop = (loop != 0);
|
|
|
|
// Si ya está sonando exactamente la misma pista y mismo modo loop, no hacemos nada
|
|
if (music_.state == MusicState::PLAYING && music_.name == name && music_.loop == new_loop) {
|
|
return;
|
|
}
|
|
|
|
// Intentar obtener recurso; si falla, no tocar estado
|
|
auto* resource = AudioCache::getMusic(name);
|
|
if (resource == nullptr) {
|
|
// manejo de error opcional
|
|
return;
|
|
}
|
|
|
|
// Si hay algo reproduciéndose, detenerlo primero (si el backend lo requiere)
|
|
if (music_.state == MusicState::PLAYING) {
|
|
JA_StopMusic(); // sustituir por la función de stop real del API si tiene otro nombre
|
|
}
|
|
|
|
// Llamada al motor para reproducir la nueva pista
|
|
JA_PlayMusic(resource, loop);
|
|
|
|
// Actualizar estado y metadatos después de start con éxito
|
|
music_.name = name;
|
|
music_.loop = new_loop;
|
|
music_.state = MusicState::PLAYING;
|
|
}
|
|
|
|
// Pausa la música
|
|
void Audio::pauseMusic() {
|
|
if (music_enabled_ && music_.state == MusicState::PLAYING) {
|
|
JA_PauseMusic();
|
|
music_.state = MusicState::PAUSED;
|
|
}
|
|
}
|
|
|
|
// Continua la música pausada
|
|
void Audio::resumeMusic() {
|
|
if (music_enabled_ && music_.state == MusicState::PAUSED) {
|
|
JA_ResumeMusic();
|
|
music_.state = MusicState::PLAYING;
|
|
}
|
|
}
|
|
|
|
// Detiene la música
|
|
void Audio::stopMusic() {
|
|
if (music_enabled_) {
|
|
JA_StopMusic();
|
|
music_.state = MusicState::STOPPED;
|
|
}
|
|
}
|
|
|
|
// Reproduce un sonido por nombre
|
|
void Audio::playSound(const std::string& name, Group group) const {
|
|
if (sound_enabled_) {
|
|
JA_PlaySound(AudioCache::getSound(name), 0, static_cast<int>(group));
|
|
}
|
|
}
|
|
|
|
// Reproduce un sonido por puntero directo
|
|
void Audio::playSound(JA_Sound_t* sound, Group group) const {
|
|
if (sound_enabled_) {
|
|
JA_PlaySound(sound, 0, static_cast<int>(group));
|
|
}
|
|
}
|
|
|
|
// Detiene todos los sonidos
|
|
void Audio::stopAllSounds() const {
|
|
if (sound_enabled_) {
|
|
JA_StopChannel(-1);
|
|
}
|
|
}
|
|
|
|
// Realiza un fundido de salida de la música
|
|
void Audio::fadeOutMusic(int milliseconds) const {
|
|
if (music_enabled_ && getRealMusicState() == MusicState::PLAYING) {
|
|
JA_FadeOutMusic(milliseconds);
|
|
}
|
|
}
|
|
|
|
// Consulta directamente el estado real de la música en jailaudio
|
|
auto Audio::getRealMusicState() -> MusicState {
|
|
JA_Music_state ja_state = JA_GetMusicState();
|
|
switch (ja_state) {
|
|
case JA_MUSIC_PLAYING:
|
|
return MusicState::PLAYING;
|
|
case JA_MUSIC_PAUSED:
|
|
return MusicState::PAUSED;
|
|
case JA_MUSIC_STOPPED:
|
|
case JA_MUSIC_INVALID:
|
|
case JA_MUSIC_DISABLED:
|
|
default:
|
|
return MusicState::STOPPED;
|
|
}
|
|
}
|
|
|
|
// Establece el volumen de los sonidos
|
|
void Audio::setSoundVolume(float sound_volume, Group group) const {
|
|
if (sound_enabled_) {
|
|
sound_volume = std::clamp(sound_volume, MIN_VOLUME, MAX_VOLUME);
|
|
const float CONVERTED_VOLUME = sound_volume * Options::audio.volume;
|
|
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
|
|
}
|
|
}
|
|
|
|
// Establece el volumen de la música
|
|
void Audio::setMusicVolume(float music_volume) const {
|
|
if (music_enabled_) {
|
|
music_volume = std::clamp(music_volume, MIN_VOLUME, MAX_VOLUME);
|
|
const float CONVERTED_VOLUME = music_volume * Options::audio.volume;
|
|
JA_SetMusicVolume(CONVERTED_VOLUME);
|
|
}
|
|
}
|
|
|
|
// Aplica la configuración
|
|
void Audio::applySettings() {
|
|
enable(Options::audio.enabled);
|
|
}
|
|
|
|
// Establecer estado general
|
|
void Audio::enable(bool value) {
|
|
enabled_ = value;
|
|
|
|
setSoundVolume(enabled_ ? Options::audio.sound.volume : MIN_VOLUME);
|
|
setMusicVolume(enabled_ ? Options::audio.music.volume : MIN_VOLUME);
|
|
}
|
|
|
|
// Inicializa SDL Audio
|
|
void Audio::initSDLAudio() {
|
|
if (!SDL_Init(SDL_INIT_AUDIO)) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
|
|
} else {
|
|
JA_Init(FREQUENCY, SDL_AUDIO_S16LE, 2);
|
|
enable(Options::audio.enabled);
|
|
|
|
std::cout << "\n** AUDIO SYSTEM **\n";
|
|
std::cout << "Audio system initialized successfully\n";
|
|
}
|
|
} |