diff options
Diffstat (limited to 'src/mapview.cpp')
-rw-r--r-- | src/mapview.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/mapview.cpp b/src/mapview.cpp new file mode 100644 index 0000000..f524d46 --- /dev/null +++ b/src/mapview.cpp | |||
@@ -0,0 +1,319 @@ | |||
1 | #include "mapview.h" | ||
2 | |||
3 | // Initialize jump physics | ||
4 | double jump_height = TILE_HEIGHT*3; | ||
5 | double jump_length = 0.25 * FRAMES_PER_SECOND; | ||
6 | double jump_velocity = -2 * jump_height / jump_length; | ||
7 | double jump_gravity = -1 * jump_velocity / jump_length; | ||
8 | |||
9 | MapView::MapView(Map* first, int x, int y) | ||
10 | { | ||
11 | // Initialize player data | ||
12 | player = new mob_t(); | ||
13 | player->x = x; | ||
14 | player->y = y; | ||
15 | player->x_vel = 0; | ||
16 | player->y_vel = 0; | ||
17 | player->x_accel = 0; | ||
18 | player->y_accel = jump_gravity; | ||
19 | player->w = 10; | ||
20 | player->h = 14; | ||
21 | |||
22 | loadMap(first); | ||
23 | } | ||
24 | |||
25 | MapView::~MapView() | ||
26 | { | ||
27 | destroyTexture(bg); | ||
28 | |||
29 | delete player; | ||
30 | } | ||
31 | |||
32 | void MapView::loadMap(Map* m) | ||
33 | { | ||
34 | curMap = m; | ||
35 | |||
36 | left_collisions.clear(); | ||
37 | right_collisions.clear(); | ||
38 | up_collisions.clear(); | ||
39 | down_collisions.clear(); | ||
40 | |||
41 | add_collision(-6, 0, GAME_WIDTH, left, (m->getLeftMap() == NULL) ? 1 : 2); | ||
42 | add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, (m->getRightMap() == NULL) ? 1 : 2); | ||
43 | |||
44 | if (bg == NULL) | ||
45 | { | ||
46 | bg = createTexture(GAME_WIDTH, GAME_HEIGHT); | ||
47 | } | ||
48 | |||
49 | fillTexture(bg, NULL, 0, 0, 0); | ||
50 | |||
51 | const char* mapbuf = m->mapdata(); | ||
52 | |||
53 | for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) | ||
54 | { | ||
55 | int x = i % MAP_WIDTH; | ||
56 | int y = i / MAP_WIDTH; | ||
57 | Rectangle dst(x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); | ||
58 | //Rectangle src; | ||
59 | |||
60 | switch (mapbuf[i]) | ||
61 | { | ||
62 | case ' ': break; | ||
63 | case 'X': fillTexture(bg, &dst, 255, 85, 85); break; | ||
64 | case 'P': fillTexture(bg, &dst, 85, 255, 255); break; | ||
65 | } | ||
66 | |||
67 | //blitTexture(tiles, bg, &src, &dst); | ||
68 | |||
69 | if (mapbuf[i] == 'X') | ||
70 | { | ||
71 | if ((x != 0) && (mapbuf[i-1] != 'X')) | ||
72 | { | ||
73 | add_collision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, right, 0); | ||
74 | } | ||
75 | |||
76 | if ((x != 39) && (mapbuf[i+1] != 'X')) | ||
77 | { | ||
78 | add_collision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, left, 0); | ||
79 | } | ||
80 | |||
81 | if ((y != 0) && (mapbuf[i-MAP_WIDTH] != 'X')) | ||
82 | { | ||
83 | add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0); | ||
84 | } | ||
85 | |||
86 | if ((y != 23) && (mapbuf[i+MAP_WIDTH] != 'X')) | ||
87 | { | ||
88 | add_collision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, up, 0); | ||
89 | } | ||
90 | } else if (mapbuf[i] == 'P') | ||
91 | { | ||
92 | add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | Texture* font = loadTextureFromBMP("../res/font.bmp"); | ||
97 | const char* map_name = m->title(); | ||
98 | int start_x = (40/2) - (strlen(map_name)/2); | ||
99 | for (size_t i=0; i<strlen(map_name); i++) | ||
100 | { | ||
101 | Rectangle srcRect(map_name[i] % 16 * 8, map_name[i] / 16 * 8, 8, 8); | ||
102 | Rectangle dstRect((start_x + i)*8, 24*8, 8, 8); | ||
103 | blitTexture(font, bg, &srcRect, &dstRect); | ||
104 | } | ||
105 | |||
106 | destroyTexture(font); | ||
107 | } | ||
108 | |||
109 | void MapView::input(int key, int action) | ||
110 | { | ||
111 | if (action == GLFW_PRESS) | ||
112 | { | ||
113 | switch (key) | ||
114 | { | ||
115 | case GLFW_KEY_LEFT: holding_left = true; break; | ||
116 | case GLFW_KEY_RIGHT: holding_right = true; break; | ||
117 | case GLFW_KEY_UP: player->y_vel = jump_velocity; break; | ||
118 | } | ||
119 | } else if (action == GLFW_RELEASE) | ||
120 | { | ||
121 | switch (key) | ||
122 | { | ||
123 | case GLFW_KEY_LEFT: holding_left = false; break; | ||
124 | case GLFW_KEY_RIGHT: holding_right = false; break; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void MapView::tick() | ||
130 | { | ||
131 | if (holding_left && player->x_vel >= 0) | ||
132 | { | ||
133 | player->x_vel = -2; | ||
134 | } else if (holding_right && player->x_vel <= 0) | ||
135 | { | ||
136 | player->x_vel = 2; | ||
137 | } else if (!holding_left && !holding_right) { | ||
138 | player->x_vel = 0; | ||
139 | } | ||
140 | |||
141 | player->x_vel += player->x_accel; | ||
142 | if (player->x_vel < -16) player->x_vel = -16; | ||
143 | if (player->x_vel > 16) player->x_vel = 16; | ||
144 | int playerx_next = player->x + player->x_vel; | ||
145 | |||
146 | player->y_vel += player->y_accel; | ||
147 | if (player->y_vel > 16) player->y_vel = 16; // Terminal velocity | ||
148 | if (player->y_vel < -16) player->y_vel = -16; | ||
149 | int playery_next = player->y + player->y_vel; | ||
150 | |||
151 | check_collisions(player, playerx_next, playery_next); | ||
152 | } | ||
153 | |||
154 | void MapView::render(Texture* tex) | ||
155 | { | ||
156 | // Draw the background | ||
157 | blitTexture(bg, tex, NULL, NULL); | ||
158 | |||
159 | // Draw the player | ||
160 | Rectangle dst_rect(player->x, player->y, player->w, player->h); | ||
161 | fillTexture(tex, &dst_rect, 255, 255, 255); | ||
162 | } | ||
163 | |||
164 | void MapView::add_collision(int axis, int lower, int upper, direction_t dir, int type) | ||
165 | { | ||
166 | //printf("added collision\n"); | ||
167 | list<collision_t>::iterator it; | ||
168 | |||
169 | switch (dir) | ||
170 | { | ||
171 | case up: | ||
172 | it = up_collisions.begin(); | ||
173 | for (; it!=up_collisions.end(); it++) | ||
174 | { | ||
175 | if (it->axis < axis) break; | ||
176 | } | ||
177 | |||
178 | up_collisions.insert(it, {axis, lower, upper, type}); | ||
179 | |||
180 | break; | ||
181 | case down: | ||
182 | it = down_collisions.begin(); | ||
183 | for (; it!=down_collisions.end(); it++) | ||
184 | { | ||
185 | if (it->axis > axis) break; | ||
186 | } | ||
187 | |||
188 | down_collisions.insert(it, {axis, lower, upper, type}); | ||
189 | |||
190 | break; | ||
191 | case left: | ||
192 | it = left_collisions.begin(); | ||
193 | for (; it!=left_collisions.end(); it++) | ||
194 | { | ||
195 | if (it->axis < axis) break; | ||
196 | } | ||
197 | |||
198 | left_collisions.insert(it, {axis, lower, upper, type}); | ||
199 | |||
200 | break; | ||
201 | case right: | ||
202 | it = right_collisions.begin(); | ||
203 | for (; it!=right_collisions.end(); it++) | ||
204 | { | ||
205 | if (it->axis > axis) break; | ||
206 | } | ||
207 | |||
208 | right_collisions.insert(it, {axis, lower, upper, type}); | ||
209 | |||
210 | break; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | void MapView::check_collisions(mob_t* mob, int x_next, int y_next) | ||
215 | { | ||
216 | if (x_next < mob->x) | ||
217 | { | ||
218 | for (list<collision_t>::iterator it=left_collisions.begin(); it!=left_collisions.end(); it++) | ||
219 | { | ||
220 | if (it->axis > mob->x) continue; | ||
221 | if (it->axis < x_next) break; | ||
222 | |||
223 | if ((mob->y+mob->h > it->lower) && (mob->y < it->upper)) | ||
224 | { | ||
225 | // We have a collision! | ||
226 | if (it->type == 0) | ||
227 | { | ||
228 | x_next = it->axis; | ||
229 | mob->x_vel = 0; | ||
230 | } else if (it->type == 1) | ||
231 | { | ||
232 | x_next = GAME_WIDTH-mob->w/2; | ||
233 | } else if (it->type == 2) | ||
234 | { | ||
235 | x_next = GAME_WIDTH-mob->w/2; | ||
236 | loadMap(curMap->getLeftMap()); | ||
237 | } | ||
238 | |||
239 | break; | ||
240 | } | ||
241 | } | ||
242 | } else if (x_next > mob->x) | ||
243 | { | ||
244 | for (list<collision_t>::iterator it=right_collisions.begin(); it!=right_collisions.end(); it++) | ||
245 | { | ||
246 | if (it->axis < mob->x+mob->w) continue; | ||
247 | if (it->axis > x_next+mob->w) break; | ||
248 | |||
249 | if ((mob->y+mob->h > it->lower) && (mob->y < it->upper)) | ||
250 | { | ||
251 | // We have a collision! | ||
252 | if (it->type == 0) | ||
253 | { | ||
254 | x_next = it->axis - mob->w; | ||
255 | mob->x_vel = 0; | ||
256 | } else if (it->type == 1) | ||
257 | { | ||
258 | x_next = -mob->w/2; | ||
259 | } else if (it->type == 2) | ||
260 | { | ||
261 | x_next = -mob->w/2; | ||
262 | loadMap(curMap->getRightMap()); | ||
263 | } | ||
264 | |||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | mob->x = x_next; | ||
271 | |||
272 | if (y_next < mob->y) | ||
273 | { | ||
274 | for (list<collision_t>::iterator it=up_collisions.begin(); it!=up_collisions.end(); it++) | ||
275 | { | ||
276 | if (it->axis > mob->y) continue; | ||
277 | if (it->axis < y_next) break; | ||
278 | |||
279 | if ((mob->x+mob->w > it->lower) && (mob->x < it->upper)) | ||
280 | { | ||
281 | // We have a collision! | ||
282 | if (it->type == 0) | ||
283 | { | ||
284 | y_next = it->axis; | ||
285 | mob->y_vel = 0; | ||
286 | } else if (it->type == 1) | ||
287 | { | ||
288 | y_next = GAME_HEIGHT-mob->h/2-1; | ||
289 | } | ||
290 | |||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | } else if (y_next > mob->y) | ||
295 | { | ||
296 | for (list<collision_t>::iterator it=down_collisions.begin(); it!=down_collisions.end(); it++) | ||
297 | { | ||
298 | if (it->axis < mob->y+mob->h) continue; | ||
299 | if (it->axis > y_next+mob->h) break; | ||
300 | |||
301 | if ((mob->x+mob->w > it->lower) && (mob->x < it->upper)) | ||
302 | { | ||
303 | // We have a collision! | ||
304 | if (it->type == 0) | ||
305 | { | ||
306 | y_next = it->axis - mob->h; | ||
307 | mob->y_vel = 0; | ||
308 | } else if (it->type == 1) | ||
309 | { | ||
310 | y_next = 1 - mob->h/2; | ||
311 | } | ||
312 | |||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | mob->y = y_next; | ||
319 | } | ||