summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--res/maps/underwater_start.tmx5
-rw-r--r--res/scripts/common.lua54
-rw-r--r--res/scripts/underwater_start.lua21
-rw-r--r--src/behaviour_system.cpp171
-rw-r--r--src/behaviour_system.h12
-rw-r--r--src/character_system.cpp2
-rw-r--r--src/game.cpp2
-rw-r--r--src/input_system.cpp2
-rw-r--r--src/script_system.cpp15
-rw-r--r--src/sprite.h16
-rw-r--r--src/transform_system.cpp4
-rw-r--r--src/transform_system.h2
-rw-r--r--src/vector.h4
13 files changed, 300 insertions, 10 deletions
diff --git a/res/maps/underwater_start.tmx b/res/maps/underwater_start.tmx index 7f9cb8c..0ced9c4 100644 --- a/res/maps/underwater_start.tmx +++ b/res/maps/underwater_start.tmx
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="UTF-8"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<map version="1.4" tiledversion="1.4.3" orientation="orthogonal" renderorder="right-down" width="32" height="32" tilewidth="16" tileheight="16" infinite="0" nextlayerid="4" nextobjectid="4"> 2<map version="1.4" tiledversion="1.4.3" orientation="orthogonal" renderorder="right-down" width="32" height="32" tilewidth="16" tileheight="16" infinite="0" nextlayerid="4" nextobjectid="5">
3 <properties> 3 <properties>
4 <property name="music" value="barren_factory"/> 4 <property name="music" value="barren_factory"/>
5 </properties> 5 </properties>
@@ -96,6 +96,9 @@
96 <point/> 96 <point/>
97 </object> 97 </object>
98 <object id="3" name="fish1_enclosure" type="zone" x="176" y="144" width="80" height="96"/> 98 <object id="3" name="fish1_enclosure" type="zone" x="176" y="144" width="80" height="96"/>
99 <object id="4" name="fish_destination" type="warp" x="184" y="122">
100 <point/>
101 </object>
99 </objectgroup> 102 </objectgroup>
100 <layer id="1" name="Upper" width="32" height="32"> 103 <layer id="1" name="Upper" width="32" height="32">
101 <properties> 104 <properties>
diff --git a/res/scripts/common.lua b/res/scripts/common.lua index 23b881a..123f2a0 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua
@@ -38,6 +38,10 @@ ChangeMapOptions = {
38 DO_NOT_FADE = 1 -- Prevents fading to and from black 38 DO_NOT_FADE = 1 -- Prevents fading to and from black
39} 39}
40 40
41PathfindingOptions = {
42 CARDINAL_DIRECTIONS_ONLY = 1
43}
44
41gamestate = {} 45gamestate = {}
42 46
43--- Yields until the specified amount of time has passed. 47--- Yields until the specified amount of time has passed.
@@ -127,6 +131,23 @@ function HideCutsceneBars(options)
127 end 131 end
128end 132end
129 133
134--- Unpauses a sprite's movement.
135-- Use this during cutscenes to allow the sprite's movement to be controlled
136-- either by the InputSystem or the BehaviourSystem.
137function UnpauseSprite(spriteName)
138 local spriteId = getSpriteByAlias(spriteName)
139 local sprite = getSprite(spriteId)
140 sprite.paused = false
141end
142
143--- Re-pauses a sprite's movement.
144-- Use this after UnpauseSprite() when you are done moving the sprite.
145function PauseSprite(spriteName)
146 local spriteId = getSpriteByAlias(spriteName)
147 local sprite = getSprite(spriteId)
148 sprite.paused = true
149end
150
130function GetPosition(spriteName) 151function GetPosition(spriteName)
131 local spriteId = getSpriteByAlias(spriteName) 152 local spriteId = getSpriteByAlias(spriteName)
132 local sprite = getSprite(spriteId) 153 local sprite = getSprite(spriteId)
@@ -216,6 +237,12 @@ function WaitForPan()
216 end 237 end
217end 238end
218 239
240function CameraFollowSprite(spriteName)
241 local spriteId = getSpriteByAlias(spriteName)
242 camera():setFollowingSprite(spriteId)
243 camera():unlockCamera()
244end
245
219function ReturnCamera(length) 246function ReturnCamera(length)
220 local playerId = getPlayerSprite() 247 local playerId = getPlayerSprite()
221 camera():panToSprite(playerId, length) 248 camera():panToSprite(playerId, length)
@@ -359,3 +386,30 @@ function SetAnimationSlowdown(spriteName, amount)
359 local sprite = getSprite(spriteId) 386 local sprite = getSprite(spriteId)
360 sprite.animSlowdown = amount 387 sprite.animSlowdown = amount
361end 388end
389
390--- Removes the enclosure zone for the specified sprite.
391-- This allows the sprite to move outside of the confines of the zone.
392function RemoveEnclosureZone(spriteName)
393 local spriteId = getSpriteByAlias(spriteName)
394 local sprite = getSprite(spriteId)
395 sprite.enclosureZone = ""
396end
397
398--- Set a sprite on a path to the specified location.
399function DirectSpriteToLocation(spriteName, warpPoint, options)
400 options = options or 0
401
402 local spriteId = getSpriteByAlias(spriteName)
403 local dest = getMap():getWarpPoint(warpPoint)
404
405 behaviour():directSpriteToLocation(spriteId, dest, options)
406end
407
408--- Blocks until the specified sprite has completed their path.
409function WaitForSpritePath(spriteName)
410 local spriteId = getSpriteByAlias(spriteName)
411
412 while (behaviour():isFollowingPath(spriteId)) do
413 coroutine.yield()
414 end
415end
diff --git a/res/scripts/underwater_start.lua b/res/scripts/underwater_start.lua index 56b0b5e..7259d05 100644 --- a/res/scripts/underwater_start.lua +++ b/res/scripts/underwater_start.lua
@@ -9,5 +9,26 @@ function underwater_start.talk_to_fish1()
9 StartCutscene() 9 StartCutscene()
10 DisplayMessage("* You deserved what she did to you.", "Fish", SpeakerType.BOY) 10 DisplayMessage("* You deserved what she did to you.", "Fish", SpeakerType.BOY)
11 WaitForEndOfMessage() 11 WaitForEndOfMessage()
12
13 Delay(500)
14
15 PanToSprite("fish1", 1000)
16 WaitForPan()
17
18 Delay(500)
19
20 UnpauseSprite("fish1")
21 RemoveEnclosureZone("fish1")
22 DirectSpriteToLocation("fish1", "fish_destination", PathfindingOptions.CARDINAL_DIRECTIONS_ONLY)
23 CameraFollowSprite("fish1")
24 WaitForSpritePath("fish1")
25
26 Delay(1000)
27 DestroyNamedSprite("fish1")
28
29 Delay(500)
30
31 ReturnCamera(1000)
32
12 HideCutsceneBars() 33 HideCutsceneBars()
13end \ No newline at end of file 34end \ No newline at end of file
diff --git a/src/behaviour_system.cpp b/src/behaviour_system.cpp index 2d46205..3637b3e 100644 --- a/src/behaviour_system.cpp +++ b/src/behaviour_system.cpp
@@ -1,8 +1,16 @@
1#include "behaviour_system.h" 1#include "behaviour_system.h"
2#include <queue>
3#include <vector>
4#include <utility>
2#include <random> 5#include <random>
3#include "game.h" 6#include "game.h"
4#include "character_system.h" 7#include "character_system.h"
5#include "direction.h" 8#include "direction.h"
9#include "transform_system.h"
10
11bool pathfindingOptionsContains(PathfindingOptions options, PathfindingOptions value) {
12 return (static_cast<int>(options) & static_cast<int>(value)) != 0;
13}
6 14
7void BehaviourSystem::tick(double dt) { 15void BehaviourSystem::tick(double dt) {
8 if (game_.isGameplayPaused()) return; 16 if (game_.isGameplayPaused()) return;
@@ -11,7 +19,7 @@ void BehaviourSystem::tick(double dt) {
11 while (timer_.step()) { 19 while (timer_.step()) {
12 for (int spriteId : game_.getSprites()) { 20 for (int spriteId : game_.getSprites()) {
13 Sprite& sprite = game_.getSprite(spriteId); 21 Sprite& sprite = game_.getSprite(spriteId);
14 if (sprite.wander && !sprite.paused) { 22 if (!sprite.paused && sprite.behaviourType == BehaviourType::Wander) {
15 // 75% chance of changing what's happening 23 // 75% chance of changing what's happening
16 if (std::bernoulli_distribution(0.75)(game_.getRng())) { 24 if (std::bernoulli_distribution(0.75)(game_.getRng())) {
17 // 50% chance of choosing a direction or stopping 25 // 50% chance of choosing a direction or stopping
@@ -31,4 +39,165 @@ void BehaviourSystem::tick(double dt) {
31 } 39 }
32 } 40 }
33 } 41 }
42
43 for (int spriteId : game_.getSprites()) {
44 Sprite& sprite = game_.getSprite(spriteId);
45 if (!sprite.paused && sprite.behaviourType == BehaviourType::Path) {
46 while (!sprite.path.empty() && sprite.path.front().endpoint == sprite.loc) {
47 sprite.path.pop_front();
48 }
49 if (sprite.path.empty()) {
50 game_.getSystem<CharacterSystem>().stopDirecting(spriteId);
51 } else {
52 if (sprite.characterState == CharacterState::Still || sprite.movementDir != sprite.path.front().dir) {
53 game_.getSystem<CharacterSystem>().moveInDirection(spriteId, sprite.path.front().dir);
54 }
55 }
56 }
57 }
58}
59
60void BehaviourSystem::directSpriteToLocation(int spriteId, vec2i pos, PathfindingOptions options) {
61 Sprite& sprite = game_.getSprite(spriteId);
62 sprite.behaviourType = BehaviourType::Path;
63 sprite.pathfindingDestination = pos;
64 sprite.cardinalDirectionsOnly = pathfindingOptionsContains(options, PathfindingOptions::CardinalDirectionsOnly);
65
66 createPath(spriteId);
67}
68
69bool BehaviourSystem::isFollowingPath(int spriteId) {
70 Sprite& sprite = game_.getSprite(spriteId);
71 return sprite.behaviourType == BehaviourType::Path && !sprite.path.empty();
72}
73
74struct PathNodeInfo {
75 int cheapestPathCost = INT_MAX;
76 int estimatedRemainingCost = INT_MAX;
77 vec2i previousPoint;
78 Direction dirFromPreviousPoint;
79};
80
81struct SearchNode {
82 vec2i point;
83 int estimatedCost = INT_MAX;
84 int tiebreaker; // this actually counts downward. wow
85
86 SearchNode(vec2i point, int estimatedCost) : point(point), estimatedCost(estimatedCost) {
87 static int tiebreakerCounter = 0;
88 tiebreaker = tiebreakerCounter--;
89 }
90
91 bool operator>(const SearchNode& rhs) const {
92 return std::tie(estimatedCost, tiebreaker) > std::tie(rhs.estimatedCost, rhs.tiebreaker);
93 }
94};
95
96int estimateRemainingCost(vec2i current, vec2i dest, int movementSpeed, bool cardinalDirectionsOnly) {
97 vec2i difference = dest - current;
98 if (cardinalDirectionsOnly) {
99 return (std::abs(difference.x()) + std::abs(difference.y())) / movementSpeed;
100 } else {
101 return std::max(std::abs(difference.x()), std::abs(difference.y())) / movementSpeed;
102 }
103}
104
105void BehaviourSystem::createPath(int spriteId) {
106 Sprite& sprite = game_.getSprite(spriteId);
107 sprite.path.clear();
108
109 const Map& map = game_.getMap();
110 vec2i mapBounds = map.getMapSize() * map.getTileSize();
111
112 // If it is not possible to reach the destination because of the parity (if
113 // the movement speed is above 1), then adjust the destination.
114 if (sprite.movementSpeed > 1) {
115 if ((sprite.loc.x() % sprite.movementSpeed) != (sprite.pathfindingDestination.x() % sprite.movementSpeed)) {
116 sprite.loc.x() = (sprite.loc.x() / sprite.movementSpeed) * sprite.movementSpeed + (sprite.pathfindingDestination.x() % sprite.movementSpeed);
117 }
118 if ((sprite.loc.y() % sprite.movementSpeed) != (sprite.pathfindingDestination.y() % sprite.movementSpeed)) {
119 sprite.loc.y() = (sprite.loc.y() / sprite.movementSpeed) * sprite.movementSpeed + (sprite.pathfindingDestination.y() % sprite.movementSpeed);
120 }
121 }
122
123 int initialCostGuess = estimateRemainingCost(sprite.loc, sprite.pathfindingDestination, sprite.movementSpeed, sprite.cardinalDirectionsOnly);
124
125 std::map<vec2i, PathNodeInfo> pathNodes;
126 pathNodes[sprite.loc] = PathNodeInfo{.cheapestPathCost = 0, .estimatedRemainingCost = initialCostGuess};
127
128 std::priority_queue<SearchNode, std::vector<SearchNode>, std::greater<SearchNode>> openSet;
129 openSet.emplace(sprite.loc, initialCostGuess);
130
131 while (!openSet.empty()) {
132 SearchNode searchNode = openSet.top();
133 openSet.pop();
134
135 if (searchNode.point == sprite.pathfindingDestination) {
136 // We're there!
137 break;
138 }
139
140 PathNodeInfo& nodeInfo = pathNodes[searchNode.point];
141 int newCost = nodeInfo.cheapestPathCost + 1;
142
143 static const std::vector<Direction> allDirections = {
144 Direction::down,
145 Direction::down_left,
146 Direction::left,
147 Direction::up_left,
148 Direction::up,
149 Direction::up_right,
150 Direction::right,
151 Direction::down_right };
152
153 static const std::vector<Direction> cardinalDirections = {
154 Direction::down,
155 Direction::left,
156 Direction::up,
157 Direction::right };
158
159 const std::vector<Direction>* directionList = sprite.cardinalDirectionsOnly ? &cardinalDirections : &allDirections;
160 for (Direction dir : *directionList) {
161 vec2i newPos = searchNode.point + unitVecInDirection(dir) * sprite.movementSpeed;
162
163 if (newPos.x() < 0 || newPos.y() < 0 || newPos.x() >= mapBounds.w() || newPos.y() >= mapBounds.h()) {
164 // The path can't go outside the map.
165 continue;
166 }
167
168 PathNodeInfo& neighborInfo = pathNodes[newPos];
169
170 if (neighborInfo.cheapestPathCost <= newCost) {
171 // There is already a faster path through this neighbor.
172 continue;
173 }
174
175 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, searchNode.point, newPos, dir);
176 if (collision.horiz.blocked || collision.vert.blocked) {
177 // There isn't actually an edge to this neighbor.
178 continue;
179 }
180
181 neighborInfo.cheapestPathCost = newCost;
182 neighborInfo.estimatedRemainingCost = estimateRemainingCost(newPos, sprite.pathfindingDestination, sprite.movementSpeed, sprite.cardinalDirectionsOnly);
183 neighborInfo.previousPoint = searchNode.point;
184 neighborInfo.dirFromPreviousPoint = dir;
185
186 openSet.emplace(newPos, neighborInfo.cheapestPathCost + neighborInfo.estimatedRemainingCost);
187 }
188 }
189
190 if (!pathNodes.count(sprite.pathfindingDestination)) {
191 // There was no path to the destination.
192 return;
193 }
194
195 vec2i curPos = sprite.pathfindingDestination;
196 while (curPos != sprite.loc) {
197 PathNodeInfo& nodeInfo = pathNodes[curPos];
198 if (sprite.path.empty() || sprite.path.front().dir != nodeInfo.dirFromPreviousPoint) {
199 sprite.path.push_front(PathfindingInstruction{.dir = nodeInfo.dirFromPreviousPoint, .endpoint = curPos});
200 }
201 curPos = nodeInfo.previousPoint;
202 }
34} 203}
diff --git a/src/behaviour_system.h b/src/behaviour_system.h index 0eb4772..526a09b 100644 --- a/src/behaviour_system.h +++ b/src/behaviour_system.h
@@ -3,6 +3,12 @@
3 3
4#include "system.h" 4#include "system.h"
5#include "timer.h" 5#include "timer.h"
6#include "vector.h"
7
8enum class PathfindingOptions {
9 None = 0,
10 CardinalDirectionsOnly = 1 << 0
11};
6 12
7class Game; 13class Game;
8 14
@@ -15,8 +21,14 @@ public:
15 21
16 void tick(double dt) override; 22 void tick(double dt) override;
17 23
24 void directSpriteToLocation(int spriteId, vec2i pos, PathfindingOptions options = PathfindingOptions::None);
25
26 bool isFollowingPath(int spriteId);
27
18private: 28private:
19 29
30 void createPath(int spriteId);
31
20 Game& game_; 32 Game& game_;
21 Timer timer_ { 500 }; 33 Timer timer_ { 500 };
22}; 34};
diff --git a/src/character_system.cpp b/src/character_system.cpp index 9b91716..53debb2 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp
@@ -150,7 +150,7 @@ void CharacterSystem::tick(double dt) {
150 pLoc += (unitVecInDirection(sprite.movementDir) * speed); 150 pLoc += (unitVecInDirection(sprite.movementDir) * speed);
151 151
152 // Check collision. 152 // Check collision.
153 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, pLoc, sprite.movementDir); 153 CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, sprite.loc, pLoc, sprite.movementDir);
154 bool blocked = collision.horiz.blocked || collision.vert.blocked; 154 bool blocked = collision.horiz.blocked || collision.vert.blocked;
155 155
156 if (collision.horiz.blocked && !sprite.clipping) { 156 if (collision.horiz.blocked && !sprite.clipping) {
diff --git a/src/game.cpp b/src/game.cpp index 6564da6..8ba4c85 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -69,7 +69,7 @@ void Game::loadMap(std::string filename) {
69 if (p.movementSpeed != -1) { 69 if (p.movementSpeed != -1) {
70 getSystem<CharacterSystem>().initSprite(spriteId, p.movementSpeed); 70 getSystem<CharacterSystem>().initSprite(spriteId, p.movementSpeed);
71 if (p.wander) { 71 if (p.wander) {
72 getSprite(spriteId).wander = true; 72 getSprite(spriteId).behaviourType = BehaviourType::Wander;
73 } 73 }
74 } 74 }
75 if (!p.enclosureZone.empty()) { 75 if (!p.enclosureZone.empty()) {
diff --git a/src/input_system.cpp b/src/input_system.cpp index 49b27ec..38423a2 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp
@@ -85,7 +85,7 @@ void InputSystem::tick(double dt) {
85 if (sprite.controllable) { 85 if (sprite.controllable) {
86 // Interacting with objects always uses Lucas's movement speed. 86 // Interacting with objects always uses Lucas's movement speed.
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, 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.horiz.blocked || collision.vert.blocked) {
91 inFrontOfSomething = true; 91 inFrontOfSomething = true;
diff --git a/src/script_system.cpp b/src/script_system.cpp index 7f9f908..931759d 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp
@@ -7,6 +7,7 @@
7#include "transform_system.h" 7#include "transform_system.h"
8#include "effect_system.h" 8#include "effect_system.h"
9#include "camera_system.h" 9#include "camera_system.h"
10#include "behaviour_system.h"
10#include "vector.h" 11#include "vector.h"
11 12
12ScriptSystem::ScriptSystem(Game& game) : game_(game) { 13ScriptSystem::ScriptSystem(Game& game) : game_(game) {
@@ -42,7 +43,8 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) {
42 "clipping", &Sprite::clipping, 43 "clipping", &Sprite::clipping,
43 "cantCrouch", &Sprite::cantCrouch, 44 "cantCrouch", &Sprite::cantCrouch,
44 "bobsWhenNormal", &Sprite::bobsWhenNormal, 45 "bobsWhenNormal", &Sprite::bobsWhenNormal,
45 "animSlowdown", &Sprite::animSlowdown); 46 "animSlowdown", &Sprite::animSlowdown,
47 "enclosureZone", &Sprite::enclosureZone);
46 48
47 engine_.new_usertype<MessageSystem>( 49 engine_.new_usertype<MessageSystem>(
48 "message", 50 "message",
@@ -93,6 +95,11 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) {
93 "unlockCamera", &CameraSystem::unlockCamera, 95 "unlockCamera", &CameraSystem::unlockCamera,
94 "setFollowingSprite", &CameraSystem::setFollowingSprite); 96 "setFollowingSprite", &CameraSystem::setFollowingSprite);
95 97
98 engine_.new_usertype<BehaviourSystem>(
99 "behaviour",
100 "directSpriteToLocation", &BehaviourSystem::directSpriteToLocation,
101 "isFollowingPath", &BehaviourSystem::isFollowingPath);
102
96 engine_.new_usertype<Mixer>( 103 engine_.new_usertype<Mixer>(
97 "mixer", 104 "mixer",
98 "playSound", &Mixer::playSound, 105 "playSound", &Mixer::playSound,
@@ -146,6 +153,12 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) {
146 }); 153 });
147 154
148 engine_.set_function( 155 engine_.set_function(
156 "behaviour",
157 [&] () -> BehaviourSystem& {
158 return game_.getSystem<BehaviourSystem>();
159 });
160
161 engine_.set_function(
149 "mixer", 162 "mixer",
150 [&] () -> Mixer& { 163 [&] () -> Mixer& {
151 return game_.getMixer(); 164 return game_.getMixer();
diff --git a/src/sprite.h b/src/sprite.h index 733c792..13d0383 100644 --- a/src/sprite.h +++ b/src/sprite.h
@@ -40,12 +40,23 @@ enum class CharacterMedium {
40 Water 40 Water
41}; 41};
42 42
43enum class BehaviourType {
44 None,
45 Wander,
46 Path
47};
48
43struct Movement { 49struct Movement {
44 vec2i pos; 50 vec2i pos;
45 Direction dir; 51 Direction dir;
46 CharacterMedium medium; 52 CharacterMedium medium;
47}; 53};
48 54
55struct PathfindingInstruction {
56 Direction dir;
57 vec2i endpoint;
58};
59
49class Sprite { 60class Sprite {
50public: 61public:
51 62
@@ -106,7 +117,10 @@ public:
106 bool player = false; 117 bool player = false;
107 118
108 // Behaviour 119 // Behaviour
109 bool wander = false; 120 BehaviourType behaviourType = BehaviourType::None;
121 vec2i pathfindingDestination;
122 bool cardinalDirectionsOnly = false;
123 std::deque<PathfindingInstruction> path;
110}; 124};
111 125
112#endif /* end of include guard: SPRITE_H_70503825 */ 126#endif /* end of include guard: SPRITE_H_70503825 */
diff --git a/src/transform_system.cpp b/src/transform_system.cpp index 4056f46..71b3a4f 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp
@@ -47,7 +47,7 @@ void TransformSystem::moveSprite(int spriteId, vec2i newLoc) {
47 } 47 }
48} 48}
49 49
50CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Direction dir) { 50CollisionResult TransformSystem::checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir) {
51 CollisionResult result; 51 CollisionResult result;
52 52
53 Sprite& sprite = game_.getSprite(spriteId); 53 Sprite& sprite = game_.getSprite(spriteId);
@@ -57,7 +57,7 @@ CollisionResult TransformSystem::checkCollision(int spriteId, vec2i newLoc, Dire
57 57
58 vec2i mapBounds = map.getMapSize() * map.getTileSize(); 58 vec2i mapBounds = map.getMapSize() * map.getTileSize();
59 59
60 vec2i oldColUL = sprite.loc + sprite.collisionOffset; 60 vec2i oldColUL = curLoc + sprite.collisionOffset;
61 vec2i oldColDR = oldColUL + sprite.collisionSize; 61 vec2i oldColDR = oldColUL + sprite.collisionSize;
62 vec2i newColUL = newLoc + sprite.collisionOffset; 62 vec2i newColUL = newLoc + sprite.collisionOffset;
63 vec2i newColDR = newColUL + sprite.collisionSize; 63 vec2i newColDR = newColUL + sprite.collisionSize;
diff --git a/src/transform_system.h b/src/transform_system.h index a07447c..6707347 100644 --- a/src/transform_system.h +++ b/src/transform_system.h
@@ -45,7 +45,7 @@ public:
45 }); 45 });
46 } 46 }
47 47
48 CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); 48 CollisionResult checkCollision(int spriteId, vec2i curLoc, vec2i newLoc, Direction dir);
49 49
50 CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc); 50 CharacterMedium getMediumAtPosition(int spriteId, vec2i newLoc);
51 51
diff --git a/src/vector.h b/src/vector.h index 9f6d54f..c7b58dc 100644 --- a/src/vector.h +++ b/src/vector.h
@@ -109,6 +109,10 @@ public:
109 return (x() != other.x()) || (y() != other.y()); 109 return (x() != other.x()) || (y() != other.y());
110 } 110 }
111 111
112 bool operator<(const vec2& other) const {
113 return std::tie(x(), y()) < std::tie(other.x(), other.y());
114 }
115
112}; 116};
113 117
114using vec2i = vec2<int>; 118using vec2i = vec2<int>;