diff --git a/CMakeLists.txt b/CMakeLists.txt index 035836c..36200cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,7 @@ if(BUILD_TESTS) add_executable(test_entities_smoke tests/test_entities_smoke.cpp tests/hole_player_stubs.cpp + tests/audio_cache_stubs.cpp source/core/resources/resource_helper.cpp source/core/resources/resource_pack.cpp source/game/map/map.cpp @@ -389,6 +390,7 @@ if(BUILD_TESTS) tests/test_whip_attack.cpp tests/whip_attack_player_stubs.cpp tests/hole_player_stubs.cpp + tests/audio_cache_stubs.cpp source/core/resources/resource_helper.cpp source/core/resources/resource_pack.cpp source/game/map/map.cpp diff --git a/data/audio/sounds/mummy_hurt.wav b/data/audio/sounds/mummy_hurt.wav new file mode 100644 index 0000000..3bd5dcd Binary files /dev/null and b/data/audio/sounds/mummy_hurt.wav differ diff --git a/data/entities/mummy/mummy.yaml b/data/entities/mummy/mummy.yaml index ef41d5b..ef1232d 100644 --- a/data/entities/mummy/mummy.yaml +++ b/data/entities/mummy/mummy.yaml @@ -58,3 +58,6 @@ hurt: duration_ms: 600 speed: 60 whippable: true + # So opcional: basename del fitxer dins `data/audio/sounds/`. Es dispara + # un sol cop per fuetada quan la mòmia entra a HURT. Si manca, no sona. + sound: mummy_hurt.wav diff --git a/source/game/entities/concrete/mummy.cpp b/source/game/entities/concrete/mummy.cpp index a53ffa1..ef26502 100644 --- a/source/game/entities/concrete/mummy.cpp +++ b/source/game/entities/concrete/mummy.cpp @@ -8,11 +8,14 @@ #include #include +#include "core/audio/audio.hpp" +#include "core/resources/resource_cache.hpp" #include "game/entities/entity_factory.hpp" #include "game/entities/entity_manager.hpp" #include "game/entities/event_bus.hpp" #include "game/entities/player.hpp" #include "game/map/map.hpp" +#include "utils/defaults.hpp" namespace { @@ -133,6 +136,14 @@ Mummy::Mummy(const fkyaml::node& yaml) if (h.contains("whippable")) { whippable_ = h["whippable"].get_value(); } + // So opcional: el basename val tant de clau al Resource::Cache com de + // path (`Defaults::Paths::AUDIO_SOUNDS_DIR + key`). Mateix patró que + // els sons del Player. Si el camp manca, la clau queda buida i + // `enterHurt` no dispara playSound. + if (h.contains("sound")) { + hurt_config_.sound_key = h["sound"].get_value(); + Resource::Cache::get().loadSound(hurt_config_.sound_key, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + hurt_config_.sound_key); + } } } @@ -511,6 +522,9 @@ void Mummy::enterHurt(Direction flee_dir) { state_ = State::HURT; hurt_remaining_s_ = hurt_config_.duration_s; hurt_speed_ = (hurt_config_.speed_px_per_s > 0.0F) ? hurt_config_.speed_px_per_s : speed_; + if (!hurt_config_.sound_key.empty() && Audio::get() != nullptr) { + Audio::get()->playSound(hurt_config_.sound_key, Audio::Group::GAME); + } const Direction CHOSEN = chooseHurtDirection(flee_dir); if (CHOSEN == Direction::NONE) { diff --git a/source/game/entities/concrete/mummy.hpp b/source/game/entities/concrete/mummy.hpp index 15c15d2..c2c246e 100644 --- a/source/game/entities/concrete/mummy.hpp +++ b/source/game/entities/concrete/mummy.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "external/fkyaml_node.hpp" @@ -35,6 +36,7 @@ class Mummy : public DynamicHazard { struct HurtConfig { float duration_s{0.0F}; float speed_px_per_s{0.0F}; + std::string sound_key; // Buit = sense so. El fitxer viu a Defaults::Paths::AUDIO_SOUNDS_DIR. }; explicit Mummy(const fkyaml::node& yaml); diff --git a/tests/audio_cache_stubs.cpp b/tests/audio_cache_stubs.cpp new file mode 100644 index 0000000..aafa42e --- /dev/null +++ b/tests/audio_cache_stubs.cpp @@ -0,0 +1,35 @@ +// Stubs d'`Audio` i `Resource::Cache` per als smokes que enllacen +// entitats amb so propi (`mummy.cpp` carrega + dispara `mummy_hurt.wav`). +// +// Linkar `audio.cpp` i `resource_cache.cpp` arrossegaria SDL_mixer/Ja, +// el sistema de paquets, el carregador de GIFs, etc. — la mateixa +// explosió de dependències que `hole_player_stubs.cpp` evita per al +// Player. Aquests stubs deixen `Audio::get()` retornant `nullptr` +// (els call-sites comprovem aquesta condició abans de tocar el so) i +// fan no-op `Resource::Cache::loadSound`. + +#include "core/audio/audio.hpp" +#include "core/resources/resource_cache.hpp" + +auto Audio::get() -> Audio* { + return nullptr; +} + +void Audio::playSound(const std::string& /*name*/, Audio::Group /*group*/) { +} + +namespace Resource { + + auto Cache::get() -> Cache& { + // Heap-leak deliberat: el destructor de Cache requeriria els + // deleters de Ja::Music/Ja::Sound (a resource_types.cpp) que el + // smoke target no enllaça. Mai destruïm la instància — el procés + // mor abans i el SO recupera la memòria. + static Cache* instance_ = new Cache(); + return *instance_; + } + + void Cache::loadSound(const std::string& /*name*/, const std::string& /*file_path*/) { + } + +} // namespace Resource