summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2021-03-11 16:06:19 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2021-03-11 17:33:15 -0500
commiteb9fa5020317a44f17cc4906c4c1c6fe55700d3e (patch)
treee4cb67d97818e06d974d0fca987dd76f25affdf9
parent4c29543e44deb7a327b21b0af6a85a92e83ff103 (diff)
downloadtanetane-eb9fa5020317a44f17cc4906c4c1c6fe55700d3e.tar.gz
tanetane-eb9fa5020317a44f17cc4906c4c1c6fe55700d3e.tar.bz2
tanetane-eb9fa5020317a44f17cc4906c4c1c6fe55700d3e.zip
Simplified collision detection output
It is no longer split into horizontal and vertical results. Also, the collision detection routine now does the work of calculating an adjusted position, instead of the caller (CharacterSystem) having to do it. This will be useful for #3.
-rw-r--r--src/behaviour_system.cpp2
-rw-r--r--src/character_system.cpp47
-rw-r--r--src/input_system.cpp18
-rw-r--r--src/transform_system.cpp84
-rw-r--r--src/transform_system.h11
5 files changed, 75 insertions, 87 deletions
diff --git a/src/behaviour_system.cpp b/src/behaviour_system.cpp index f4f7546..ce980f6 100644 --- a/src/behaviour_system.cpp +++ b/src/behaviour_system.cpp
@@ -196,7 +196,7 @@ void BehaviourSystem::createPath(int spriteId) {
196 } 196 }
197 197
198 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, searchNode.point, newPos, dir); 198 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, searchNode.point, newPos, dir);
199 if (collision.horiz.blocked || collision.vert.blocked) { 199 if (collision.blocked) {
200 // There isn't actually an edge to this neighbor. 200 // There isn't actually an edge to this neighbor.
201 continue; 201 continue;
202 } 202 }
diff --git a/src/character_system.cpp b/src/character_system.cpp index 548bd9d..10cb06f 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp
@@ -154,46 +154,35 @@ void CharacterSystem::tick(double dt) {
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);
157 bool blocked = collision.horiz.blocked || collision.vert.blocked;
158 int colliderSpriteId = (collision.horiz.colliderSprite == -1) ? collision.vert.colliderSprite : collision.horiz.colliderSprite;
159 157
160 if (collision.horiz.blocked && !sprite.clipping) { 158 if (!(collision.blocked && sprite.clipping)) {
161 pLoc.x() = sprite.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; 159 pLoc = collision.adjustedLoc;
162 } else if (collision.horiz.colliderSprite != -1) {
163 Sprite& collider = game_.getSprite(collision.horiz.colliderSprite);
164
165 if (collider.walkthroughScript != "") {
166 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.walkthroughScript);
167 }
168 } 160 }
169 161
170 if (collision.vert.blocked && !sprite.clipping) { 162 for (int colliderSpriteId : collision.colliders) {
171 pLoc.y() = sprite.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; 163 Sprite& collider = game_.getSprite(colliderSpriteId);
172 } else if (collision.vert.colliderSprite != -1) {
173 Sprite& collider = game_.getSprite(collision.vert.colliderSprite);
174 164
175 if (collider.walkthroughScript != "") { 165 if (!collider.walkthroughScript.empty()) {
176 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.walkthroughScript); 166 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.walkthroughScript);
177 } 167 }
178 }
179 168
180 if (blocked && sprite.characterState == CharacterState::Running && !sprite.clipping) { 169 if (!sprite.bumpPlayerScript.empty()) {
181 stopRunning(spriteId); 170 bool bumpedPlayer = collider.player;
182 game_.getMixer().playSound("../res/sfx/bump.wav");
183 }
184 171
185 if (colliderSpriteId != -1 && !sprite.bumpPlayerScript.empty()) { 172 if (!bumpedPlayer && collider.leaderId != -1) {
186 Sprite& collider = game_.getSprite(colliderSpriteId); 173 Sprite& colliderLeader = game_.getSprite(collider.leaderId);
187 bool bumpedPlayer = collider.player; 174 bumpedPlayer = colliderLeader.player;
175 }
188 176
189 if (!bumpedPlayer && collider.leaderId != -1) { 177 if (bumpedPlayer) {
190 Sprite& colliderLeader = game_.getSprite(collider.leaderId); 178 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), sprite.bumpPlayerScript);
191 bumpedPlayer = colliderLeader.player; 179 }
192 } 180 }
181 }
193 182
194 if (bumpedPlayer) { 183 if (collision.blocked && sprite.characterState == CharacterState::Running && !sprite.clipping) {
195 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), sprite.bumpPlayerScript); 184 stopRunning(spriteId);
196 } 185 game_.getMixer().playSound("../res/sfx/bump.wav");
197 } 186 }
198 187
199 // Move everything 188 // Move everything
diff --git a/src/input_system.cpp b/src/input_system.cpp index 38423a2..c399e91 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp
@@ -87,25 +87,17 @@ void InputSystem::tick(double dt) {
87 vec2i checkLoc = sprite.loc + (unitVecInDirection(sprite.dir) * LUCAS_MOVEMENT_SPEED); 87 vec2i checkLoc = sprite.loc + (unitVecInDirection(sprite.dir) * LUCAS_MOVEMENT_SPEED);
88 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, sprite.loc, checkLoc, sprite.dir); 88 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, sprite.loc, checkLoc, sprite.dir);
89 89
90 if (collision.horiz.blocked || collision.vert.blocked) { 90 if (collision.blocked) {
91 inFrontOfSomething = true; 91 inFrontOfSomething = true;
92 } 92 }
93 93
94 // If there is a sprite to be interacted with, rotate that sprite so it is facing the player. 94 // If there is a sprite to be interacted with, rotate that sprite so it is facing the player.
95 // Then, run its interaction script if present. 95 // Then, run its interaction script if present.
96 if (collision.horiz.colliderSprite != -1) { 96 for (int colliderSpriteId : collision.colliders) {
97 game_.getSystem<AnimationSystem>().setSpriteDirection(collision.horiz.colliderSprite, oppositeDirection(sprite.dir)); 97 game_.getSystem<AnimationSystem>().setSpriteDirection(colliderSpriteId, oppositeDirection(sprite.dir));
98 98
99 Sprite& collider = game_.getSprite(collision.horiz.colliderSprite); 99 Sprite& collider = game_.getSprite(colliderSpriteId);
100 if (collider.interactionScript != "") { 100 if (!collider.interactionScript.empty()) {
101 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.interactionScript);
102 activated = true;
103 }
104 } else if (collision.vert.colliderSprite != -1) {
105 game_.getSystem<AnimationSystem>().setSpriteDirection(collision.vert.colliderSprite, oppositeDirection(sprite.dir));
106
107 Sprite& collider = game_.getSprite(collision.vert.colliderSprite);
108 if (collider.interactionScript != "") {
109 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.interactionScript); 101 game_.getSystem<ScriptSystem>().runScript(game_.getMap().getName(), collider.interactionScript);
110 activated = true; 102 activated = true;
111 } 103 }
diff --git a/src/transform_system.cpp b/src/transform_system.cpp index 4ed47c0..a643255 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp
@@ -59,6 +59,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
59 59
60 // First check horizontal movement only. 60 // First check horizontal movement only.
61 vec2i horizMovement = { newLoc.x(), curLoc.y() }; 61 vec2i horizMovement = { newLoc.x(), curLoc.y() };
62 bool horizBlocked = false;
62 63
63 vec2i oldColUL = curLoc + sprite.collisionOffset; 64 vec2i oldColUL = curLoc + sprite.collisionOffset;
64 vec2i oldColDR = oldColUL + sprite.collisionSize - vec2i{1,1}; 65 vec2i oldColDR = oldColUL + sprite.collisionSize - vec2i{1,1};
@@ -80,23 +81,23 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
80 newColDR.x() < mapBounds.w()) { 81 newColDR.x() < mapBounds.w()) {
81 for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { 82 for (int y = newTileUL.y(); y <= newTileDR.y(); y++) {
82 if (map.isBlocked(newTileDR.x(), y)) { 83 if (map.isBlocked(newTileDR.x(), y)) {
83 result.horiz.blocked = true; 84 horizBlocked = true;
84 result.horiz.dir = Direction::right; 85 result.dir = Direction::right;
85 86
86 break; 87 break;
87 } 88 }
88 } 89 }
89 } 90 }
90 91
91 if (!result.horiz.blocked && enclosureZone) { 92 if (!horizBlocked && enclosureZone) {
92 if (oldColDR.x() <= enclosureZone->dr.x()-1 && 93 if (oldColDR.x() <= enclosureZone->dr.x()-1 &&
93 newColDR.x() > enclosureZone->dr.x()-1) { 94 newColDR.x() > enclosureZone->dr.x()-1) {
94 result.horiz.blocked = true; 95 horizBlocked = true;
95 result.horiz.dir = Direction::right; 96 result.dir = Direction::right;
96 } 97 }
97 } 98 }
98 99
99 if (!result.horiz.blocked) { 100 if (!horizBlocked) {
100 auto it = rightCollidables_.lower_bound({oldColDR.x()+1, 0}); 101 auto it = rightCollidables_.lower_bound({oldColDR.x()+1, 0});
101 for (; 102 for (;
102 (it != std::end(rightCollidables_) && 103 (it != std::end(rightCollidables_) &&
@@ -106,9 +107,9 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
106 newColUL.y() <= it->second.upper) { 107 newColUL.y() <= it->second.upper) {
107 int colliderSpriteId = std::get<1>(it->first); 108 int colliderSpriteId = std::get<1>(it->first);
108 Sprite& collider = game_.getSprite(colliderSpriteId); 109 Sprite& collider = game_.getSprite(colliderSpriteId);
109 result.horiz.blocked = collider.solid; 110 horizBlocked = collider.solid;
110 result.horiz.dir = Direction::right; 111 result.dir = Direction::right;
111 result.horiz.colliderSprite = colliderSpriteId; 112 result.colliders.push_back(colliderSpriteId);
112 113
113 break; 114 break;
114 } 115 }
@@ -121,23 +122,23 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
121 newColUL.x() >= 0) { 122 newColUL.x() >= 0) {
122 for (int y = newTileUL.y(); y <= newTileDR.y(); y++) { 123 for (int y = newTileUL.y(); y <= newTileDR.y(); y++) {
123 if (map.isBlocked(newTileUL.x(), y)) { 124 if (map.isBlocked(newTileUL.x(), y)) {
124 result.horiz.blocked = true; 125 horizBlocked = true;
125 result.horiz.dir = Direction::left; 126 result.dir = Direction::left;
126 127
127 break; 128 break;
128 } 129 }
129 } 130 }
130 } 131 }
131 132
132 if (!result.horiz.blocked && enclosureZone) { 133 if (!horizBlocked && enclosureZone) {
133 if (oldColUL.x() >= enclosureZone->ul.x() && 134 if (oldColUL.x() >= enclosureZone->ul.x() &&
134 newColUL.x() < enclosureZone->ul.x()) { 135 newColUL.x() < enclosureZone->ul.x()) {
135 result.horiz.blocked = true; 136 horizBlocked = true;
136 result.horiz.dir = Direction::left; 137 result.dir = Direction::left;
137 } 138 }
138 } 139 }
139 140
140 if (!result.horiz.blocked) { 141 if (!horizBlocked) {
141 auto it = leftCollidables_.lower_bound({oldColUL.x()-1, INT_MAX}); 142 auto it = leftCollidables_.lower_bound({oldColUL.x()-1, INT_MAX});
142 for (; 143 for (;
143 (it != std::end(leftCollidables_) && 144 (it != std::end(leftCollidables_) &&
@@ -147,9 +148,9 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
147 newColUL.y() <= it->second.upper) { 148 newColUL.y() <= it->second.upper) {
148 int colliderSpriteId = std::get<1>(it->first); 149 int colliderSpriteId = std::get<1>(it->first);
149 Sprite& collider = game_.getSprite(colliderSpriteId); 150 Sprite& collider = game_.getSprite(colliderSpriteId);
150 result.horiz.blocked = collider.solid; 151 horizBlocked = collider.solid;
151 result.horiz.dir = Direction::left; 152 result.dir = Direction::left;
152 result.horiz.colliderSprite = colliderSpriteId; 153 result.colliders.push_back(colliderSpriteId);
153 154
154 break; 155 break;
155 } 156 }
@@ -161,12 +162,14 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
161 // taken place (as long as it was not in fact blocked). 162 // taken place (as long as it was not in fact blocked).
162 vec2i effectiveCurLoc = curLoc; 163 vec2i effectiveCurLoc = curLoc;
163 vec2i vertMovement = newLoc; 164 vec2i vertMovement = newLoc;
164 if (result.horiz.blocked) { 165 if (horizBlocked) {
165 vertMovement.x() = curLoc.x(); 166 vertMovement.x() = curLoc.x();
166 } else { 167 } else {
167 effectiveCurLoc.x() = newLoc.x(); 168 effectiveCurLoc.x() = newLoc.x();
168 } 169 }
169 170
171 bool vertBlocked = false;
172
170 oldColUL = effectiveCurLoc + sprite.collisionOffset; 173 oldColUL = effectiveCurLoc + sprite.collisionOffset;
171 oldColDR = oldColUL + sprite.collisionSize - vec2i{1,1}; 174 oldColDR = oldColUL + sprite.collisionSize - vec2i{1,1};
172 newColUL = vertMovement + sprite.collisionOffset; 175 newColUL = vertMovement + sprite.collisionOffset;
@@ -182,23 +185,23 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
182 newColDR.y() < mapBounds.h()) { 185 newColDR.y() < mapBounds.h()) {
183 for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { 186 for (int x = newTileUL.x(); x <= newTileDR.x(); x++) {
184 if (map.isBlocked(x, newTileDR.y())) { 187 if (map.isBlocked(x, newTileDR.y())) {
185 result.vert.blocked = true; 188 vertBlocked = true;
186 result.vert.dir = Direction::down; 189 result.dir = Direction::down;
187 190
188 break; 191 break;
189 } 192 }
190 } 193 }
191 } 194 }
192 195
193 if (!result.vert.blocked && enclosureZone) { 196 if (!vertBlocked && enclosureZone) {
194 if (oldColDR.y() <= enclosureZone->dr.y()-1 && 197 if (oldColDR.y() <= enclosureZone->dr.y()-1 &&
195 newColDR.y() > enclosureZone->dr.y()-1) { 198 newColDR.y() > enclosureZone->dr.y()-1) {
196 result.vert.blocked = true; 199 vertBlocked = true;
197 result.vert.dir = Direction::down; 200 result.dir = Direction::down;
198 } 201 }
199 } 202 }
200 203
201 if (!result.vert.blocked) { 204 if (!vertBlocked) {
202 auto it = downCollidables_.lower_bound({oldColDR.y()+1, 0}); 205 auto it = downCollidables_.lower_bound({oldColDR.y()+1, 0});
203 for (; 206 for (;
204 (it != std::end(downCollidables_) && 207 (it != std::end(downCollidables_) &&
@@ -208,9 +211,9 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
208 newColUL.x() <= it->second.upper) { 211 newColUL.x() <= it->second.upper) {
209 int colliderSpriteId = std::get<1>(it->first); 212 int colliderSpriteId = std::get<1>(it->first);
210 Sprite& collider = game_.getSprite(colliderSpriteId); 213 Sprite& collider = game_.getSprite(colliderSpriteId);
211 result.vert.blocked = collider.solid; 214 vertBlocked = collider.solid;
212 result.vert.dir = Direction::down; 215 result.dir = Direction::down;
213 result.vert.colliderSprite = colliderSpriteId; 216 result.colliders.push_back(colliderSpriteId);
214 217
215 break; 218 break;
216 } 219 }
@@ -223,23 +226,23 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
223 newColUL.y() >= 0) { 226 newColUL.y() >= 0) {
224 for (int x = newTileUL.x(); x <= newTileDR.x(); x++) { 227 for (int x = newTileUL.x(); x <= newTileDR.x(); x++) {
225 if (map.isBlocked(x, newTileUL.y())) { 228 if (map.isBlocked(x, newTileUL.y())) {
226 result.vert.blocked = true; 229 vertBlocked = true;
227 result.vert.dir = Direction::up; 230 result.dir = Direction::up;
228 231
229 break; 232 break;
230 } 233 }
231 } 234 }
232 } 235 }
233 236
234 if (!result.vert.blocked && enclosureZone) { 237 if (!vertBlocked && enclosureZone) {
235 if (oldColUL.y() >= enclosureZone->ul.y() && 238 if (oldColUL.y() >= enclosureZone->ul.y() &&
236 newColUL.y() < enclosureZone->ul.y()) { 239 newColUL.y() < enclosureZone->ul.y()) {
237 result.vert.blocked = true; 240 vertBlocked = true;
238 result.vert.dir = Direction::up; 241 result.dir = Direction::up;
239 } 242 }
240 } 243 }
241 244
242 if (!result.vert.blocked) { 245 if (!vertBlocked) {
243 auto it = upCollidables_.lower_bound({oldColUL.y()-1, INT_MAX}); 246 auto it = upCollidables_.lower_bound({oldColUL.y()-1, INT_MAX});
244 for (; 247 for (;
245 (it != std::end(upCollidables_) && 248 (it != std::end(upCollidables_) &&
@@ -249,9 +252,9 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
249 newColUL.x() <= it->second.upper) { 252 newColUL.x() <= it->second.upper) {
250 int colliderSpriteId = std::get<1>(it->first); 253 int colliderSpriteId = std::get<1>(it->first);
251 Sprite& collider = game_.getSprite(colliderSpriteId); 254 Sprite& collider = game_.getSprite(colliderSpriteId);
252 result.vert.blocked = collider.solid; 255 vertBlocked = collider.solid;
253 result.vert.dir = Direction::up; 256 result.dir = Direction::up;
254 result.vert.colliderSprite = colliderSpriteId; 257 result.colliders.push_back(colliderSpriteId);
255 258
256 break; 259 break;
257 } 260 }
@@ -259,6 +262,13 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2
259 } 262 }
260 } 263 }
261 264
265 result.adjustedLoc = vertMovement;
266 if (vertBlocked) {
267 result.adjustedLoc.y() = effectiveCurLoc.y();
268 }
269
270 result.blocked = horizBlocked || vertBlocked;
271
262 return result; 272 return result;
263} 273}
264 274
diff --git a/src/transform_system.h b/src/transform_system.h index 7fa3423..476b8d8 100644 --- a/src/transform_system.h +++ b/src/transform_system.h
@@ -5,6 +5,7 @@
5#include <set> 5#include <set>
6#include <map> 6#include <map>
7#include <tuple> 7#include <tuple>
8#include <list>
8#include "direction.h" 9#include "direction.h"
9#include "system.h" 10#include "system.h"
10#include "vector.h" 11#include "vector.h"
@@ -13,15 +14,11 @@
13 14
14class Game; 15class Game;
15 16
16struct AxisResult { 17struct CollisionResult {
17 Direction dir; 18 Direction dir;
18 bool blocked = false; 19 bool blocked = false;
19 int colliderSprite = -1; 20 std::list<int> colliders;
20}; 21 vec2i adjustedLoc;
21
22struct CollisionResult {
23 AxisResult horiz;
24 AxisResult vert;
25}; 22};
26 23
27class TransformSystem : public System { 24class TransformSystem : public System {