From dab96b810691c26e29fef92d88c828a311be3e9d Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 3 Feb 2021 17:11:46 -0500 Subject: Added running sounds --- src/character_system.cpp | 23 +++++++++++++++++++++ src/character_system.h | 2 ++ src/map.cpp | 14 +++++++++++++ src/map.h | 4 ++++ src/mixer.cpp | 29 ++++++++++++++++++++++---- src/mixer.h | 8 ++++++- src/sprite.h | 3 +++ src/step_type.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 src/step_type.h (limited to 'src') diff --git a/src/character_system.cpp b/src/character_system.cpp index ac0f01a..2f26aee 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp @@ -130,6 +130,20 @@ void CharacterSystem::tick(double dt) { if (pLoc != sprite.loc) { game_.getSystem().moveSprite(spriteId, pLoc); + if (sprite.characterState == CharacterState::Running) { + vec2i newMapTileLoc = pLoc / map.getTileSize(); + StepType newTileStep = map.getStepType(newMapTileLoc.x(), newMapTileLoc.y()); + if (sprite.stepType != newTileStep) { + stopRunningSound(sprite); + + sprite.stepType = newTileStep; + + if (newTileStep != StepType::none) { + sprite.runningSfxChannel = game_.getMixer().loopSound(runningSfxForStepType(newTileStep)); + } + } + } + for (int followerId : sprite.followers) { Sprite& pNext = game_.getSprite(followerId); const Movement& posdir = pNext.trail.front(); @@ -180,6 +194,7 @@ void CharacterSystem::endCrouch(int spriteId) { void CharacterSystem::stopRunning(int spriteId) { Sprite& sprite = game_.getSprite(spriteId); setPartyState(spriteId, CharacterState::Still); + stopRunningSound(sprite); // Double the movement buffer for the followers. for (int followerId : sprite.followers) { @@ -232,3 +247,11 @@ void CharacterSystem::setPartyState(int spriteId, CharacterState state) { game_.getSystem().setSpriteAnimation(followerId, animName); } } + +void CharacterSystem::stopRunningSound(Sprite& sprite) { + sprite.stepType = StepType::none; + if (sprite.runningSfxChannel != -1) { + game_.getMixer().stopChannel(sprite.runningSfxChannel); + sprite.runningSfxChannel = -1; + } +} diff --git a/src/character_system.h b/src/character_system.h index 2eea233..18b6c46 100644 --- a/src/character_system.h +++ b/src/character_system.h @@ -37,6 +37,8 @@ private: void setPartyState(int spriteId, CharacterState state); + void stopRunningSound(Sprite& sprite); + Game& game_; Timer inputTimer_ {33}; }; diff --git a/src/map.cpp b/src/map.cpp index 7d9800d..0c4f9d6 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -42,6 +42,8 @@ Map::Map(std::string_view filename, Renderer& renderer) { for (const tmx::Property& property : tileset.getTile(maptile.ID)->properties) { if (property.getName() == "solid" && property.getBoolValue()) { tile.blocked = true; + } else if (property.getName() == "runSound") { + tile.step = stepTypeFromString(property.getStringValue()); } } @@ -64,3 +66,15 @@ bool Map::isBlocked(int x, int y) const { return false; } + +StepType Map::getStepType(int x, int y) const { + int i = x + y * mapSize_.w(); + + for (const std::vector& layer : layers_) { + if (layer.at(i).step != StepType::none) { + return layer.at(i).step; + } + } + + return StepType::none; +} diff --git a/src/map.h b/src/map.h index 2f8ec1a..de18e68 100644 --- a/src/map.h +++ b/src/map.h @@ -5,6 +5,7 @@ #include #include "renderer.h" #include "vector.h" +#include "step_type.h" class Renderer; @@ -13,6 +14,7 @@ struct Tile { bool flipHorizontal = false; bool flipVertical = false; bool blocked = false; + StepType step = StepType::none; }; class Map { @@ -32,6 +34,8 @@ public: bool isBlocked(int x, int y) const; + StepType getStepType(int x, int y) const; + private: vec2i mapSize_; diff --git a/src/mixer.cpp b/src/mixer.cpp index bfbedcd..bdcb7ce 100644 --- a/src/mixer.cpp +++ b/src/mixer.cpp @@ -1,6 +1,29 @@ #include "mixer.h" -void Mixer::playSound(std::string filename) { +void Mixer::playSound(std::string_view filename) { + Mix_Chunk* chunk = getChunkByFilename(std::string(filename)); + + if (Mix_PlayChannel(-1, chunk, 0) == -1) { + throw mix_error(); + } +} + +int Mixer::loopSound(std::string_view filename) { + Mix_Chunk* chunk = getChunkByFilename(std::string(filename)); + + int ret = Mix_PlayChannel(-1, chunk, -1); + if (ret == -1) { + throw mix_error(); + } + + return ret; +} + +void Mixer::stopChannel(int channel) { + Mix_HaltChannel(channel); +} + +Mix_Chunk* Mixer::getChunkByFilename(std::string filename) { if (!sounds_.count(filename)) { Mix_Chunk* sample = Mix_LoadWAV(filename.c_str()); if (!sample) { @@ -10,7 +33,5 @@ void Mixer::playSound(std::string filename) { sounds_[filename] = chunk_ptr(sample); } - if (Mix_PlayChannel(-1, sounds_[filename].get(), 0) == -1) { - throw mix_error(); - } + return sounds_[filename].get(); } diff --git a/src/mixer.h b/src/mixer.h index 010bb09..7f6ef72 100644 --- a/src/mixer.h +++ b/src/mixer.h @@ -56,10 +56,16 @@ using chunk_ptr = std::unique_ptr; class Mixer { public: - void playSound(std::string filename); + void playSound(std::string_view filename); + + int loopSound(std::string_view filename); + + void stopChannel(int channel); private: + Mix_Chunk* getChunkByFilename(std::string filename); + mix_wrapper mix_; std::map sounds_; }; diff --git a/src/sprite.h b/src/sprite.h index 2dc0ee1..028008d 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -8,6 +8,7 @@ #include "direction.h" #include "renderer.h" #include "vector.h" +#include "step_type.h" struct SpriteFrame { SDL_Rect srcRect; @@ -49,6 +50,8 @@ public: std::vector followers; std::deque trail; CharacterState characterState = CharacterState::Still; + StepType stepType = StepType::none; + int runningSfxChannel = -1; // Input bool controllable = false; diff --git a/src/step_type.h b/src/step_type.h new file mode 100644 index 0000000..c38d6f9 --- /dev/null +++ b/src/step_type.h @@ -0,0 +1,54 @@ +#ifndef STEP_TYPE_H_38251870 +#define STEP_TYPE_H_38251870 + +#include +#include + +enum class StepType { + none, + wood, + land_light, + land, + sand, + water, + mechanical, + grass, + unknown, + paved, + carpet, + weak_wood +}; + +inline StepType stepTypeFromString(std::string_view str) { + if (str == "wood") return StepType::wood; + if (str == "land_light") return StepType::land_light; + if (str == "land") return StepType::land; + if (str == "sand") return StepType::sand; + if (str == "water") return StepType::water; + if (str == "mechanical") return StepType::mechanical; + if (str == "grass") return StepType::grass; + if (str == "unknown") return StepType::unknown; + if (str == "paved") return StepType::paved; + if (str == "carpet") return StepType::carpet; + if (str == "weak_wood") return StepType::weak_wood; + return StepType::none; +} + +inline std::string_view runningSfxForStepType(StepType step) { + switch (step) { + case StepType::wood: return "../res/running_wood.wav"; + case StepType::land_light: return "../res/running_land_light.wav"; + case StepType::land: return "../res/running_land.wav"; + case StepType::sand: return "../res/running_sand.wav"; + case StepType::water: return "../res/running_water.wav"; + case StepType::mechanical: return "../res/running_mechanical.wav"; + case StepType::grass: return "../res/running_grass.wav"; + case StepType::unknown: return "../res/running_unknown.wav"; + case StepType::paved: return "../res/running_paved.wav"; + case StepType::carpet: return "../res/running_carpet.wav"; + case StepType::weak_wood: return "../res/running_weak_wood.wav"; + case StepType::none: throw std::invalid_argument("No running sfx for none step type"); + } +} + +#endif /* end of include guard: STEP_TYPE_H_38251870 */ -- cgit 1.4.1