diff options
| -rw-r--r-- | src/character_system.cpp | 23 | ||||
| -rw-r--r-- | src/character_system.h | 2 | ||||
| -rw-r--r-- | src/map.cpp | 14 | ||||
| -rw-r--r-- | src/map.h | 4 | ||||
| -rw-r--r-- | src/mixer.cpp | 29 | ||||
| -rw-r--r-- | src/mixer.h | 8 | ||||
| -rw-r--r-- | src/sprite.h | 3 | ||||
| -rw-r--r-- | src/step_type.h | 54 |
8 files changed, 132 insertions, 5 deletions
| 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) { | |||
| 130 | if (pLoc != sprite.loc) { | 130 | if (pLoc != sprite.loc) { |
| 131 | game_.getSystem<TransformSystem>().moveSprite(spriteId, pLoc); | 131 | game_.getSystem<TransformSystem>().moveSprite(spriteId, pLoc); |
| 132 | 132 | ||
| 133 | if (sprite.characterState == CharacterState::Running) { | ||
| 134 | vec2i newMapTileLoc = pLoc / map.getTileSize(); | ||
| 135 | StepType newTileStep = map.getStepType(newMapTileLoc.x(), newMapTileLoc.y()); | ||
| 136 | if (sprite.stepType != newTileStep) { | ||
| 137 | stopRunningSound(sprite); | ||
| 138 | |||
| 139 | sprite.stepType = newTileStep; | ||
| 140 | |||
| 141 | if (newTileStep != StepType::none) { | ||
| 142 | sprite.runningSfxChannel = game_.getMixer().loopSound(runningSfxForStepType(newTileStep)); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 133 | for (int followerId : sprite.followers) { | 147 | for (int followerId : sprite.followers) { |
| 134 | Sprite& pNext = game_.getSprite(followerId); | 148 | Sprite& pNext = game_.getSprite(followerId); |
| 135 | const Movement& posdir = pNext.trail.front(); | 149 | const Movement& posdir = pNext.trail.front(); |
| @@ -180,6 +194,7 @@ void CharacterSystem::endCrouch(int spriteId) { | |||
| 180 | void CharacterSystem::stopRunning(int spriteId) { | 194 | void CharacterSystem::stopRunning(int spriteId) { |
| 181 | Sprite& sprite = game_.getSprite(spriteId); | 195 | Sprite& sprite = game_.getSprite(spriteId); |
| 182 | setPartyState(spriteId, CharacterState::Still); | 196 | setPartyState(spriteId, CharacterState::Still); |
| 197 | stopRunningSound(sprite); | ||
| 183 | 198 | ||
| 184 | // Double the movement buffer for the followers. | 199 | // Double the movement buffer for the followers. |
| 185 | for (int followerId : sprite.followers) { | 200 | for (int followerId : sprite.followers) { |
| @@ -232,3 +247,11 @@ void CharacterSystem::setPartyState(int spriteId, CharacterState state) { | |||
| 232 | game_.getSystem<AnimationSystem>().setSpriteAnimation(followerId, animName); | 247 | game_.getSystem<AnimationSystem>().setSpriteAnimation(followerId, animName); |
| 233 | } | 248 | } |
| 234 | } | 249 | } |
| 250 | |||
| 251 | void CharacterSystem::stopRunningSound(Sprite& sprite) { | ||
| 252 | sprite.stepType = StepType::none; | ||
| 253 | if (sprite.runningSfxChannel != -1) { | ||
| 254 | game_.getMixer().stopChannel(sprite.runningSfxChannel); | ||
| 255 | sprite.runningSfxChannel = -1; | ||
| 256 | } | ||
| 257 | } | ||
| 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: | |||
| 37 | 37 | ||
| 38 | void setPartyState(int spriteId, CharacterState state); | 38 | void setPartyState(int spriteId, CharacterState state); |
| 39 | 39 | ||
| 40 | void stopRunningSound(Sprite& sprite); | ||
| 41 | |||
| 40 | Game& game_; | 42 | Game& game_; |
| 41 | Timer inputTimer_ {33}; | 43 | Timer inputTimer_ {33}; |
| 42 | }; | 44 | }; |
| 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) { | |||
| 42 | for (const tmx::Property& property : tileset.getTile(maptile.ID)->properties) { | 42 | for (const tmx::Property& property : tileset.getTile(maptile.ID)->properties) { |
| 43 | if (property.getName() == "solid" && property.getBoolValue()) { | 43 | if (property.getName() == "solid" && property.getBoolValue()) { |
| 44 | tile.blocked = true; | 44 | tile.blocked = true; |
| 45 | } else if (property.getName() == "runSound") { | ||
| 46 | tile.step = stepTypeFromString(property.getStringValue()); | ||
| 45 | } | 47 | } |
| 46 | } | 48 | } |
| 47 | 49 | ||
| @@ -64,3 +66,15 @@ bool Map::isBlocked(int x, int y) const { | |||
| 64 | 66 | ||
| 65 | return false; | 67 | return false; |
| 66 | } | 68 | } |
| 69 | |||
| 70 | StepType Map::getStepType(int x, int y) const { | ||
| 71 | int i = x + y * mapSize_.w(); | ||
| 72 | |||
| 73 | for (const std::vector<Tile>& layer : layers_) { | ||
| 74 | if (layer.at(i).step != StepType::none) { | ||
| 75 | return layer.at(i).step; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | return StepType::none; | ||
| 80 | } | ||
| 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 @@ | |||
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | #include "renderer.h" | 6 | #include "renderer.h" |
| 7 | #include "vector.h" | 7 | #include "vector.h" |
| 8 | #include "step_type.h" | ||
| 8 | 9 | ||
| 9 | class Renderer; | 10 | class Renderer; |
| 10 | 11 | ||
| @@ -13,6 +14,7 @@ struct Tile { | |||
| 13 | bool flipHorizontal = false; | 14 | bool flipHorizontal = false; |
| 14 | bool flipVertical = false; | 15 | bool flipVertical = false; |
| 15 | bool blocked = false; | 16 | bool blocked = false; |
| 17 | StepType step = StepType::none; | ||
| 16 | }; | 18 | }; |
| 17 | 19 | ||
| 18 | class Map { | 20 | class Map { |
| @@ -32,6 +34,8 @@ public: | |||
| 32 | 34 | ||
| 33 | bool isBlocked(int x, int y) const; | 35 | bool isBlocked(int x, int y) const; |
| 34 | 36 | ||
| 37 | StepType getStepType(int x, int y) const; | ||
| 38 | |||
| 35 | private: | 39 | private: |
| 36 | 40 | ||
| 37 | vec2i mapSize_; | 41 | 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 @@ | |||
| 1 | #include "mixer.h" | 1 | #include "mixer.h" |
| 2 | 2 | ||
| 3 | void Mixer::playSound(std::string filename) { | 3 | void Mixer::playSound(std::string_view filename) { |
| 4 | Mix_Chunk* chunk = getChunkByFilename(std::string(filename)); | ||
| 5 | |||
| 6 | if (Mix_PlayChannel(-1, chunk, 0) == -1) { | ||
| 7 | throw mix_error(); | ||
| 8 | } | ||
| 9 | } | ||
| 10 | |||
| 11 | int Mixer::loopSound(std::string_view filename) { | ||
| 12 | Mix_Chunk* chunk = getChunkByFilename(std::string(filename)); | ||
| 13 | |||
| 14 | int ret = Mix_PlayChannel(-1, chunk, -1); | ||
| 15 | if (ret == -1) { | ||
| 16 | throw mix_error(); | ||
| 17 | } | ||
| 18 | |||
| 19 | return ret; | ||
| 20 | } | ||
| 21 | |||
| 22 | void Mixer::stopChannel(int channel) { | ||
| 23 | Mix_HaltChannel(channel); | ||
| 24 | } | ||
| 25 | |||
| 26 | Mix_Chunk* Mixer::getChunkByFilename(std::string filename) { | ||
| 4 | if (!sounds_.count(filename)) { | 27 | if (!sounds_.count(filename)) { |
| 5 | Mix_Chunk* sample = Mix_LoadWAV(filename.c_str()); | 28 | Mix_Chunk* sample = Mix_LoadWAV(filename.c_str()); |
| 6 | if (!sample) { | 29 | if (!sample) { |
| @@ -10,7 +33,5 @@ void Mixer::playSound(std::string filename) { | |||
| 10 | sounds_[filename] = chunk_ptr(sample); | 33 | sounds_[filename] = chunk_ptr(sample); |
| 11 | } | 34 | } |
| 12 | 35 | ||
| 13 | if (Mix_PlayChannel(-1, sounds_[filename].get(), 0) == -1) { | 36 | return sounds_[filename].get(); |
| 14 | throw mix_error(); | ||
| 15 | } | ||
| 16 | } | 37 | } |
| 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<Mix_Chunk, chunk_deleter>; | |||
| 56 | class Mixer { | 56 | class Mixer { |
| 57 | public: | 57 | public: |
| 58 | 58 | ||
| 59 | void playSound(std::string filename); | 59 | void playSound(std::string_view filename); |
| 60 | |||
| 61 | int loopSound(std::string_view filename); | ||
| 62 | |||
| 63 | void stopChannel(int channel); | ||
| 60 | 64 | ||
| 61 | private: | 65 | private: |
| 62 | 66 | ||
| 67 | Mix_Chunk* getChunkByFilename(std::string filename); | ||
| 68 | |||
| 63 | mix_wrapper mix_; | 69 | mix_wrapper mix_; |
| 64 | std::map<std::string, chunk_ptr> sounds_; | 70 | std::map<std::string, chunk_ptr> sounds_; |
| 65 | }; | 71 | }; |
| 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 @@ | |||
| 8 | #include "direction.h" | 8 | #include "direction.h" |
| 9 | #include "renderer.h" | 9 | #include "renderer.h" |
| 10 | #include "vector.h" | 10 | #include "vector.h" |
| 11 | #include "step_type.h" | ||
| 11 | 12 | ||
| 12 | struct SpriteFrame { | 13 | struct SpriteFrame { |
| 13 | SDL_Rect srcRect; | 14 | SDL_Rect srcRect; |
| @@ -49,6 +50,8 @@ public: | |||
| 49 | std::vector<int> followers; | 50 | std::vector<int> followers; |
| 50 | std::deque<Movement> trail; | 51 | std::deque<Movement> trail; |
| 51 | CharacterState characterState = CharacterState::Still; | 52 | CharacterState characterState = CharacterState::Still; |
| 53 | StepType stepType = StepType::none; | ||
| 54 | int runningSfxChannel = -1; | ||
| 52 | 55 | ||
| 53 | // Input | 56 | // Input |
| 54 | bool controllable = false; | 57 | 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 @@ | |||
| 1 | #ifndef STEP_TYPE_H_38251870 | ||
| 2 | #define STEP_TYPE_H_38251870 | ||
| 3 | |||
| 4 | #include <string_view> | ||
| 5 | #include <stdexcept> | ||
| 6 | |||
| 7 | enum class StepType { | ||
| 8 | none, | ||
| 9 | wood, | ||
| 10 | land_light, | ||
| 11 | land, | ||
| 12 | sand, | ||
| 13 | water, | ||
| 14 | mechanical, | ||
| 15 | grass, | ||
| 16 | unknown, | ||
| 17 | paved, | ||
| 18 | carpet, | ||
| 19 | weak_wood | ||
| 20 | }; | ||
| 21 | |||
| 22 | inline StepType stepTypeFromString(std::string_view str) { | ||
| 23 | if (str == "wood") return StepType::wood; | ||
| 24 | if (str == "land_light") return StepType::land_light; | ||
| 25 | if (str == "land") return StepType::land; | ||
| 26 | if (str == "sand") return StepType::sand; | ||
| 27 | if (str == "water") return StepType::water; | ||
| 28 | if (str == "mechanical") return StepType::mechanical; | ||
| 29 | if (str == "grass") return StepType::grass; | ||
| 30 | if (str == "unknown") return StepType::unknown; | ||
| 31 | if (str == "paved") return StepType::paved; | ||
| 32 | if (str == "carpet") return StepType::carpet; | ||
| 33 | if (str == "weak_wood") return StepType::weak_wood; | ||
| 34 | return StepType::none; | ||
| 35 | } | ||
| 36 | |||
| 37 | inline std::string_view runningSfxForStepType(StepType step) { | ||
| 38 | switch (step) { | ||
| 39 | case StepType::wood: return "../res/running_wood.wav"; | ||
| 40 | case StepType::land_light: return "../res/running_land_light.wav"; | ||
| 41 | case StepType::land: return "../res/running_land.wav"; | ||
| 42 | case StepType::sand: return "../res/running_sand.wav"; | ||
| 43 | case StepType::water: return "../res/running_water.wav"; | ||
| 44 | case StepType::mechanical: return "../res/running_mechanical.wav"; | ||
| 45 | case StepType::grass: return "../res/running_grass.wav"; | ||
| 46 | case StepType::unknown: return "../res/running_unknown.wav"; | ||
| 47 | case StepType::paved: return "../res/running_paved.wav"; | ||
| 48 | case StepType::carpet: return "../res/running_carpet.wav"; | ||
| 49 | case StepType::weak_wood: return "../res/running_weak_wood.wav"; | ||
| 50 | case StepType::none: throw std::invalid_argument("No running sfx for none step type"); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | #endif /* end of include guard: STEP_TYPE_H_38251870 */ | ||
