summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/character_system.cpp23
-rw-r--r--src/character_system.h2
-rw-r--r--src/map.cpp14
-rw-r--r--src/map.h4
-rw-r--r--src/mixer.cpp29
-rw-r--r--src/mixer.h8
-rw-r--r--src/sprite.h3
-rw-r--r--src/step_type.h54
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) {
180void CharacterSystem::stopRunning(int spriteId) { 194void 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
251void 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
70StepType 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
9class Renderer; 10class 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
18class Map { 20class 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
35private: 39private:
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
3void Mixer::playSound(std::string filename) { 3void 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
11int 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
22void Mixer::stopChannel(int channel) {
23 Mix_HaltChannel(channel);
24}
25
26Mix_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>;
56class Mixer { 56class Mixer {
57public: 57public:
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
61private: 65private:
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
12struct SpriteFrame { 13struct 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
7enum 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
22inline 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
37inline 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 */