diff options
-rw-r--r-- | src/character_system.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 1 | ||||
-rw-r--r-- | src/sprite.h | 1 | ||||
-rw-r--r-- | src/transform_system.cpp | 70 | ||||
-rw-r--r-- | src/transform_system.h | 7 |
5 files changed, 78 insertions, 3 deletions
diff --git a/src/character_system.cpp b/src/character_system.cpp index 10cb06f..368505e 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp | |||
@@ -153,7 +153,7 @@ void CharacterSystem::tick(double dt) { | |||
153 | pLoc += (unitVecInDirection(sprite.movementDir) * speed); | 153 | pLoc += (unitVecInDirection(sprite.movementDir) * speed); |
154 | 154 | ||
155 | // Check collision. | 155 | // Check collision. |
156 | CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, sprite.loc, pLoc, sprite.movementDir); | 156 | CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, sprite.loc, pLoc, sprite.movementDir, CheckCollisionOptions::AllowSliding); |
157 | 157 | ||
158 | if (!(collision.blocked && sprite.clipping)) { | 158 | if (!(collision.blocked && sprite.clipping)) { |
159 | pLoc = collision.adjustedLoc; | 159 | pLoc = collision.adjustedLoc; |
diff --git a/src/main.cpp b/src/main.cpp index dcf96e5..b515891 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -42,6 +42,7 @@ void loop(Renderer& renderer, std::mt19937& rng) { | |||
42 | game.getSprite(lucasSprite).player = true; | 42 | game.getSprite(lucasSprite).player = true; |
43 | game.getSprite(lucasSprite).controllable = true; | 43 | game.getSprite(lucasSprite).controllable = true; |
44 | game.getSprite(lucasSprite).persistent = true; | 44 | game.getSprite(lucasSprite).persistent = true; |
45 | game.getSprite(lucasSprite).sliding = true; | ||
45 | game.getSystem<CharacterSystem>().initSprite(lucasSprite, LUCAS_MOVEMENT_SPEED); | 46 | game.getSystem<CharacterSystem>().initSprite(lucasSprite, LUCAS_MOVEMENT_SPEED); |
46 | game.getSystem<CameraSystem>().setFollowingSprite(lucasSprite); | 47 | game.getSystem<CameraSystem>().setFollowingSprite(lucasSprite); |
47 | game.getSystem<CameraSystem>().unlockCamera(); | 48 | game.getSystem<CameraSystem>().unlockCamera(); |
diff --git a/src/sprite.h b/src/sprite.h index f631652..413c20d 100644 --- a/src/sprite.h +++ b/src/sprite.h | |||
@@ -83,6 +83,7 @@ public: | |||
83 | std::string walkthroughScript; | 83 | std::string walkthroughScript; |
84 | std::string bumpPlayerScript; | 84 | std::string bumpPlayerScript; |
85 | std::string enclosureZone; | 85 | std::string enclosureZone; |
86 | bool sliding = false; | ||
86 | 87 | ||
87 | // Animation (internals) | 88 | // Animation (internals) |
88 | bool isAnimated = false; | 89 | bool isAnimated = false; |
diff --git a/src/transform_system.cpp b/src/transform_system.cpp index a643255..825514f 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp | |||
@@ -2,6 +2,10 @@ | |||
2 | #include "game.h" | 2 | #include "game.h" |
3 | #include "map.h" | 3 | #include "map.h" |
4 | 4 | ||
5 | bool checkCollisionOptionsContains(CheckCollisionOptions options, CheckCollisionOptions value) { | ||
6 | return (static_cast<int>(options) & static_cast<int>(value)) != 0; | ||
7 | } | ||
8 | |||
5 | void TransformSystem::initSprite(int spriteId, vec2i loc, SpriteLayer layer) { | 9 | void TransformSystem::initSprite(int spriteId, vec2i loc, SpriteLayer layer) { |
6 | Sprite& sprite = game_.getSprite(spriteId); | 10 | Sprite& sprite = game_.getSprite(spriteId); |
7 | sprite.loc = loc; | 11 | sprite.loc = loc; |
@@ -47,7 +51,7 @@ void TransformSystem::moveSprite(int spriteId, vec2i newLoc) { | |||
47 | } | 51 | } |
48 | } | 52 | } |
49 | 53 | ||
50 | CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir) { | 54 | CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir, CheckCollisionOptions options) { |
51 | CollisionResult result; | 55 | CollisionResult result; |
52 | 56 | ||
53 | Sprite& sprite = game_.getSprite(spriteId); | 57 | Sprite& sprite = game_.getSprite(spriteId); |
@@ -87,6 +91,22 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2 | |||
87 | break; | 91 | break; |
88 | } | 92 | } |
89 | } | 93 | } |
94 | |||
95 | if (checkCollisionOptionsContains(options, CheckCollisionOptions::AllowSliding) && | ||
96 | sprite.sliding && | ||
97 | dir == Direction::right && | ||
98 | horizBlocked && | ||
99 | oldTileUL.y() != oldTileDR.y()) { | ||
100 | // If sliding is enabled for this sprite, check if we can slide | ||
101 | // either perpendicular direction. Because sliding can only happen | ||
102 | // if we were moving in a cardinal direction, we can use tail | ||
103 | // recursion and exit early. | ||
104 | if (!map.isBlocked(oldTileDR.x()+1, oldTileUL.y())) { | ||
105 | return checkCollision(spriteId, curLoc, curLoc - vec2i{0,1} * sprite.movementSpeed, Direction::up); | ||
106 | } else if (!map.isBlocked(oldTileDR.x()+1, oldTileDR.y())) { | ||
107 | return checkCollision(spriteId, curLoc, curLoc + vec2i{0,1} * sprite.movementSpeed, Direction::down); | ||
108 | } | ||
109 | } | ||
90 | } | 110 | } |
91 | 111 | ||
92 | if (!horizBlocked && enclosureZone) { | 112 | if (!horizBlocked && enclosureZone) { |
@@ -128,6 +148,22 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2 | |||
128 | break; | 148 | break; |
129 | } | 149 | } |
130 | } | 150 | } |
151 | |||
152 | if (checkCollisionOptionsContains(options, CheckCollisionOptions::AllowSliding) && | ||
153 | sprite.sliding && | ||
154 | dir == Direction::left && | ||
155 | horizBlocked && | ||
156 | oldTileUL.y() != oldTileDR.y()) { | ||
157 | // If sliding is enabled for this sprite, check if we can slide | ||
158 | // either perpendicular direction. Because sliding can only happen | ||
159 | // if we were moving in a cardinal direction, we can use tail | ||
160 | // recursion and exit early. | ||
161 | if (!map.isBlocked(oldTileUL.x()-1, oldTileUL.y())) { | ||
162 | return checkCollision(spriteId, curLoc, curLoc - vec2i{0,1} * sprite.movementSpeed, Direction::up); | ||
163 | } else if (!map.isBlocked(oldTileUL.x()-1, oldTileDR.y())) { | ||
164 | return checkCollision(spriteId, curLoc, curLoc + vec2i{0,1} * sprite.movementSpeed, Direction::down); | ||
165 | } | ||
166 | } | ||
131 | } | 167 | } |
132 | 168 | ||
133 | if (!horizBlocked && enclosureZone) { | 169 | if (!horizBlocked && enclosureZone) { |
@@ -191,6 +227,22 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2 | |||
191 | break; | 227 | break; |
192 | } | 228 | } |
193 | } | 229 | } |
230 | |||
231 | if (checkCollisionOptionsContains(options, CheckCollisionOptions::AllowSliding) && | ||
232 | sprite.sliding && | ||
233 | dir == Direction::down && | ||
234 | vertBlocked && | ||
235 | oldTileUL.x() != oldTileDR.x()) { | ||
236 | // If sliding is enabled for this sprite, check if we can slide | ||
237 | // either perpendicular direction. Because sliding can only happen | ||
238 | // if we were moving in a cardinal direction, we can use tail | ||
239 | // recursion and exit early. | ||
240 | if (!map.isBlocked(oldTileUL.x(), oldTileDR.y()+1)) { | ||
241 | return checkCollision(spriteId, curLoc, curLoc - vec2i{1,0} * sprite.movementSpeed, Direction::left); | ||
242 | } else if (!map.isBlocked(oldTileDR.x(), oldTileDR.y()+1)) { | ||
243 | return checkCollision(spriteId, curLoc, curLoc + vec2i{1,0} * sprite.movementSpeed, Direction::right); | ||
244 | } | ||
245 | } | ||
194 | } | 246 | } |
195 | 247 | ||
196 | if (!vertBlocked && enclosureZone) { | 248 | if (!vertBlocked && enclosureZone) { |
@@ -232,6 +284,22 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2 | |||
232 | break; | 284 | break; |
233 | } | 285 | } |
234 | } | 286 | } |
287 | |||
288 | if (checkCollisionOptionsContains(options, CheckCollisionOptions::AllowSliding) && | ||
289 | sprite.sliding && | ||
290 | dir == Direction::up && | ||
291 | vertBlocked && | ||
292 | oldTileUL.x() != oldTileDR.x()) { | ||
293 | // If sliding is enabled for this sprite, check if we can slide | ||
294 | // either perpendicular direction. Because sliding can only happen | ||
295 | // if we were moving in a cardinal direction, we can use tail | ||
296 | // recursion and exit early. | ||
297 | if (!map.isBlocked(oldTileUL.x(), oldTileUL.y()-1)) { | ||
298 | return checkCollision(spriteId, curLoc, curLoc - vec2i{1,0} * sprite.movementSpeed, Direction::left); | ||
299 | } else if (!map.isBlocked(oldTileDR.x(), oldTileUL.y()-1)) { | ||
300 | return checkCollision(spriteId, curLoc, curLoc + vec2i{1,0} * sprite.movementSpeed, Direction::right); | ||
301 | } | ||
302 | } | ||
235 | } | 303 | } |
236 | 304 | ||
237 | if (!vertBlocked && enclosureZone) { | 305 | if (!vertBlocked && enclosureZone) { |
diff --git a/src/transform_system.h b/src/transform_system.h index 476b8d8..03f391a 100644 --- a/src/transform_system.h +++ b/src/transform_system.h | |||
@@ -21,6 +21,11 @@ struct CollisionResult { | |||
21 | vec2i adjustedLoc; | 21 | vec2i adjustedLoc; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | enum class CheckCollisionOptions { | ||
25 | None = 0, | ||
26 | AllowSliding = 1 << 0 | ||
27 | }; | ||
28 | |||
24 | class TransformSystem : public System { | 29 | class TransformSystem : public System { |
25 | public: | 30 | public: |
26 | 31 | ||
@@ -42,7 +47,7 @@ public: | |||
42 | }); | 47 | }); |
43 | } | 48 | } |
44 | 49 | ||
45 | CollisionResult checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir); | 50 | CollisionResult checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir, CheckCollisionOptions options = CheckCollisionOptions::None); |
46 | 51 | ||
47 | CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc); | 52 | CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc); |
48 | 53 | ||