diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-02-23 22:22:49 -0500 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2021-02-24 16:00:53 -0500 |
commit | b06b259c54e09f1a4026191d6eec9684599bd370 (patch) | |
tree | f31b241c3da5559d388d97bf9e65c2104f4652e8 | |
parent | ae654356f843bb42a3c72d57b528d87aa63cf66d (diff) | |
download | tanetane-b06b259c54e09f1a4026191d6eec9684599bd370.tar.gz tanetane-b06b259c54e09f1a4026191d6eec9684599bd370.tar.bz2 tanetane-b06b259c54e09f1a4026191d6eec9684599bd370.zip |
Started working on ladders
TODO: * all the animations are weird. we will need to have an adjustable framerate bc the climbing animation does not look right at the current rate. (also remove the manual animation stuff ig) * does the medium stuff seem good and right? i am kinda not satisfied with it. * running onto a ladder causes the characters to bunch up bc the movement speed is slowed down but the trails are not doubled * no ladder running sound * shadows should vanish while on a ladder * uhh if you end a cutscene while on a ladder it resets the animation to "still" which is wrong. will this ever happen? idk * adding a sprite to your party while you are on a ladder??
-rw-r--r-- | res/maps/hallucination.tsx | 30 | ||||
-rw-r--r-- | res/sprites/boney_anim.txt | 4 | ||||
-rw-r--r-- | res/sprites/duster_anim.txt | 4 | ||||
-rw-r--r-- | res/sprites/kuma_anim.txt | 4 | ||||
-rw-r--r-- | res/sprites/lucas_anim.txt | 4 | ||||
-rw-r--r-- | src/animation_system.cpp | 20 | ||||
-rw-r--r-- | src/animation_system.h | 3 | ||||
-rw-r--r-- | src/character_system.cpp | 122 | ||||
-rw-r--r-- | src/character_system.h | 3 | ||||
-rw-r--r-- | src/map.cpp | 22 | ||||
-rw-r--r-- | src/map.h | 4 | ||||
-rw-r--r-- | src/sprite.h | 10 | ||||
-rw-r--r-- | src/transform_system.cpp | 31 | ||||
-rw-r--r-- | src/transform_system.h | 2 |
14 files changed, 224 insertions, 39 deletions
diff --git a/res/maps/hallucination.tsx b/res/maps/hallucination.tsx index 82edada..e06dab1 100644 --- a/res/maps/hallucination.tsx +++ b/res/maps/hallucination.tsx | |||
@@ -1096,6 +1096,16 @@ | |||
1096 | <property name="runSound" value="grass"/> | 1096 | <property name="runSound" value="grass"/> |
1097 | </properties> | 1097 | </properties> |
1098 | </tile> | 1098 | </tile> |
1099 | <tile id="320"> | ||
1100 | <properties> | ||
1101 | <property name="medium" value="ladder"/> | ||
1102 | </properties> | ||
1103 | </tile> | ||
1104 | <tile id="321"> | ||
1105 | <properties> | ||
1106 | <property name="medium" value="ladder"/> | ||
1107 | </properties> | ||
1108 | </tile> | ||
1099 | <tile id="322"> | 1109 | <tile id="322"> |
1100 | <properties> | 1110 | <properties> |
1101 | <property name="solid" type="bool" value="true"/> | 1111 | <property name="solid" type="bool" value="true"/> |
@@ -1151,6 +1161,11 @@ | |||
1151 | <property name="solid" type="bool" value="true"/> | 1161 | <property name="solid" type="bool" value="true"/> |
1152 | </properties> | 1162 | </properties> |
1153 | </tile> | 1163 | </tile> |
1164 | <tile id="333"> | ||
1165 | <properties> | ||
1166 | <property name="medium" value="ladder"/> | ||
1167 | </properties> | ||
1168 | </tile> | ||
1154 | <tile id="334"> | 1169 | <tile id="334"> |
1155 | <properties> | 1170 | <properties> |
1156 | <property name="solid" type="bool" value="true"/> | 1171 | <property name="solid" type="bool" value="true"/> |
@@ -1281,6 +1296,16 @@ | |||
1281 | <property name="runSound" value="grass"/> | 1296 | <property name="runSound" value="grass"/> |
1282 | </properties> | 1297 | </properties> |
1283 | </tile> | 1298 | </tile> |
1299 | <tile id="360"> | ||
1300 | <properties> | ||
1301 | <property name="medium" value="ladder"/> | ||
1302 | </properties> | ||
1303 | </tile> | ||
1304 | <tile id="361"> | ||
1305 | <properties> | ||
1306 | <property name="medium" value="ladder"/> | ||
1307 | </properties> | ||
1308 | </tile> | ||
1284 | <tile id="362"> | 1309 | <tile id="362"> |
1285 | <properties> | 1310 | <properties> |
1286 | <property name="solid" type="bool" value="true"/> | 1311 | <property name="solid" type="bool" value="true"/> |
@@ -1311,6 +1336,11 @@ | |||
1311 | <property name="solid" type="bool" value="true"/> | 1336 | <property name="solid" type="bool" value="true"/> |
1312 | </properties> | 1337 | </properties> |
1313 | </tile> | 1338 | </tile> |
1339 | <tile id="368"> | ||
1340 | <properties> | ||
1341 | <property name="medium" value="ladder"/> | ||
1342 | </properties> | ||
1343 | </tile> | ||
1314 | <tile id="369"> | 1344 | <tile id="369"> |
1315 | <properties> | 1345 | <properties> |
1316 | <property name="runSound" value="land"/> | 1346 | <property name="runSound" value="land"/> |
diff --git a/res/sprites/boney_anim.txt b/res/sprites/boney_anim.txt index a8b036c..5dfb65f 100644 --- a/res/sprites/boney_anim.txt +++ b/res/sprites/boney_anim.txt | |||
@@ -47,4 +47,6 @@ barking[up_left]: 3,35,43,35,43,35,43 | |||
47 | barking[up]: 4,36,44,36,44,36,44 | 47 | barking[up]: 4,36,44,36,44,36,44 |
48 | barking[up_right]: 5,37,45,37,45,37,45 | 48 | barking[up_right]: 5,37,45,37,45,37,45 |
49 | barking[right]: 6,38,46,38,46,38,46 | 49 | barking[right]: 6,38,46,38,46,38,46 |
50 | barking[down_right]: 7,39,47,39,47,39,47 \ No newline at end of file | 50 | barking[down_right]: 7,39,47,39,47,39,47 |
51 | climb.[up]: 240,241,242,243,244,245,246,247,248,249,250,251,252 | ||
52 | climb.[down]: 253,254,255,256,257,258,259,260,261,262,263,264,265 \ No newline at end of file | ||
diff --git a/res/sprites/duster_anim.txt b/res/sprites/duster_anim.txt index 57c470c..538ddd1 100644 --- a/res/sprites/duster_anim.txt +++ b/res/sprites/duster_anim.txt | |||
@@ -39,4 +39,6 @@ run[up_left]: 75,83,91,99,107 | |||
39 | run[up]: 76,84,92,100,108 | 39 | run[up]: 76,84,92,100,108 |
40 | run[up_right]: 77,85,93,101,109 | 40 | run[up_right]: 77,85,93,101,109 |
41 | run[right]: 78,86,94,102,110 | 41 | run[right]: 78,86,94,102,110 |
42 | run[down_right]: 79,87,95,103,111 \ No newline at end of file | 42 | run[down_right]: 79,87,95,103,111 |
43 | climb.[up]: 200,201,202,206,207,208,203,204,205,206,207,208 | ||
44 | climb.[down]: 200,201,202,206,207,208,203,204,205,206,207,208 \ No newline at end of file | ||
diff --git a/res/sprites/kuma_anim.txt b/res/sprites/kuma_anim.txt index 01ca970..a691b7d 100644 --- a/res/sprites/kuma_anim.txt +++ b/res/sprites/kuma_anim.txt | |||
@@ -47,4 +47,6 @@ talk[up_left]: 35,43 | |||
47 | talk[up]: 36,44 | 47 | talk[up]: 36,44 |
48 | talk[up_right]: 37,45 | 48 | talk[up_right]: 37,45 |
49 | talk[right]: 38,46 | 49 | talk[right]: 38,46 |
50 | talk[down_right]: 39,47 \ No newline at end of file | 50 | talk[down_right]: 39,47 |
51 | climb.[up]: 257,258,259,263,264,265,260,261,262,263,264,265 | ||
52 | climb.[down]: 257,258,259,263,264,265,260,261,262,263,264,265 \ No newline at end of file | ||
diff --git a/res/sprites/lucas_anim.txt b/res/sprites/lucas_anim.txt index 1a8b62b..cd5ee9f 100644 --- a/res/sprites/lucas_anim.txt +++ b/res/sprites/lucas_anim.txt | |||
@@ -41,4 +41,6 @@ run[up_right]: 72,80,88,96 | |||
41 | run[right]: 73,81,89,97 | 41 | run[right]: 73,81,89,97 |
42 | run[down_right]: 74,82,90,98 | 42 | run[down_right]: 74,82,90,98 |
43 | lightning_electrocute![down]: 116,117,118,116,117,118 | 43 | lightning_electrocute![down]: 116,117,118,116,117,118 |
44 | lightning_collapse![down]: 119,120,121,122 \ No newline at end of file | 44 | lightning_collapse![down]: 119,120,121,122 |
45 | climb.[up]: 123,124,125,128,127,127,129,130,131,128,127,126 | ||
46 | climb.[down]: 123,124,125,128,127,127,129,130,131,128,127,126 \ No newline at end of file | ||
diff --git a/src/animation_system.cpp b/src/animation_system.cpp index d23eae2..a280aee 100644 --- a/src/animation_system.cpp +++ b/src/animation_system.cpp | |||
@@ -65,7 +65,7 @@ void AnimationSystem::initSprite(int spriteId, std::string_view filename) { | |||
65 | std::string animLine; | 65 | std::string animLine; |
66 | std::getline(datafile, animLine); // blank | 66 | std::getline(datafile, animLine); // blank |
67 | while (std::getline(datafile, animLine)) { | 67 | while (std::getline(datafile, animLine)) { |
68 | std::regex re(R"(([a-z!_]+)\[([a-z_]+)\]: ([0-9,]+))"); | 68 | std::regex re(R"(([a-z!._]+)\[([a-z_]+)\]: ([0-9,]+))"); |
69 | std::smatch m; | 69 | std::smatch m; |
70 | std::regex_match(animLine, m, re); | 70 | std::regex_match(animLine, m, re); |
71 | 71 | ||
@@ -78,6 +78,8 @@ void AnimationSystem::initSprite(int spriteId, std::string_view filename) { | |||
78 | 78 | ||
79 | if (animName.back() == '!') { | 79 | if (animName.back() == '!') { |
80 | anim.looping = false; | 80 | anim.looping = false; |
81 | } else if (animName.back() == '.') { | ||
82 | anim.manual = true; | ||
81 | } | 83 | } |
82 | 84 | ||
83 | int animId = sprite.animations.size(); | 85 | int animId = sprite.animations.size(); |
@@ -96,7 +98,7 @@ void AnimationSystem::tick(double dt) { | |||
96 | animTimer_.accumulate(dt); | 98 | animTimer_.accumulate(dt); |
97 | while (animTimer_.step()) { | 99 | while (animTimer_.step()) { |
98 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { | 100 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { |
99 | if (sprite.isAnimated && !sprite.animFinished) { | 101 | if (sprite.isAnimated && !sprite.animFinished && !sprite.animPaused) { |
100 | sprite.animationFrame++; | 102 | sprite.animationFrame++; |
101 | 103 | ||
102 | if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { | 104 | if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { |
@@ -112,6 +114,19 @@ void AnimationSystem::tick(double dt) { | |||
112 | } | 114 | } |
113 | } | 115 | } |
114 | 116 | ||
117 | void AnimationSystem::advanceAnimation(int spriteId) { | ||
118 | Sprite& sprite = game_.getSprite(spriteId); | ||
119 | Animation& animation = sprite.animations[sprite.animationId]; | ||
120 | |||
121 | if (animation.manual) { | ||
122 | sprite.animationFrame++; | ||
123 | |||
124 | if (sprite.animationFrame >= animation.frameIndices.size()) { | ||
125 | sprite.animationFrame = 0; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
115 | void AnimationSystem::setSpriteDirection(int spriteId, Direction dir) { | 130 | void AnimationSystem::setSpriteDirection(int spriteId, Direction dir) { |
116 | Sprite& sprite = game_.getSprite(spriteId); | 131 | Sprite& sprite = game_.getSprite(spriteId); |
117 | if (sprite.dir != dir) { | 132 | if (sprite.dir != dir) { |
@@ -133,4 +148,5 @@ void AnimationSystem::updateAnimation(int spriteId) { | |||
133 | sprite.animationId = sprite.nameDirToAnim[sprite.animationName][sprite.dir]; | 148 | sprite.animationId = sprite.nameDirToAnim[sprite.animationName][sprite.dir]; |
134 | sprite.animationFrame = 0; | 149 | sprite.animationFrame = 0; |
135 | sprite.animFinished = false; | 150 | sprite.animFinished = false; |
151 | sprite.animPaused = false; | ||
136 | } | 152 | } |
diff --git a/src/animation_system.h b/src/animation_system.h index a116673..8352c19 100644 --- a/src/animation_system.h +++ b/src/animation_system.h | |||
@@ -17,6 +17,9 @@ public: | |||
17 | 17 | ||
18 | void tick(double dt) override; | 18 | void tick(double dt) override; |
19 | 19 | ||
20 | // Advances animation by a frame. Only to be used on manual animations. | ||
21 | void advanceAnimation(int spriteId); | ||
22 | |||
20 | void initSprite(int spriteId, std::string_view filename); | 23 | void initSprite(int spriteId, std::string_view filename); |
21 | 24 | ||
22 | void setSpriteDirection(int spriteId, Direction dir); | 25 | void setSpriteDirection(int spriteId, Direction dir); |
diff --git a/src/character_system.cpp b/src/character_system.cpp index 99b6929..27c2280 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp | |||
@@ -34,7 +34,7 @@ void CharacterSystem::addSpriteToParty(int leaderId, int followerId) { | |||
34 | 34 | ||
35 | for (int i=0; i<truePartyDelay; i++) { | 35 | for (int i=0; i<truePartyDelay; i++) { |
36 | vec2i tween = ((follower.loc - targetPos) * i) / static_cast<double>(truePartyDelay) + targetPos; | 36 | vec2i tween = ((follower.loc - targetPos) * i) / static_cast<double>(truePartyDelay) + targetPos; |
37 | follower.trail.push_front({.pos = tween, .dir = toFace}); | 37 | follower.trail.push_front({.pos = tween, .dir = toFace, .medium = CharacterMedium::Normal}); |
38 | } | 38 | } |
39 | 39 | ||
40 | leader.followers.push_back(followerId); | 40 | leader.followers.push_back(followerId); |
@@ -70,14 +70,31 @@ void CharacterSystem::transplantParty(int leaderId, vec2i pos, Direction dir) { | |||
70 | 70 | ||
71 | void CharacterSystem::moveInDirection(int spriteId, Direction dir) { | 71 | void CharacterSystem::moveInDirection(int spriteId, Direction dir) { |
72 | Sprite& sprite = game_.getSprite(spriteId); | 72 | Sprite& sprite = game_.getSprite(spriteId); |
73 | sprite.movementDir = dir; | ||
73 | 74 | ||
74 | game_.getSystem<AnimationSystem>().setSpriteDirection(spriteId, dir); | 75 | switch (sprite.characterMedium) { |
76 | case CharacterMedium::Normal: { | ||
77 | game_.getSystem<AnimationSystem>().setSpriteDirection(spriteId, dir); | ||
78 | break; | ||
79 | } | ||
80 | case CharacterMedium::Ladder: { | ||
81 | if (dirHasDir(dir, Direction::up)) { | ||
82 | game_.getSystem<AnimationSystem>().setSpriteDirection(spriteId, Direction::up); | ||
83 | } else if (dirHasDir(dir, Direction::down)) { | ||
84 | game_.getSystem<AnimationSystem>().setSpriteDirection(spriteId, Direction::down); | ||
85 | } | ||
86 | break; | ||
87 | } | ||
88 | } | ||
75 | 89 | ||
76 | if (sprite.characterState == CharacterState::Still) { | 90 | if (sprite.characterState == CharacterState::Still) { |
77 | setPartyState(spriteId, CharacterState::Walking); | 91 | setPartyState(spriteId, CharacterState::Walking); |
78 | } else if (sprite.characterState == CharacterState::Crouching) { | 92 | } else if (sprite.characterState == CharacterState::Crouching) { |
79 | for (int followerId : sprite.followers) { | 93 | for (int followerId : sprite.followers) { |
80 | game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, dir); | 94 | Sprite& follower = game_.getSprite(followerId); |
95 | if (follower.characterMedium == CharacterMedium::Normal) { | ||
96 | game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, dir); | ||
97 | } | ||
81 | } | 98 | } |
82 | } | 99 | } |
83 | } | 100 | } |
@@ -107,14 +124,18 @@ void CharacterSystem::tick(double dt) { | |||
107 | } | 124 | } |
108 | 125 | ||
109 | int speed = sprite.movementSpeed; | 126 | int speed = sprite.movementSpeed; |
110 | if (sprite.characterState == CharacterState::Running) { | 127 | if (sprite.characterState == CharacterState::Running && sprite.characterMedium == CharacterMedium::Normal) { |
111 | speed *= 2; | 128 | speed *= 2; |
112 | } | 129 | } |
113 | 130 | ||
114 | pLoc += (unitVecInDirection(sprite.dir) * speed); | 131 | if (sprite.characterMedium == CharacterMedium::Ladder) { |
132 | //game_.getSystem<AnimationSystem>().advanceAnimation(spriteId); | ||
133 | } | ||
134 | |||
135 | pLoc += (unitVecInDirection(sprite.movementDir) * speed); | ||
115 | 136 | ||
116 | // Check collision. | 137 | // Check collision. |
117 | CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, pLoc, sprite.dir); | 138 | CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, pLoc, sprite.movementDir); |
118 | bool blocked = collision.horiz.blocked || collision.vert.blocked; | 139 | bool blocked = collision.horiz.blocked || collision.vert.blocked; |
119 | 140 | ||
120 | if (collision.horiz.blocked && !sprite.clipping) { | 141 | if (collision.horiz.blocked && !sprite.clipping) { |
@@ -146,6 +167,12 @@ void CharacterSystem::tick(double dt) { | |||
146 | if (pLoc != sprite.loc) { | 167 | if (pLoc != sprite.loc) { |
147 | game_.getSystem<TransformSystem>().moveSprite(spriteId, pLoc); | 168 | game_.getSystem<TransformSystem>().moveSprite(spriteId, pLoc); |
148 | 169 | ||
170 | CharacterMedium newMedium = game_.getSystem<TransformSystem>().getMediumAtPosition(spriteId, pLoc); | ||
171 | if (newMedium != sprite.characterMedium) { | ||
172 | sprite.characterMedium = newMedium; | ||
173 | setAnimationFor(spriteId, sprite.characterState); | ||
174 | } | ||
175 | |||
149 | if (sprite.characterState == CharacterState::Running) { | 176 | if (sprite.characterState == CharacterState::Running) { |
150 | const Map& map = game_.getMap(); | 177 | const Map& map = game_.getMap(); |
151 | 178 | ||
@@ -164,12 +191,20 @@ void CharacterSystem::tick(double dt) { | |||
164 | 191 | ||
165 | for (int followerId : sprite.followers) { | 192 | for (int followerId : sprite.followers) { |
166 | Sprite& pNext = game_.getSprite(followerId); | 193 | Sprite& pNext = game_.getSprite(followerId); |
194 | if (pNext.characterMedium == CharacterMedium::Ladder) { | ||
195 | //game_.getSystem<AnimationSystem>().advanceAnimation(followerId); | ||
196 | } | ||
197 | |||
167 | const Movement& posdir = pNext.trail.front(); | 198 | const Movement& posdir = pNext.trail.front(); |
168 | game_.getSystem<TransformSystem>().moveSprite(followerId, posdir.pos); | 199 | game_.getSystem<TransformSystem>().moveSprite(followerId, posdir.pos); |
169 | game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, posdir.dir); | 200 | game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, posdir.dir); |
201 | if (posdir.medium != pNext.characterMedium) { | ||
202 | pNext.characterMedium = posdir.medium; | ||
203 | setAnimationFor(followerId, sprite.characterState); | ||
204 | } | ||
170 | 205 | ||
171 | pNext.trail.pop_front(); | 206 | pNext.trail.pop_front(); |
172 | pNext.trail.push_back({.pos = pLoc, .dir = sprite.dir}); | 207 | pNext.trail.push_back({.pos = pLoc, .dir = sprite.dir, .medium = sprite.characterMedium}); |
173 | } | 208 | } |
174 | } | 209 | } |
175 | } | 210 | } |
@@ -180,6 +215,10 @@ void CharacterSystem::tick(double dt) { | |||
180 | void CharacterSystem::beginCrouch(int spriteId) { | 215 | void CharacterSystem::beginCrouch(int spriteId) { |
181 | Sprite& sprite = game_.getSprite(spriteId); | 216 | Sprite& sprite = game_.getSprite(spriteId); |
182 | 217 | ||
218 | if (sprite.characterMedium == CharacterMedium::Ladder) { | ||
219 | return; | ||
220 | } | ||
221 | |||
183 | if (sprite.characterState == CharacterState::Running) { | 222 | if (sprite.characterState == CharacterState::Running) { |
184 | stopRunning(spriteId); | 223 | stopRunning(spriteId); |
185 | } else { | 224 | } else { |
@@ -242,32 +281,12 @@ void CharacterSystem::stopRunning(int spriteId) { | |||
242 | } | 281 | } |
243 | 282 | ||
244 | void CharacterSystem::setPartyState(int spriteId, CharacterState state) { | 283 | void CharacterSystem::setPartyState(int spriteId, CharacterState state) { |
245 | std::string animName; | ||
246 | switch (state) { | ||
247 | case CharacterState::Still: { | ||
248 | animName = "still"; | ||
249 | break; | ||
250 | } | ||
251 | case CharacterState::Walking: { | ||
252 | animName = "walk"; | ||
253 | break; | ||
254 | } | ||
255 | case CharacterState::Crouching: { | ||
256 | animName = "crouch"; | ||
257 | break; | ||
258 | } | ||
259 | case CharacterState::Running: { | ||
260 | animName = "run"; | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | Sprite& sprite = game_.getSprite(spriteId); | 284 | Sprite& sprite = game_.getSprite(spriteId); |
266 | sprite.characterState = state; | 285 | sprite.characterState = state; |
267 | 286 | ||
268 | game_.getSystem<AnimationSystem>().setSpriteAnimation(spriteId, animName); | 287 | setAnimationFor(spriteId, state); |
269 | for (int followerId : sprite.followers) { | 288 | for (int followerId : sprite.followers) { |
270 | game_.getSystem<AnimationSystem>().setSpriteAnimation(followerId, animName); | 289 | setAnimationFor(followerId, state); |
271 | } | 290 | } |
272 | } | 291 | } |
273 | 292 | ||
@@ -297,3 +316,48 @@ void CharacterSystem::destroySprite(int spriteId) { | |||
297 | stopRunningSound(sprite); | 316 | stopRunningSound(sprite); |
298 | } | 317 | } |
299 | } | 318 | } |
319 | |||
320 | void CharacterSystem::setAnimationFor(int spriteId, CharacterState state) { | ||
321 | Sprite& sprite = game_.getSprite(spriteId); | ||
322 | std::string animName; | ||
323 | |||
324 | switch (sprite.characterMedium) { | ||
325 | case CharacterMedium::Normal: { | ||
326 | std::string animName; | ||
327 | |||
328 | switch (state) { | ||
329 | case CharacterState::Still: { | ||
330 | animName = "still"; | ||
331 | break; | ||
332 | } | ||
333 | case CharacterState::Walking: { | ||
334 | animName = "walk"; | ||
335 | break; | ||
336 | } | ||
337 | case CharacterState::Crouching: { | ||
338 | animName = "crouch"; | ||
339 | break; | ||
340 | } | ||
341 | case CharacterState::Running: { | ||
342 | animName = "run"; | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | game_.getSystem<AnimationSystem>().setSpriteAnimation(spriteId, animName); | ||
348 | |||
349 | break; | ||
350 | } | ||
351 | case CharacterMedium::Ladder: { | ||
352 | game_.getSystem<AnimationSystem>().setSpriteAnimation(spriteId, "climb."); | ||
353 | |||
354 | if (state == CharacterState::Still || state == CharacterState::Crouching) { | ||
355 | sprite.animPaused = true; | ||
356 | } else { | ||
357 | sprite.animPaused = false; | ||
358 | } | ||
359 | |||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | } | ||
diff --git a/src/character_system.h b/src/character_system.h index 79c1710..ef49d0e 100644 --- a/src/character_system.h +++ b/src/character_system.h | |||
@@ -47,6 +47,9 @@ private: | |||
47 | 47 | ||
48 | void stopRunningSound(Sprite& sprite); | 48 | void stopRunningSound(Sprite& sprite); |
49 | 49 | ||
50 | // state should be the party leader's state | ||
51 | void setAnimationFor(int spriteId, CharacterState state); | ||
52 | |||
50 | Game& game_; | 53 | Game& game_; |
51 | Timer inputTimer_ {33}; | 54 | Timer inputTimer_ {33}; |
52 | }; | 55 | }; |
diff --git a/src/map.cpp b/src/map.cpp index 4781231..0425962 100644 --- a/src/map.cpp +++ b/src/map.cpp | |||
@@ -44,6 +44,10 @@ Map::Map(std::string_view name) : name_(name) { | |||
44 | tile.blocked = true; | 44 | tile.blocked = true; |
45 | } else if (property.getName() == "runSound") { | 45 | } else if (property.getName() == "runSound") { |
46 | tile.step = stepTypeFromString(property.getStringValue()); | 46 | tile.step = stepTypeFromString(property.getStringValue()); |
47 | } else if (property.getName() == "medium") { | ||
48 | if (property.getStringValue() == "ladder") { | ||
49 | tile.medium = CharacterMedium::Ladder; | ||
50 | } | ||
47 | } | 51 | } |
48 | } | 52 | } |
49 | 53 | ||
@@ -178,3 +182,21 @@ StepType Map::getStepType(int x, int y) const { | |||
178 | 182 | ||
179 | return StepType::none; | 183 | return StepType::none; |
180 | } | 184 | } |
185 | |||
186 | CharacterMedium Map::getMedium(int x, int y) const { | ||
187 | CharacterMedium ret = CharacterMedium::Normal; | ||
188 | |||
189 | if (x < 0 || y < 0 || x >= mapSize_.w() || y >= mapSize_.h()) { | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | int i = x + y * mapSize_.w(); | ||
194 | |||
195 | for (const std::vector<Tile>& layer : lowerLayers_) { | ||
196 | if (layer.at(i).medium > ret) { | ||
197 | ret = layer.at(i).medium; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | return ret; | ||
202 | } | ||
diff --git a/src/map.h b/src/map.h index 9467d75..1a88cc8 100644 --- a/src/map.h +++ b/src/map.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <vector> | 7 | #include <vector> |
8 | #include "vector.h" | 8 | #include "vector.h" |
9 | #include "step_type.h" | 9 | #include "step_type.h" |
10 | #include "sprite.h" | ||
10 | 11 | ||
11 | struct Tile { | 12 | struct Tile { |
12 | unsigned int id = 0; | 13 | unsigned int id = 0; |
@@ -14,6 +15,7 @@ struct Tile { | |||
14 | bool flipVertical = false; | 15 | bool flipVertical = false; |
15 | bool blocked = false; | 16 | bool blocked = false; |
16 | StepType step = StepType::none; | 17 | StepType step = StepType::none; |
18 | CharacterMedium medium = CharacterMedium::Normal; | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | struct Prototype { | 21 | struct Prototype { |
@@ -64,6 +66,8 @@ public: | |||
64 | 66 | ||
65 | StepType getStepType(int x, int y) const; | 67 | StepType getStepType(int x, int y) const; |
66 | 68 | ||
69 | CharacterMedium getMedium(int x, int y) const; | ||
70 | |||
67 | const std::vector<Prototype>& getPrototypes() const { return prototypes_; } | 71 | const std::vector<Prototype>& getPrototypes() const { return prototypes_; } |
68 | 72 | ||
69 | const vec2i& getWarpPoint(const std::string& name) const { return warpPoints_.at(name); } | 73 | const vec2i& getWarpPoint(const std::string& name) const { return warpPoints_.at(name); } |
diff --git a/src/sprite.h b/src/sprite.h index 3d2e9df..59d2caf 100644 --- a/src/sprite.h +++ b/src/sprite.h | |||
@@ -23,6 +23,7 @@ struct SpriteFrame { | |||
23 | 23 | ||
24 | struct Animation { | 24 | struct Animation { |
25 | bool looping = true; | 25 | bool looping = true; |
26 | bool manual = false; | ||
26 | std::vector<int> frameIndices; | 27 | std::vector<int> frameIndices; |
27 | }; | 28 | }; |
28 | 29 | ||
@@ -33,9 +34,15 @@ enum class CharacterState { | |||
33 | Running | 34 | Running |
34 | }; | 35 | }; |
35 | 36 | ||
37 | enum class CharacterMedium { | ||
38 | Normal, | ||
39 | Ladder | ||
40 | }; | ||
41 | |||
36 | struct Movement { | 42 | struct Movement { |
37 | vec2i pos; | 43 | vec2i pos; |
38 | Direction dir; | 44 | Direction dir; |
45 | CharacterMedium medium; | ||
39 | }; | 46 | }; |
40 | 47 | ||
41 | class Sprite { | 48 | class Sprite { |
@@ -68,6 +75,7 @@ public: | |||
68 | std::map<std::string, std::map<Direction, int>> nameDirToAnim; | 75 | std::map<std::string, std::map<Direction, int>> nameDirToAnim; |
69 | bool animFinished = false; | 76 | bool animFinished = false; |
70 | bool hasShadow = false; | 77 | bool hasShadow = false; |
78 | bool animPaused = false; | ||
71 | 79 | ||
72 | // Character | 80 | // Character |
73 | bool orientable = false; | 81 | bool orientable = false; |
@@ -75,6 +83,8 @@ public: | |||
75 | std::vector<int> followers; | 83 | std::vector<int> followers; |
76 | std::deque<Movement> trail; | 84 | std::deque<Movement> trail; |
77 | CharacterState characterState = CharacterState::Still; | 85 | CharacterState characterState = CharacterState::Still; |
86 | CharacterMedium characterMedium = CharacterMedium::Normal; | ||
87 | Direction movementDir = Direction::down; | ||
78 | StepType stepType = StepType::none; | 88 | StepType stepType = StepType::none; |
79 | int runningSfxChannel = -1; | 89 | int runningSfxChannel = -1; |
80 | bool clipping = false; | 90 | bool clipping = false; |
diff --git a/src/transform_system.cpp b/src/transform_system.cpp index ee392f1..4056f46 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp | |||
@@ -72,7 +72,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire | |||
72 | enclosureZone = &map.getZone(sprite.enclosureZone); | 72 | enclosureZone = &map.getZone(sprite.enclosureZone); |
73 | } | 73 | } |
74 | 74 | ||
75 | if (dirHasDir(sprite.dir, Direction::right)) { | 75 | if (dirHasDir(dir, Direction::right)) { |
76 | if (newTileDR.x() > oldTileDR.x() && | 76 | if (newTileDR.x() > oldTileDR.x() && |
77 | newColDR.x() < mapBounds.w()) { | 77 | newColDR.x() < mapBounds.w()) { |
78 | for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { | 78 | for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { |
@@ -113,7 +113,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire | |||
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | if (dirHasDir(sprite.dir, Direction::left)) { | 116 | if (dirHasDir(dir, Direction::left)) { |
117 | if (newTileUL.x() < oldTileUL.x() && | 117 | if (newTileUL.x() < oldTileUL.x() && |
118 | newColUL.x() >= 0) { | 118 | newColUL.x() >= 0) { |
119 | for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { | 119 | for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { |
@@ -154,7 +154,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire | |||
154 | } | 154 | } |
155 | } | 155 | } |
156 | 156 | ||
157 | if (dirHasDir(sprite.dir, Direction::down)) { | 157 | if (dirHasDir(dir, Direction::down)) { |
158 | if (newTileDR.y() > oldTileDR.y() && | 158 | if (newTileDR.y() > oldTileDR.y() && |
159 | newColDR.y() < mapBounds.h()) { | 159 | newColDR.y() < mapBounds.h()) { |
160 | for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { | 160 | for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { |
@@ -195,7 +195,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire | |||
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | if (dirHasDir(sprite.dir, Direction::up)) { | 198 | if (dirHasDir(dir, Direction::up)) { |
199 | if (newTileUL.y() < oldTileUL.y() && | 199 | if (newTileUL.y() < oldTileUL.y() && |
200 | newColUL.y() >= 0) { | 200 | newColUL.y() >= 0) { |
201 | for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { | 201 | for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { |
@@ -239,6 +239,29 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire | |||
239 | return result; | 239 | return result; |
240 | } | 240 | } |
241 | 241 | ||
242 | CharacterMedium TransformSystem::getMediumAtPosition(int spriteId, vec2i newLoc) { | ||
243 | Sprite& sprite = game_.getSprite(spriteId); | ||
244 | |||
245 | const Map& map = game_.getMap(); | ||
246 | |||
247 | vec2i newColUL = newLoc + sprite.collisionOffset; | ||
248 | vec2i newColDR = newColUL + sprite.collisionSize; | ||
249 | vec2i newTileUL = newColUL / map.getTileSize(); | ||
250 | vec2i newTileDR = newColDR / map.getTileSize(); | ||
251 | |||
252 | CharacterMedium result = CharacterMedium::Normal; | ||
253 | for (int y=newTileUL.y(); y<=newTileDR.y(); y++) { | ||
254 | for (int x=newTileUL.x(); x<=newTileDR.x(); x++) { | ||
255 | CharacterMedium tileMedium = map.getMedium(x, y); | ||
256 | if (tileMedium > result) { | ||
257 | result = tileMedium; | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | |||
262 | return result; | ||
263 | } | ||
264 | |||
242 | void TransformSystem::addCollidable(int spriteId) { | 265 | void TransformSystem::addCollidable(int spriteId) { |
243 | Sprite& sprite = game_.getSprite(spriteId); | 266 | Sprite& sprite = game_.getSprite(spriteId); |
244 | 267 | ||
diff --git a/src/transform_system.h b/src/transform_system.h index d894b30..a07447c 100644 --- a/src/transform_system.h +++ b/src/transform_system.h | |||
@@ -47,6 +47,8 @@ public: | |||
47 | 47 | ||
48 | CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); | 48 | CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); |
49 | 49 | ||
50 | CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc); | ||
51 | |||
50 | void destroySprite(int spriteId) override; | 52 | void destroySprite(int spriteId) override; |
51 | 53 | ||
52 | private: | 54 | private: |