diff options
| -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: |
