summary refs log tree commit diff stats
path: root/src/components/map_collision.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/map_collision.cpp')
-rw-r--r--src/components/map_collision.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/components/map_collision.cpp b/src/components/map_collision.cpp new file mode 100644 index 0000000..f385320 --- /dev/null +++ b/src/components/map_collision.cpp
@@ -0,0 +1,211 @@
1#include "map_collision.h"
2#include "map.h"
3#include "game.h"
4
5MapCollisionComponent::MapCollisionComponent(const Map& map) : map(map)
6{
7 addCollision(-6, 0, GAME_WIDTH, Direction::left, (map.getLeftMap() == nullptr) ? Collision::Type::wrap : Collision::Type::teleport);
8 addCollision(GAME_WIDTH+6, 0, GAME_WIDTH, Direction::right, (map.getRightMap() == nullptr) ? Collision::Type::reverse : Collision::Type::teleport);
9
10 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++)
11 {
12 int x = i % MAP_WIDTH;
13 int y = i / MAP_WIDTH;
14 int tile = map.getMapdata()[i];
15
16 if ((tile > 0) && (tile < 28) && (!((tile >= 5) && (tile <= 7))))
17 {
18 addCollision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::right, Collision::Type::wall);
19 addCollision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, Direction::left, Collision::Type::wall);
20 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::wall);
21 addCollision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::up, Collision::Type::wall);
22 } else if ((tile >= 5) && (tile <= 7))
23 {
24 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::platform);
25 } else if (tile == 42)
26 {
27 addCollision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, Direction::down, Collision::Type::danger);
28 }
29 }
30}
31
32void MapCollisionComponent::addCollision(double axis, double lower, double
33 upper, Direction dir, Collision::Type type)
34{
35 std::list<Collision>::iterator it;
36
37 switch (dir)
38 {
39 case Direction::up:
40 it = up_collisions.begin();
41 for (; it!=up_collisions.end(); it++)
42 {
43 if (it->axis < axis) break;
44 }
45
46 up_collisions.insert(it, {axis, lower, upper, type});
47
48 break;
49 case Direction::down:
50 it = down_collisions.begin();
51 for (; it!=down_collisions.end(); it++)
52 {
53 if (it->axis > axis) break;
54 }
55
56 down_collisions.insert(it, {axis, lower, upper, type});
57
58 break;
59 case Direction::left:
60 it = left_collisions.begin();
61 for (; it!=left_collisions.end(); it++)
62 {
63 if (it->axis < axis) break;
64 }
65
66 left_collisions.insert(it, {axis, lower, upper, type});
67
68 break;
69 case Direction::right:
70 it = right_collisions.begin();
71 for (; it!=right_collisions.end(); it++)
72 {
73 if (it->axis > axis) break;
74 }
75
76 right_collisions.insert(it, {axis, lower, upper, type});
77
78 break;
79 }
80}
81
82void MapCollisionComponent::detectCollision(Game& game, Entity&, Entity& collider, std::pair<double, double> old_position)
83{
84 if (collider.position.first < old_position.first)
85 {
86 for (auto collision : left_collisions)
87 {
88 if (collision.axis > old_position.first) continue;
89 if (collision.axis < collider.position.first) break;
90
91 if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper))
92 {
93 // We have a collision!
94 processCollision(game, collider, collision, Direction::left, old_position);
95
96 break;
97 }
98 }
99 } else if (collider.position.first > old_position.first)
100 {
101 for (auto collision : right_collisions)
102 {
103 if (collision.axis < old_position.first+collider.size.first) continue;
104 if (collision.axis > collider.position.first+collider.size.first) break;
105
106 if ((old_position.second+collider.size.second > collision.lower) && (old_position.second < collision.upper))
107 {
108 // We have a collision!
109 processCollision(game, collider, collision, Direction::right, old_position);
110
111 break;
112 }
113 }
114 }
115
116 if (collider.position.second < old_position.second)
117 {
118 for (auto collision : up_collisions)
119 {
120 if (collision.axis > old_position.second) continue;
121 if (collision.axis < collider.position.second) break;
122
123 if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper))
124 {
125 // We have a collision!
126 processCollision(game, collider, collision, Direction::up, old_position);
127
128 break;
129 }
130 }
131 } else if (collider.position.second > old_position.second)
132 {
133 for (auto collision : down_collisions)
134 {
135 if (collision.axis < old_position.second+collider.size.second) continue;
136 if (collision.axis > collider.position.second+collider.size.second) break;
137
138 if ((collider.position.first+collider.size.first > collision.lower) && (collider.position.first < collision.upper))
139 {
140 // We have a collision!
141 processCollision(game, collider, collision, Direction::down, old_position);
142
143 break;
144 }
145 }
146 }
147}
148
149void MapCollisionComponent::processCollision(Game& game, Entity& collider, Collision collision, Direction dir, std::pair<double, double> old_position)
150{
151 if (collision.type == Collision::Type::wall)
152 {
153 if (dir == Direction::left)
154 {
155 collider.position.first = collision.axis;
156 collider.send(game, Message::Type::stopMovingHorizontally);
157 } else if (dir == Direction::right)
158 {
159 collider.position.first = collision.axis - collider.size.first;
160 collider.send(game, Message::Type::stopMovingHorizontally);
161 } else if (dir == Direction::up)
162 {
163 collider.position.second = collision.axis;
164 collider.send(game, Message::Type::stopMovingVertically);
165 } else if (dir == Direction::down)
166 {
167 collider.position.second = collision.axis - collider.size.second;
168 collider.send(game, Message::Type::hitTheGround);
169 }
170 } else if (collision.type == Collision::Type::wrap)
171 {
172 if (dir == Direction::left)
173 {
174 collider.position.first = GAME_WIDTH-collider.size.first/2;
175 } else if (dir == Direction::right)
176 {
177 collider.position.first = -collider.size.first/2;
178 } else if (dir == Direction::up)
179 {
180 collider.position.second = GAME_HEIGHT-collider.size.second/2-1;
181 } else if (dir == Direction::down)
182 {
183 collider.position.second = -collider.size.second/2;
184 }
185 } else if (collision.type == Collision::Type::teleport)
186 {
187 if (dir == Direction::left)
188 {
189 game.loadMap(*map.getLeftMap(), std::make_pair(GAME_WIDTH-collider.size.first/2, old_position.second));
190 } else if (dir == Direction::right)
191 {
192 game.loadMap(*map.getRightMap(), std::make_pair(-collider.size.first/2, old_position.second));
193 }
194 } else if (collision.type == Collision::Type::reverse)
195 {
196 if (dir == Direction::right)
197 {
198 collider.position.first = collision.axis - collider.size.first;
199 collider.send(game, Message::Type::walkLeft);
200 }
201 } else if (collision.type == Collision::Type::platform)
202 {
203 Message msg(Message::Type::drop);
204 msg.dropAxis = collision.axis;
205
206 collider.send(game, msg);
207 } else if (collision.type == Collision::Type::danger)
208 {
209 game.playerDie();
210 }
211}