diff --git a/data/mus_gameover.ogg b/data/mus_gameover.ogg new file mode 100644 index 0000000..fd24d56 Binary files /dev/null and b/data/mus_gameover.ogg differ diff --git a/data/mus_menu.ogg b/data/mus_menu.ogg new file mode 100644 index 0000000..c7362b4 Binary files /dev/null and b/data/mus_menu.ogg differ diff --git a/data/snd_disappear.wav b/data/snd_disappear.wav new file mode 100644 index 0000000..85f6a5e Binary files /dev/null and b/data/snd_disappear.wav differ diff --git a/data/snd_fall.wav b/data/snd_fall.wav new file mode 100644 index 0000000..b582967 Binary files /dev/null and b/data/snd_fall.wav differ diff --git a/data/snd_jump.wav b/data/snd_jump.wav new file mode 100644 index 0000000..ac478f3 Binary files /dev/null and b/data/snd_jump.wav differ diff --git a/data/snd_pick.wav b/data/snd_pick.wav new file mode 100644 index 0000000..158a8e0 Binary files /dev/null and b/data/snd_pick.wav differ diff --git a/data/snd_push.wav b/data/snd_push.wav new file mode 100644 index 0000000..28126f9 Binary files /dev/null and b/data/snd_push.wav differ diff --git a/data/snd_walk.wav b/data/snd_walk.wav new file mode 100644 index 0000000..ca0a56d Binary files /dev/null and b/data/snd_walk.wav differ diff --git a/source/actor.cpp b/source/actor.cpp index 434e39c..61bf852 100644 --- a/source/actor.cpp +++ b/source/actor.cpp @@ -30,8 +30,8 @@ namespace actor int current_tag = 0; bool floating_editing = false; - audio::sound *walk = nullptr; int walk_channel = -1; + int falling_sound = -1; void resetTag() { @@ -811,6 +811,8 @@ namespace actor actor::actor_t *future_below = any_below_me(act); if ((input::keyDown(SDL_SCANCODE_SPACE) || input::keyDown(config::getKey(KEY_JUMP))) && (hero::getSkills() & SKILL_SHOES) && (act->pos.y + act->size.y) <= max.y && act->pos.y >= min.y && (act->pos.x + act->size.x) <= max.x && act->pos.x >= min.x && act->react_mask == 0 && ((act->pos.z == 0 && room::getFloor() != 11) || (act->below || future_below))) { + audio::pauseChannel(walk_channel); + audio::playSound("snd_jump.wav", SOUND_ALL); // [RZC 01/10/2024] Hack per a que al aterrar sobre els que desapareixen puga botar sobre ells, i a més ells desapareguen if (!act->below && future_below && future_below->flags & FLAG_DISAPPEAR) actor::push(act, future_below, PUSH_ZN); @@ -852,6 +854,9 @@ namespace actor { act->react_mask = 0; // desactivem la guarda (react_mask=0) act->flags |= FLAG_GRAVITY; // i reactivem el flag de gravetat + + if (falling_sound!=-1) { audio::stopChannel(falling_sound); falling_sound = -1; } + falling_sound = audio::playSound("snd_fall.wav", SOUND_ALL, -1); } } @@ -859,13 +864,12 @@ namespace actor if (moving) { act->flags |= FLAG_ANIMATED; - //if (audio::getChannelState(walk_channel) == audio::CHANNEL_PAUSED) audio::resumeChannel(walk_channel); - if ( (config::getSoundMode()==SOUND_ALL) && (act->anim_frame==0)) walk_channel = audio::playSound(walk, 0); + if (act->react_mask==0 && !(act->flags&FLAG_GRAVITY)) audio::resumeChannel(walk_channel); } else { act->flags &= uint8_t(~FLAG_ANIMATED); - //if (audio::getChannelState(walk_channel) == audio::CHANNEL_PLAYING) audio::pauseChannel(walk_channel); + audio::pauseChannel(walk_channel); } } @@ -1252,6 +1256,8 @@ namespace actor // Si estic sobre el piso, no faig res if (act->pos.z == 0) { + if (act->flags&FLAG_HERO && falling_sound!=-1) { audio::stopChannel(falling_sound); falling_sound = -1; } + if ((act->flags & FLAG_MOVING) && (act->movement == MOV_Z)) changeMoving(act); act->push &= ~PUSH_ZN; @@ -1292,6 +1298,7 @@ namespace actor // Si sí que hi ha... if (below) { + if (act->flags&FLAG_HERO && falling_sound!=-1) { audio::stopChannel(falling_sound); falling_sound = -1; } // ...el asociem... act->below = below; below->above = act; @@ -1889,10 +1896,10 @@ namespace actor for (int i = 0; i < 100; ++i) boosters_collected[i] = false; brilli = draw::getSurface("objectes.gif"); - - if (config::getSoundMode()==SOUND_ALL) walk = audio::loadSound("walk.wav"); - //walk_channel = audio::playSound(walk, -1); - //audio::pauseChannel(walk_channel); + if ( (config::getSoundMode()==SOUND_ALL) ) { + walk_channel = audio::playSound("snd_walk.wav", SOUND_ALL, -1); + audio::pauseChannel(walk_channel); + } } else { diff --git a/source/config.h b/source/config.h index 92a5d4b..db383e3 100644 --- a/source/config.h +++ b/source/config.h @@ -5,6 +5,7 @@ namespace config #define SOUND_ALL 0 #define SOUND_BASIC 1 #define SOUND_NONE 2 + #define SOUND_MUSIC 2 #define KEY_UP 0 #define KEY_DOWN 1 diff --git a/source/jaudio.cpp b/source/jaudio.cpp index 419f7b0..f720793 100644 --- a/source/jaudio.cpp +++ b/source/jaudio.cpp @@ -3,51 +3,53 @@ #include #include #include "jfile.h" +#include +#include "config.h" namespace audio { - // Açò son estructures de mentires, per a usar estructures de SDL_Mixer de forma opaca. - // Al final es un punter, així que és irrelevant el tipus del punter, - // però si amague que son estructures de SDL_Mixer, no fa falta ficar el include a SDL_mixer fora de este arxiu - struct sound - { - }; // Dummy structs - struct music + struct sound_cache_t { + std::string name; + Mix_Chunk *chunk; }; char *music_buffer = nullptr; + Mix_Music *music = nullptr; + std::vector sounds; + std::string musica_actual = ""; // Inicialitza el sistema de só void init() { int result = Mix_Init(MIX_INIT_OGG | MIX_INIT_WAVPACK); // Al final he ficat la configuració automàtica i au. Si en el futur necesitem canviar-ho pos se canvia - result = Mix_OpenAudio(48000, AUDIO_S16, 2, 1024); + result = Mix_OpenAudio(48000, AUDIO_S16, 2, 512); } // Tanca el sistema de só (no shit, sherlock) void quit() { + for (auto sound : sounds) Mix_FreeChunk(sound.chunk); + sounds.clear(); Mix_CloseAudio(); } - // Carrega un arxiu de música en format OGG - const music *loadMusic(const std::string filename) + // Comença a reproduïr la música en questió + void playMusic(const std::string filename, const int loop) { - int size; + if (!config::isMusicEnabled()) return; + // Si hi havia musica carregada, alliberem memòria if (music_buffer) free(music_buffer); + if (music) Mix_FreeMusic(music); + + int size; music_buffer = file::getFileBuffer(filename, size); auto rwops = SDL_RWFromMem(music_buffer, size); auto mus = Mix_LoadMUS_RW(rwops, 1); - //free(buffer); - return (music *)mus; - } - - // Comença a reproduïr la música en questió - void playMusic(const music *mus, const int loop) - { + //free(music_buffer); // [RZC 03/10/2024] Si allibere el buffer, no funciona la música. Porca miseria! Per aixó l'allibere abans de carregar si ja estava usat. Mix_PlayMusic((Mix_Music *)mus, loop); + musica_actual = filename; } // Pausa la música que està sonant ara @@ -59,6 +61,7 @@ namespace audio // Continua la música pausada void resumeMusic() { + if (!config::isMusicEnabled()) return; Mix_ResumeMusic(); } @@ -66,6 +69,7 @@ namespace audio void stopMusic() { Mix_HaltMusic(); + musica_actual = ""; } // Obté el estat actual de la música @@ -85,50 +89,63 @@ namespace audio } } - // Allibera una música - void deleteMusic(music *mus) + // Obté el nom de la música actual + const std::string getCurrentMusic() { - Mix_FreeMusic((Mix_Music *)mus); + return musica_actual; } + + // Carrega un só des d'un arxiu WAV - sound *loadSound(const std::string filename) + void loadSound(const std::string filename) { int size; char *buffer = file::getFileBuffer(filename, size); - return (sound *)Mix_LoadWAV_RW(SDL_RWFromMem(buffer, size), 1); + auto chunk = Mix_LoadWAV_RW(SDL_RWFromMem(buffer, size), 1); + if (!chunk) printf("ERROR: %s\n", SDL_GetError()); + sound_cache_t sound = { filename, chunk }; + sounds.push_back(sound); } // Comença a reproduïr el só especificat - const int playSound(sound *snd, const int loop) + const int playSound(const std::string name, const int priority, const int loop) { - return Mix_PlayChannel(-1, (Mix_Chunk *)snd, loop); - } - - // Allibera un só - void deleteSound(sound *snd) - { - Mix_FreeChunk((Mix_Chunk *)snd); + if (priority < config::getSoundMode()) return -1; + for (auto sound : sounds) + { + if (sound.name == name) return Mix_PlayChannel(-1, sound.chunk, loop); + } + return -1; } // Pausa un canal en el que s'estava reproduïnt un só void pauseChannel(const int channel) { + if (channel == -1) return; Mix_Pause(channel); } // Continua un canal pausat void resumeChannel(const int channel) { + if (channel == -1) return; Mix_Resume(channel); } // Para un canal que estava reproduïnt un só void stopChannel(const int channel) { + if (channel == -1) return; Mix_HaltChannel(channel); } + // Para tots els canals + void stopAllChannel() + { + Mix_HaltChannel(-1); + } + // Obté l'estat d'un canal const channel_state getChannelState(const int channel) { diff --git a/source/jaudio.h b/source/jaudio.h index d69e205..2c6ea01 100644 --- a/source/jaudio.h +++ b/source/jaudio.h @@ -21,25 +21,16 @@ namespace audio MUSIC_STOPPED }; - // Estructures per a gestionar música i só - struct sound; - struct music; - /// @brief Inicialitza el sistema de só void init(); /// @brief Tanca el sistema de só void quit(); - /// @brief Carrega un arxiu de música en format OGG + /// @brief Comença a reproduïr la música des d'un arxiu /// @param filename nom de l'arxiu - /// @return punter a la música - const music *loadMusic(const std::string filename); - - /// @brief Comença a reproduïr la música en questió - /// @param mus punter a la música /// @param loop quants bucles farà (-1=infinit, 0=no repeteix, 1=repeteix 1 vegada...) - void playMusic(const music *mus, const int loop = -1); + void playMusic(const std::string filename, const int loop = -1); /// @brief Pausa la música que està sonant ara void pauseMusic(); @@ -54,20 +45,19 @@ namespace audio /// @return estat actual de la música (MUSIC_INVALID, MUSIC_PLAYING, MUSIC_PAUSED o MUSIC_STOPPED) const music_state getMusicState(); - /// @brief Allibera una música - /// @param mus punter a la música a alliberar - void deleteMusic(music *mus); + /// @brief Obté el nom de la música actual + /// @return nom de la cançò + const std::string getCurrentMusic(); - /// @brief Carrega un só des d'un arxiu WAV + /// @brief Precarrega un só des d'un arxiu WAV /// @param filename nom de l'arxiu - /// @return un punter al só - sound *loadSound(const std::string filename); + void loadSound(const std::string filename); /// @brief Comença a reproduïr el só especificat /// @param snd punter al só a reproduïr /// @param loop si es fa bucle (-1=infinit, 0=no repeteix, 1=repeteix 1 vegada...) /// @return número del canal en que està sonant el só - const int playSound(sound *snd, const int loop = 0); + const int playSound(const std::string name, const int priority, const int loop = 0); /// @brief Pausa un canal en el que s'estava reproduïnt un só /// @param channel número del canal a pausar @@ -81,15 +71,14 @@ namespace audio /// @param channel número del canal a parar void stopChannel(const int channel); + /// @brief Para tots els canals + void stopAllChannel(); + /// @brief Obté l'estat d'un canal /// @param channel canal del que es vol obtindre l'estat /// @return estat del canal (CHANNEL_INVALID, CHANNEL_FREE, CHANNEL_PLAYING o CHANNEL_PAUSED) const channel_state getChannelState(const int channel); - /// @brief Allibera un só - /// @param snd punter al só - void deleteSound(sound *snd); - /// @brief Estableix el volum general /// @param volume valor a establir com a volum (128 màxim) /// @return el volum anterior diff --git a/source/jgame.cpp b/source/jgame.cpp index 80b3484..67af48d 100644 --- a/source/jgame.cpp +++ b/source/jgame.cpp @@ -34,9 +34,9 @@ int main(int argc, char *argv[]) game::param_count = argc; game::params = argv; - game::init(); input::init(); audio::init(); + game::init(); static unsigned int current_ticks = SDL_GetTicks(); diff --git a/source/m_catslife.cpp b/source/m_catslife.cpp index 65db197..e88b452 100644 --- a/source/m_catslife.cpp +++ b/source/m_catslife.cpp @@ -2,6 +2,7 @@ #include "jgame.h" #include "jinput.h" #include "jdraw.h" +#include "jaudio.h" #include "actor.h" #include "room.h" #include "config.h" @@ -15,6 +16,7 @@ namespace modules void init() { + audio::playMusic("mus_gameover.ogg"); if (gat == nullptr) gat = actor::createFromTemplate("GAT-NEGRE"); } diff --git a/source/m_game.cpp b/source/m_game.cpp index 52473c4..7de81f7 100644 --- a/source/m_game.cpp +++ b/source/m_game.cpp @@ -42,11 +42,7 @@ namespace modules } fclose(f); } else { - if (config::isMusicEnabled()) - { - auto musica = audio::loadMusic("ingame.ogg"); - audio::playMusic(musica); - } + audio::playMusic("ingame.ogg"); } actor::hero::init(); diff --git a/source/m_gameover.cpp b/source/m_gameover.cpp index 8bddefc..5878886 100644 --- a/source/m_gameover.cpp +++ b/source/m_gameover.cpp @@ -2,6 +2,7 @@ #include "jgame.h" #include "jinput.h" #include "jdraw.h" +#include "jaudio.h" #include "actor.h" #include "room.h" #include "config.h" @@ -16,6 +17,8 @@ namespace modules void init() { + audio::playMusic("mus_gameover.ogg"); + if (heroi == nullptr) heroi = actor::create("HERO", {16,32,8}, {6,6,12}, "test.gif", {0,32,20,32}, {-6,38}); heroi->flags = FLAG_ANIMATED; diff --git a/source/m_logo.cpp b/source/m_logo.cpp index bd84d82..47be6b0 100644 --- a/source/m_logo.cpp +++ b/source/m_logo.cpp @@ -1,6 +1,7 @@ #include "m_logo.h" #include "jdraw.h" #include "jinput.h" +#include "jaudio.h" #include "config.h" #include @@ -49,6 +50,8 @@ namespace modules } num_pixels++; } + + audio::playMusic("mus_logo.ogg"); } int steps=0; diff --git a/source/m_menu.cpp b/source/m_menu.cpp index c59ca34..3674f3c 100644 --- a/source/m_menu.cpp +++ b/source/m_menu.cpp @@ -17,10 +17,7 @@ namespace modules void init() { - if (config::isMusicEnabled()) - { - audio::stopMusic(); - } + if (audio::getCurrentMusic() != "mus_menu.ogg") audio::playMusic("mus_menu.ogg"); selected_option = OPTION_JUGAR; ::game::setUpdateTicks(64); draw::loadPalette("test.gif"); diff --git a/source/m_menu_audio.cpp b/source/m_menu_audio.cpp index 7e057f1..e598ea9 100644 --- a/source/m_menu_audio.cpp +++ b/source/m_menu_audio.cpp @@ -2,6 +2,7 @@ #include "jgame.h" #include "jinput.h" #include "jdraw.h" +#include "jaudio.h" #include #include "config.h" @@ -22,16 +23,27 @@ namespace modules return MENU_AUDIO_TORNAR; } if (input::keyPressed(SDL_SCANCODE_DOWN) || input::keyPressed(config::getKey(KEY_DOWN))) + { selected_option = (selected_option==2)?0:selected_option+1; - + audio::playSound("snd_push.wav", SOUND_BASIC); + } if (input::keyPressed(SDL_SCANCODE_UP) || input::keyPressed(config::getKey(KEY_UP))) + { selected_option = (selected_option==0)?2:selected_option-1; - + audio::playSound("snd_push.wav", SOUND_BASIC); + } if (input::keyPressed(SDL_SCANCODE_SPACE) || input::keyPressed(SDL_SCANCODE_RETURN) || input::keyPressed(config::getKey(KEY_JUMP)) || input::keyPressed(config::getKey(KEY_PICK))) { - if (selected_option==MENU_AUDIO_MUSICA) config::toggleMusic(); + if (selected_option==MENU_AUDIO_MUSICA) { + config::toggleMusic(); + if (config::isMusicEnabled()) + audio::playMusic("mus_menu.ogg"); + else + audio::stopMusic(); + } if (selected_option==MENU_AUDIO_SO) config::toggleSound(); if (selected_option==MENU_AUDIO_TORNAR) return MENU_AUDIO_TORNAR; + audio::playSound("snd_push.wav", SOUND_BASIC); } draw::cls(2); diff --git a/source/main.cpp b/source/main.cpp index 35e3944..e2629ca 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,6 +2,7 @@ #include "jdraw.h" #include "jfile.h" #include "jinput.h" +#include "jaudio.h" #include "editor.h" #include "console.h" #include @@ -90,6 +91,13 @@ void game::init() loadConfig(); draw::init("The Pool", 320, 240, zoom, fullscreen); console::init(); + + audio::loadSound("snd_walk.wav"); + audio::loadSound("snd_push.wav"); + audio::loadSound("snd_pick.wav"); + audio::loadSound("snd_jump.wav"); + audio::loadSound("snd_disappear.wav"); + audio::loadSound("snd_fall.wav"); } draw::loadPalette("test.gif");