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 */ | ||