diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/direction.h | 10 | ||||
-rw-r--r-- | src/map.cpp | 38 | ||||
-rw-r--r-- | src/map.h | 3 | ||||
-rw-r--r-- | src/party.cpp | 121 | ||||
-rw-r--r-- | src/party.h | 2 | ||||
-rw-r--r-- | src/vector.h | 8 |
6 files changed, 144 insertions, 38 deletions
diff --git a/src/direction.h b/src/direction.h index ebc0e46..a83a6f8 100644 --- a/src/direction.h +++ b/src/direction.h | |||
@@ -41,4 +41,14 @@ inline vec2i unitVecInDirection(Direction dir) { | |||
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | inline bool dirHasDir(Direction value, Direction inner) { | ||
45 | switch (inner) { | ||
46 | case Direction::up: return value == Direction::up_left || value == Direction::up || value == Direction::up_right; | ||
47 | case Direction::down: return value == Direction::down_left || value == Direction::down || value == Direction::down_right; | ||
48 | case Direction::left: return value == Direction::up_left || value == Direction::left || value == Direction::down_left; | ||
49 | case Direction::right: return value == Direction::up_right || value == Direction::right || value == Direction::down_right; | ||
50 | default: return value == inner; | ||
51 | } | ||
52 | } | ||
53 | |||
44 | #endif /* end of include guard: DIRECTION_H_AB66A90E */ | 54 | #endif /* end of include guard: DIRECTION_H_AB66A90E */ |
diff --git a/src/map.cpp b/src/map.cpp index a60cbba..7d9800d 100644 --- a/src/map.cpp +++ b/src/map.cpp | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "map.h" | 1 | #include "map.h" |
2 | #include <tmxlite/Map.hpp> | 2 | #include <tmxlite/Map.hpp> |
3 | #include <tmxlite/Layer.hpp> | 3 | #include <tmxlite/Layer.hpp> |
4 | #include <tmxlite/Property.hpp> | ||
4 | #include <tmxlite/TileLayer.hpp> | 5 | #include <tmxlite/TileLayer.hpp> |
5 | #include <tmxlite/Tileset.hpp> | 6 | #include <tmxlite/Tileset.hpp> |
6 | #include "renderer.h" | 7 | #include "renderer.h" |
@@ -21,11 +22,10 @@ Map::Map(std::string_view filename, Renderer& renderer) { | |||
21 | 22 | ||
22 | int firstGID = 0; | 23 | int firstGID = 0; |
23 | // There should only be one tileset. | 24 | // There should only be one tileset. |
24 | for (const tmx::Tileset& tileset : mapfile.getTilesets()) { | 25 | const tmx::Tileset& tileset = mapfile.getTilesets()[0]; |
25 | firstGID = tileset.getFirstGID(); | 26 | firstGID = tileset.getFirstGID(); |
26 | tilesetTextureId_ = renderer.loadImageFromFile(tileset.getImagePath()); | 27 | tilesetTextureId_ = renderer.loadImageFromFile(tileset.getImagePath()); |
27 | tilesetColumns_ = tileset.getColumnCount(); | 28 | tilesetColumns_ = tileset.getColumnCount(); |
28 | } | ||
29 | 29 | ||
30 | for (const auto& layer : mapfile.getLayers()) { | 30 | for (const auto& layer : mapfile.getLayers()) { |
31 | if (layer->getType() == tmx::Layer::Type::Tile) { | 31 | if (layer->getType() == tmx::Layer::Type::Tile) { |
@@ -34,13 +34,33 @@ Map::Map(std::string_view filename, Renderer& renderer) { | |||
34 | std::vector<Tile> tilesToStore; | 34 | std::vector<Tile> tilesToStore; |
35 | 35 | ||
36 | for (const auto& maptile : tileLayer.getTiles()) { | 36 | for (const auto& maptile : tileLayer.getTiles()) { |
37 | tilesToStore.push_back(Tile { | 37 | Tile tile; |
38 | .id = maptile.ID - firstGID, | 38 | tile.id = maptile.ID - firstGID; |
39 | .flipHorizontal = (maptile.flipFlags & tmx::TileLayer::Horizontal) != 0, | 39 | tile.flipHorizontal = (maptile.flipFlags & tmx::TileLayer::Horizontal) != 0; |
40 | .flipVertical = (maptile.flipFlags & tmx::TileLayer::Vertical) != 0 }); | 40 | tile.flipVertical = (maptile.flipFlags & tmx::TileLayer::Vertical) != 0; |
41 | |||
42 | for (const tmx::Property& property : tileset.getTile(maptile.ID)->properties) { | ||
43 | if (property.getName() == "solid" && property.getBoolValue()) { | ||
44 | tile.blocked = true; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | tilesToStore.push_back(std::move(tile)); | ||
41 | } | 49 | } |
42 | 50 | ||
43 | layers_.push_back(std::move(tilesToStore)); | 51 | layers_.push_back(std::move(tilesToStore)); |
44 | } | 52 | } |
45 | } | 53 | } |
46 | } | 54 | } |
55 | |||
56 | bool Map::isBlocked(int x, int y) const { | ||
57 | int i = x + y * mapSize_.w(); | ||
58 | |||
59 | for (const std::vector<Tile>& layer : layers_) { | ||
60 | if (layer.at(i).blocked) { | ||
61 | return true; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | return false; | ||
66 | } | ||
diff --git a/src/map.h b/src/map.h index 1031996..2f8ec1a 100644 --- a/src/map.h +++ b/src/map.h | |||
@@ -12,6 +12,7 @@ struct Tile { | |||
12 | unsigned int id = 0; | 12 | unsigned int id = 0; |
13 | bool flipHorizontal = false; | 13 | bool flipHorizontal = false; |
14 | bool flipVertical = false; | 14 | bool flipVertical = false; |
15 | bool blocked = false; | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | class Map { | 18 | class Map { |
@@ -29,6 +30,8 @@ public: | |||
29 | 30 | ||
30 | int getTilesetColumns() const { return tilesetColumns_; } | 31 | int getTilesetColumns() const { return tilesetColumns_; } |
31 | 32 | ||
33 | bool isBlocked(int x, int y) const; | ||
34 | |||
32 | private: | 35 | private: |
33 | 36 | ||
34 | vec2i mapSize_; | 37 | vec2i mapSize_; |
diff --git a/src/party.cpp b/src/party.cpp index 2af252f..307bca8 100644 --- a/src/party.cpp +++ b/src/party.cpp | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "party.h" | 1 | #include "party.h" |
2 | #include "consts.h" | 2 | #include "consts.h" |
3 | #include <iostream> | ||
3 | 4 | ||
4 | void Party::addMember(Game& game, int spriteId) { | 5 | void Party::addMember(Game& game, int spriteId) { |
5 | int index = members_.size(); | 6 | int index = members_.size(); |
@@ -93,41 +94,84 @@ void Party::move(Game& game, const Input& keystate) { | |||
93 | 94 | ||
94 | pLoc += (unitVecInDirection(dir) * speed); | 95 | pLoc += (unitVecInDirection(dir) * speed); |
95 | 96 | ||
96 | game.moveSprite(members_[0].spriteId, pLoc); | 97 | // Check collision. |
98 | const Map& map = game.getMap(); | ||
99 | bool blocked = false; | ||
100 | |||
101 | const vec2i UL_COL_BOX = { 8, 8 }; | ||
102 | const vec2i DR_COL_BOX = { 4, 0 }; | ||
103 | vec2i oldColPosUL = (p1.loc() - UL_COL_BOX) / map.getTileSize(); | ||
104 | vec2i newColPosUL = (pLoc - UL_COL_BOX) / map.getTileSize(); | ||
105 | vec2i oldColPosDR = (p1.loc() + DR_COL_BOX) / map.getTileSize(); | ||
106 | vec2i newColPosDR = (pLoc + DR_COL_BOX) / map.getTileSize(); | ||
107 | |||
108 | if (dirHasDir(dir, Direction::right) && | ||
109 | newColPosDR.x() > oldColPosDR.x()) { | ||
110 | for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { | ||
111 | if (map.isBlocked(newColPosDR.x(), y)) { | ||
112 | blocked = true; | ||
113 | pLoc.x() = p1.loc().x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | } | ||
97 | 118 | ||
98 | for (int i = 1; i < members_.size(); i++) { | 119 | if (dirHasDir(dir, Direction::left) && |
99 | const Sprite& pNext = game.getSprite(members_[i].spriteId); | 120 | newColPosUL.x() < oldColPosUL.x()) { |
100 | const Movement& posdir = members_[i].movement.front(); | 121 | for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { |
101 | game.moveSprite(members_[i].spriteId, posdir.pos); | 122 | if (map.isBlocked(newColPosUL.x(), y)) { |
102 | game.setSpriteDirection(members_[i].spriteId, posdir.dir); | 123 | blocked = true; |
124 | pLoc.x() = p1.loc().x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | } | ||
103 | 129 | ||
104 | members_[i].movement.pop_front(); | 130 | if (dirHasDir(dir, Direction::down) && |
105 | members_[i].movement.push_back({.pos = pLoc, .dir = dir}); | 131 | newColPosDR.y() > oldColPosDR.y()) { |
132 | for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { | ||
133 | if (map.isBlocked(x, newColPosDR.y())) { | ||
134 | blocked = true; | ||
135 | pLoc.y() = p1.loc().y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; | ||
136 | break; | ||
137 | } | ||
138 | } | ||
106 | } | 139 | } |
107 | } | ||
108 | 140 | ||
109 | void Party::beginCrouch(Game& game) { | 141 | if (dirHasDir(dir, Direction::up) && |
110 | if (state_ == State::Running) { | 142 | newColPosUL.y() < oldColPosUL.y()) { |
111 | state_ = State::Normal; | 143 | for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { |
144 | if (map.isBlocked(x, newColPosUL.y())) { | ||
145 | blocked = true; | ||
146 | pLoc.y() = p1.loc().y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
152 | if (blocked && state_ == State::Running) { | ||
153 | stopRunning(game); | ||
154 | } | ||
155 | |||
156 | // Move everything | ||
157 | if (pLoc != p1.loc()) { | ||
158 | game.moveSprite(members_[0].spriteId, pLoc); | ||
112 | 159 | ||
113 | // Double the movement buffer for the followers. | ||
114 | for (int i = 1; i < members_.size(); i++) { | 160 | for (int i = 1; i < members_.size(); i++) { |
115 | std::deque<Movement> newMove; | 161 | const Sprite& pNext = game.getSprite(members_[i].spriteId); |
116 | vec2i lastPos = game.getSprite(members_[i].spriteId).loc(); | 162 | const Movement& posdir = members_[i].movement.front(); |
117 | 163 | game.moveSprite(members_[i].spriteId, posdir.pos); | |
118 | while (!members_[i].movement.empty()) { | 164 | game.setSpriteDirection(members_[i].spriteId, posdir.dir); |
119 | Movement m1 = members_[i].movement.front(); | ||
120 | Movement m2 = m1; | ||
121 | m1.pos = (m1.pos + lastPos) / 2; | ||
122 | lastPos = m2.pos; | ||
123 | |||
124 | newMove.push_back(m1); | ||
125 | newMove.push_back(m2); | ||
126 | members_[i].movement.pop_front(); | ||
127 | } | ||
128 | 165 | ||
129 | members_[i].movement = std::move(newMove); | 166 | members_[i].movement.pop_front(); |
167 | members_[i].movement.push_back({.pos = pLoc, .dir = dir}); | ||
130 | } | 168 | } |
169 | } | ||
170 | } | ||
171 | |||
172 | void Party::beginCrouch(Game& game) { | ||
173 | if (state_ == State::Running) { | ||
174 | stopRunning(game); | ||
131 | } else { | 175 | } else { |
132 | state_ = State::Crouching; | 176 | state_ = State::Crouching; |
133 | 177 | ||
@@ -159,3 +203,26 @@ void Party::endCrouch(Game& game) { | |||
159 | } | 203 | } |
160 | } | 204 | } |
161 | } | 205 | } |
206 | |||
207 | void Party::stopRunning(Game& game) { | ||
208 | state_ = State::Normal; | ||
209 | |||
210 | // Double the movement buffer for the followers. | ||
211 | for (int i = 1; i < members_.size(); i++) { | ||
212 | std::deque<Movement> newMove; | ||
213 | vec2i lastPos = game.getSprite(members_[i].spriteId).loc(); | ||
214 | |||
215 | while (!members_[i].movement.empty()) { | ||
216 | Movement m1 = members_[i].movement.front(); | ||
217 | Movement m2 = m1; | ||
218 | m1.pos = (m1.pos + lastPos) / 2; | ||
219 | lastPos = m2.pos; | ||
220 | |||
221 | newMove.push_back(m1); | ||
222 | newMove.push_back(m2); | ||
223 | members_[i].movement.pop_front(); | ||
224 | } | ||
225 | |||
226 | members_[i].movement = std::move(newMove); | ||
227 | } | ||
228 | } | ||
diff --git a/src/party.h b/src/party.h index 06f8639..2864073 100644 --- a/src/party.h +++ b/src/party.h | |||
@@ -18,6 +18,8 @@ public: | |||
18 | 18 | ||
19 | private: | 19 | private: |
20 | 20 | ||
21 | void stopRunning(Game& game); | ||
22 | |||
21 | enum class State { | 23 | enum class State { |
22 | Normal, | 24 | Normal, |
23 | Crouching, | 25 | Crouching, |
diff --git a/src/vector.h b/src/vector.h index 8019edf..9f6d54f 100644 --- a/src/vector.h +++ b/src/vector.h | |||
@@ -97,12 +97,16 @@ public: | |||
97 | return vec2(x() * other.x(), y() * other.y()); | 97 | return vec2(x() * other.x(), y() * other.y()); |
98 | } | 98 | } |
99 | 99 | ||
100 | vec2 operator/(const vec2& other) const { | ||
101 | return vec2(x() / other.x(), y() / other.y()); | ||
102 | } | ||
103 | |||
100 | bool operator==(const vec2& other) const { | 104 | bool operator==(const vec2& other) const { |
101 | return std::tie(x(), other.x()) == std::tie(y(), other.y()); | 105 | return (x() == other.x()) && (y() == other.y()); |
102 | } | 106 | } |
103 | 107 | ||
104 | bool operator!=(const vec2& other) const { | 108 | bool operator!=(const vec2& other) const { |
105 | return std::tie(x(), other.x()) != std::tie(y(), other.y()); | 109 | return (x() != other.x()) || (y() != other.y()); |
106 | } | 110 | } |
107 | 111 | ||
108 | }; | 112 | }; |