Mercurial > molko
comparison src/libmlk-rpg/rpg/map.c @ 320:8f9937403749
misc: improve loading of data
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 01 Oct 2021 20:30:00 +0200 |
parents | libmlk-rpg/rpg/map.c@d01e83210ca2 |
children | 460c78706989 |
comparison
equal
deleted
inserted
replaced
319:b843eef4cc35 | 320:8f9937403749 |
---|---|
1 /* | |
2 * map.c -- game map | |
3 * | |
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #include <assert.h> | |
20 #include <stdio.h> | |
21 #include <stdlib.h> | |
22 #include <string.h> | |
23 | |
24 #include <core/error.h> | |
25 #include <core/event.h> | |
26 #include <core/image.h> | |
27 #include <core/maths.h> | |
28 #include <core/painter.h> | |
29 #include <core/sprite.h> | |
30 #include <core/sys.h> | |
31 #include <core/texture.h> | |
32 #include <core/window.h> | |
33 | |
34 #include <ui/debug.h> | |
35 | |
36 #include "map.h" | |
37 #include "tileset.h" | |
38 | |
39 /* | |
40 * This is the speed the player moves on the map. | |
41 * | |
42 * SPEED represents the number of pixels it must move per SEC. | |
43 * SEC simply represends the number of milliseconds in one second. | |
44 */ | |
45 #define SPEED 100 | |
46 #define SEC 1000 | |
47 | |
48 /* | |
49 * Those are margins within the edge of the screen. The camera always try to | |
50 * keep those padding between the player and the screen. | |
51 */ | |
52 #define MARGIN_WIDTH 160 | |
53 #define MARGIN_HEIGHT 90 | |
54 | |
55 #define WIDTH(map) ((map)->columns * (map)->tileset->sprite->cellw) | |
56 #define HEIGHT(map) ((map)->rows * (map)->tileset->sprite->cellh) | |
57 | |
58 /* | |
59 * This structure defines the possible movement of the player as flags since | |
60 * it's possible to make diagonal movements. | |
61 */ | |
62 enum movement { | |
63 MOVING_UP = 1 << 0, | |
64 MOVING_RIGHT = 1 << 1, | |
65 MOVING_DOWN = 1 << 2, | |
66 MOVING_LEFT = 1 << 3 | |
67 }; | |
68 | |
69 /* | |
70 * A bit of explanation within this array. The structure walksprite requires | |
71 * an orientation between 0-7 depending on the user direction. | |
72 * | |
73 * Since keys for moving the character may be pressed at the same time, we need | |
74 * a conversion table from "key pressed" to "orientation". | |
75 * | |
76 * When an orientation is impossible, it is set to -1. Example, when both left | |
77 * and right are pressed. | |
78 * | |
79 * MOVING_UP = 0001 = 0x1 | |
80 * MOVING_RIGHT = 0010 = 0x2 | |
81 * MOVING_DOWN = 0100 = 0x3 | |
82 * MOVING_LEFT = 1000 = 0x4 | |
83 */ | |
84 static unsigned int orientations[16] = { | |
85 [0x1] = 0, | |
86 [0x2] = 2, | |
87 [0x3] = 1, | |
88 [0x4] = 4, | |
89 [0x6] = 3, | |
90 [0x8] = 6, | |
91 [0x9] = 7, | |
92 [0xC] = 5 | |
93 }; | |
94 | |
95 /* | |
96 * Check if this block is usable for collision detection. For example if the | |
97 * player is moving upwards but the collision shape is below it is unnecessary | |
98 * to check. | |
99 */ | |
100 static int | |
101 is_block_relevant(const struct map *map, | |
102 const struct map_block *block, | |
103 int drow, | |
104 int dcol) | |
105 { | |
106 if (drow) { | |
107 /* Object outside of left-right bounds. */ | |
108 if (block->x + (int)block->w <= map->player_x || | |
109 block->x >= map->player_x + (int)map->player_sprite->cellw) | |
110 return 0; | |
111 | |
112 if ((drow < 0 && block->y >= map->player_y + (int)map->player_sprite->cellh) || | |
113 (drow > 0 && block->y + block->h <= map->player_y + map->player_sprite->cellh)) | |
114 return 0; | |
115 } else if (dcol) { | |
116 /* Object outside of up-down bounds. */ | |
117 if (block->y + (int)block->h <= map->player_y || | |
118 block->y >= map->player_y + (int)map->player_sprite->cellh) | |
119 return 0; | |
120 | |
121 if ((dcol < 0 && block->x >= map->player_x + (int)map->player_sprite->cellw) || | |
122 (dcol > 0 && block->x + block->w <= map->player_x + map->player_sprite->cellw)) | |
123 return 0; | |
124 } | |
125 | |
126 return 1; | |
127 } | |
128 | |
129 /* | |
130 * Determine if this collision shape is "closer" to the player by checking the | |
131 * new block coordinates with the previous one. | |
132 */ | |
133 static int | |
134 is_block_better(const struct map_block *now, | |
135 const struct map_block *new, | |
136 int drow, | |
137 int dcol) | |
138 { | |
139 return ((drow < 0 && new->y + new->h > now->y + now->h) || | |
140 (drow > 0 && new->y < now->y) || | |
141 (dcol < 0 && new->x + new->w > now->x + now->w) || | |
142 (dcol > 0 && new->x < now->x)); | |
143 | |
144 } | |
145 | |
146 static void | |
147 center(struct map *map) | |
148 { | |
149 map->view_x = map->player_x - (int)(map->view_w / 2); | |
150 map->view_y = map->player_y - (int)(map->view_h / 2); | |
151 | |
152 if (map->view_x < 0) | |
153 map->view_x = 0; | |
154 else if ((unsigned int)map->view_x > WIDTH(map) - map->view_w) | |
155 map->view_x = WIDTH(map) - map->view_w; | |
156 | |
157 if (map->view_y < 0) | |
158 map->view_y = 0; | |
159 else if ((unsigned int)map->view_y > HEIGHT(map) - map->view_h) | |
160 map->view_y = HEIGHT(map) - map->view_h; | |
161 } | |
162 | |
163 static void | |
164 init(struct map *map) | |
165 { | |
166 /* Adjust view. */ | |
167 map->view_w = window.w; | |
168 map->view_h = window.h; | |
169 | |
170 /* Adjust margin. */ | |
171 map->margin_w = map->view_w - (MARGIN_WIDTH * 2) - map->player_sprite->cellw; | |
172 map->margin_h = map->view_h - (MARGIN_HEIGHT * 2) - map->player_sprite->cellh; | |
173 | |
174 /* Center the view by default. */ | |
175 center(map); | |
176 | |
177 /* Final bits. */ | |
178 walksprite_init(&map->player_ws, map->player_sprite, 150); | |
179 } | |
180 | |
181 static void | |
182 handle_keydown(struct map *map, const union event *event) | |
183 { | |
184 switch (event->key.key) { | |
185 case KEY_UP: | |
186 map->player_movement |= MOVING_UP; | |
187 break; | |
188 case KEY_RIGHT: | |
189 map->player_movement |= MOVING_RIGHT; | |
190 break; | |
191 case KEY_DOWN: | |
192 map->player_movement |= MOVING_DOWN; | |
193 break; | |
194 case KEY_LEFT: | |
195 map->player_movement |= MOVING_LEFT; | |
196 break; | |
197 default: | |
198 break; | |
199 } | |
200 | |
201 map->player_angle = orientations[map->player_movement]; | |
202 } | |
203 | |
204 static void | |
205 handle_keyup(struct map *map, const union event *event) | |
206 { | |
207 switch (event->key.key) { | |
208 case KEY_TAB: | |
209 map->flags ^= MAP_FLAGS_SHOW_GRID | MAP_FLAGS_SHOW_COLLIDE; | |
210 break; | |
211 case KEY_UP: | |
212 map->player_movement &= ~(MOVING_UP); | |
213 break; | |
214 case KEY_RIGHT: | |
215 map->player_movement &= ~(MOVING_RIGHT); | |
216 break; | |
217 case KEY_DOWN: | |
218 map->player_movement &= ~(MOVING_DOWN); | |
219 break; | |
220 case KEY_LEFT: | |
221 map->player_movement &= ~(MOVING_LEFT); | |
222 break; | |
223 default: | |
224 break; | |
225 } | |
226 } | |
227 | |
228 static int | |
229 cmp_tile(const struct tileset_tiledef *td1, const struct tileset_tiledef *td2) | |
230 { | |
231 if (td1->id < td2->id) | |
232 return -1; | |
233 if (td1->id > td2->id) | |
234 return 1; | |
235 | |
236 return 0; | |
237 } | |
238 | |
239 static struct tileset_tiledef * | |
240 find_tiledef_by_id(const struct map *map, unsigned short id) | |
241 { | |
242 typedef int (*cmp)(const void *, const void *); | |
243 | |
244 const struct tileset_tiledef key = { | |
245 .id = id | |
246 }; | |
247 | |
248 return bsearch(&key, map->tileset->tiledefs, map->tileset->tiledefsz, | |
249 sizeof (key), (cmp)cmp_tile); | |
250 } | |
251 | |
252 static struct tileset_tiledef * | |
253 find_tiledef_by_row_column_in_layer(const struct map *map, | |
254 const struct map_layer *layer, | |
255 int row, | |
256 int col) | |
257 { | |
258 unsigned short id; | |
259 | |
260 if (row < 0 || (unsigned int)row >= map->rows || | |
261 col < 0 || (unsigned int)col >= map->columns) | |
262 return 0; | |
263 | |
264 if ((id = layer->tiles[col + row * map->columns]) == 0) | |
265 return NULL; | |
266 | |
267 return find_tiledef_by_id(map, id - 1); | |
268 } | |
269 | |
270 static struct tileset_tiledef * | |
271 find_tiledef_by_row_column(const struct map *map, int row, int col) | |
272 { | |
273 struct tileset_tiledef *tile; | |
274 | |
275 /* TODO: probably a for loop when we have indefinite layers. */ | |
276 if (!(tile = find_tiledef_by_row_column_in_layer(map, &map->layers[1], row, col))) | |
277 tile = find_tiledef_by_row_column_in_layer(map, &map->layers[0], row, col); | |
278 | |
279 return tile; | |
280 } | |
281 | |
282 static void | |
283 find_block_iterate(const struct map *map, | |
284 struct map_block *block, | |
285 int rowstart, | |
286 int rowend, | |
287 int colstart, | |
288 int colend, | |
289 int drow, | |
290 int dcol) | |
291 { | |
292 assert(map); | |
293 assert(block); | |
294 | |
295 /* First, check with tiledefs. */ | |
296 for (int r = rowstart; r <= rowend; ++r) { | |
297 for (int c = colstart; c <= colend; ++c) { | |
298 struct tileset_tiledef *td; | |
299 struct map_block tmp; | |
300 | |
301 if (!(td = find_tiledef_by_row_column(map, r, c))) | |
302 continue; | |
303 | |
304 /* Convert to absolute values. */ | |
305 tmp.x = td->x + c * map->tileset->sprite->cellw; | |
306 tmp.y = td->y + r * map->tileset->sprite->cellh; | |
307 tmp.w = td->w; | |
308 tmp.h = td->h; | |
309 | |
310 /* This tiledef is out of context. */ | |
311 if (!is_block_relevant(map, &tmp, drow, dcol)) | |
312 continue; | |
313 | |
314 if (is_block_better(block, &tmp, drow, dcol)) { | |
315 block->x = tmp.x; | |
316 block->y = tmp.y; | |
317 block->w = tmp.w; | |
318 block->h = tmp.h; | |
319 } | |
320 } | |
321 } | |
322 | |
323 /* Now check if there are objects closer than tiledefs. */ | |
324 for (size_t i = 0; i < map->blocksz; ++i) { | |
325 const struct map_block *new = &map->blocks[i]; | |
326 | |
327 if (is_block_relevant(map, new, drow, dcol) && | |
328 is_block_better(block, new, drow, dcol)) { | |
329 block->x = new->x; | |
330 block->y = new->y; | |
331 block->w = new->w; | |
332 block->h = new->h; | |
333 } | |
334 } | |
335 } | |
336 | |
337 static void | |
338 find_collision(const struct map *map, struct map_block *block, int drow, int dcolumn) | |
339 { | |
340 assert((drow && !dcolumn) || (dcolumn && !drow)); | |
341 | |
342 const int playercol = map->player_x / map->tileset->sprite->cellw; | |
343 const int playerrow = map->player_y / map->tileset->sprite->cellh; | |
344 const int ncols = (map->player_sprite->cellw / map->tileset->sprite->cellw) + 1; | |
345 const int nrows = (map->player_sprite->cellh / map->tileset->sprite->cellh) + 1; | |
346 int rowstart, rowend, colstart, colend; | |
347 | |
348 if (drow) { | |
349 colstart = playercol; | |
350 colend = playercol + ncols; | |
351 | |
352 if (drow < 0) { | |
353 /* Moving UP. */ | |
354 rowstart = 0; | |
355 rowend = playerrow; | |
356 block->x = block->y = block->h = 0; | |
357 block->w = WIDTH(map); | |
358 } else { | |
359 /* Moving DOWN. */ | |
360 rowstart = playerrow; | |
361 rowend = HEIGHT(map); | |
362 block->x = block->h = 0; | |
363 block->y = HEIGHT(map); | |
364 block->w = WIDTH(map); | |
365 } | |
366 } else { | |
367 rowstart = playerrow; | |
368 rowend = playerrow + nrows; | |
369 | |
370 if (dcolumn < 0) { | |
371 /* Moving LEFT. */ | |
372 colstart = 0; | |
373 colend = playercol; | |
374 block->x = block->y = block->w = 0; | |
375 block->h = HEIGHT(map); | |
376 } else { | |
377 /* Moving RIGHT. */ | |
378 colstart = playercol; | |
379 colend = WIDTH(map); | |
380 block->x = WIDTH(map); | |
381 block->y = block->w = 0; | |
382 block->h = block->h; | |
383 } | |
384 } | |
385 | |
386 find_block_iterate(map, block, rowstart, rowend, colstart, colend, drow, dcolumn); | |
387 } | |
388 | |
389 static void | |
390 move_x(struct map *map, int delta) | |
391 { | |
392 struct map_block block; | |
393 | |
394 find_collision(map, &block, 0, delta < 0 ? -1 : +1); | |
395 | |
396 if (delta < 0 && map->player_x + delta < (int)(block.x + block.w)) | |
397 delta = map->player_x - block.x - block.w; | |
398 else if (delta > 0 && (int)(map->player_x + map->player_sprite->cellw + delta) >= block.x) | |
399 delta = block.x - map->player_x - (int)(map->player_sprite->cellw); | |
400 | |
401 map->player_x += delta; | |
402 | |
403 if ((delta < 0 && map->player_x < map->margin_x) || | |
404 (delta > 0 && map->player_x >= (int)(map->margin_x + map->margin_w))) | |
405 map->view_x += delta; | |
406 | |
407 if (map->view_x < 0) | |
408 map->view_x = 0; | |
409 else if (map->view_x >= (int)(WIDTH(map) - map->view_w)) | |
410 map->view_x = WIDTH(map) - map->view_w; | |
411 } | |
412 | |
413 static void | |
414 move_y(struct map *map, int delta) | |
415 { | |
416 struct map_block block; | |
417 | |
418 find_collision(map, &block, delta < 0 ? -1 : +1, 0); | |
419 | |
420 if (delta < 0 && map->player_y + delta < (int)(block.y + block.h)) | |
421 delta = map->player_y - block.y - block.h; | |
422 else if (delta > 0 && (int)(map->player_y + map->player_sprite->cellh + delta) >= block.y) | |
423 delta = block.y - map->player_y - (int)(map->player_sprite->cellh); | |
424 | |
425 map->player_y += delta; | |
426 | |
427 if ((delta < 0 && map->player_y < map->margin_y) || | |
428 (delta > 0 && map->player_y >= (int)(map->margin_y + map->margin_h))) | |
429 map->view_y += delta; | |
430 | |
431 if (map->view_y < 0) | |
432 map->view_y = 0; | |
433 else if (map->view_y >= (int)(HEIGHT(map) - map->view_h)) | |
434 map->view_y = HEIGHT(map) - map->view_h; | |
435 } | |
436 | |
437 static void | |
438 move(struct map *map, unsigned int ticks) | |
439 { | |
440 /* This is the amount of pixels the player must move. */ | |
441 const int delta = SPEED * ticks / SEC; | |
442 | |
443 /* This is the rectangle within the view where users must be. */ | |
444 map->margin_x = map->view_x + MARGIN_WIDTH; | |
445 map->margin_y = map->view_y + MARGIN_HEIGHT; | |
446 | |
447 int dx = 0; | |
448 int dy = 0; | |
449 | |
450 if (map->player_movement == 0) | |
451 return; | |
452 | |
453 if (map->player_movement & MOVING_UP) | |
454 dy = -1; | |
455 if (map->player_movement & MOVING_DOWN) | |
456 dy = 1; | |
457 if (map->player_movement & MOVING_LEFT) | |
458 dx = -1; | |
459 if (map->player_movement & MOVING_RIGHT) | |
460 dx = 1; | |
461 | |
462 /* Move the player and adjust view if needed. */ | |
463 if (dx) | |
464 move_x(map, dx * delta); | |
465 if (dy) | |
466 move_y(map, dy * delta); | |
467 | |
468 walksprite_update(&map->player_ws, ticks); | |
469 } | |
470 | |
471 static inline void | |
472 draw_layer_tile(const struct map *map, | |
473 const struct map_layer *layer, | |
474 struct texture *colbox, | |
475 int start_col, | |
476 int start_row, | |
477 int start_x, | |
478 int start_y, | |
479 unsigned int r, | |
480 unsigned int c) | |
481 { | |
482 const struct tileset_tiledef *td; | |
483 int index, id, sc, sr, mx, my; | |
484 | |
485 index = (start_col + c) + ((start_row + r) * map->columns); | |
486 | |
487 if ((id = layer->tiles[index]) == 0) | |
488 return; | |
489 | |
490 id -= 1; | |
491 | |
492 /* Sprite row/column. */ | |
493 sc = (id) % map->tileset->sprite->ncols; | |
494 sr = (id) / map->tileset->sprite->ncols; | |
495 | |
496 /* On screen coordinates. */ | |
497 mx = start_x + (int)c * (int)map->tileset->sprite->cellw; | |
498 my = start_y + (int)r * (int)map->tileset->sprite->cellh; | |
499 | |
500 tileset_draw(map->tileset, sr, sc, mx, my); | |
501 | |
502 if ((td = find_tiledef_by_id(map, id)) && texture_ok(colbox)) | |
503 texture_scale(colbox, 0, 0, 5, 5, mx + td->x, my + td->y, td->w, td->h, 0); | |
504 | |
505 if (map->flags & MAP_FLAGS_SHOW_GRID) { | |
506 painter_set_color(0x202e37ff); | |
507 painter_draw_line(mx, my, mx + (int)map->tileset->sprite->cellw, my); | |
508 painter_draw_line( | |
509 mx + (int)map->tileset->sprite->cellw - 1, my, | |
510 mx + (int)map->tileset->sprite->cellw - 1, my + (int)map->tileset->sprite->cellh); | |
511 } | |
512 } | |
513 | |
514 static void | |
515 draw_layer(const struct map *map, const struct map_layer *layer) | |
516 { | |
517 assert(map); | |
518 assert(layer); | |
519 | |
520 /* Beginning of view in row/column. */ | |
521 const unsigned int start_col = map->view_x / map->tileset->sprite->cellw; | |
522 const unsigned int start_row = map->view_y / map->tileset->sprite->cellh; | |
523 | |
524 /* Convert into x/y coordinate. */ | |
525 const int start_x = 0 - (map->view_x % (int)map->tileset->sprite->cellw); | |
526 const int start_y = 0 - (map->view_y % (int)map->tileset->sprite->cellh); | |
527 | |
528 /* Number of row/columns to draw starting from there. */ | |
529 const unsigned int ncols = (map->view_w / map->tileset->sprite->cellw) + 2; | |
530 const unsigned int nrows = (map->view_h / map->tileset->sprite->cellh) + 2; | |
531 | |
532 struct texture colbox = {0}; | |
533 | |
534 if (!layer->tiles) | |
535 return; | |
536 | |
537 /* Show collision box if requested. */ | |
538 if (map->flags & MAP_FLAGS_SHOW_COLLIDE && texture_new(&colbox, 16, 16) == 0) { | |
539 texture_set_blend_mode(&colbox, TEXTURE_BLEND_BLEND); | |
540 texture_set_alpha_mod(&colbox, 100); | |
541 PAINTER_BEGIN(&colbox); | |
542 painter_set_color(0xa53030ff); | |
543 painter_clear(); | |
544 PAINTER_END(); | |
545 } | |
546 | |
547 for (unsigned int r = 0; r < nrows; ++r) { | |
548 for (unsigned int c = 0; c < ncols; ++c) { | |
549 if (start_col + c >= map->columns || | |
550 start_row + r >= map->rows) | |
551 continue; | |
552 | |
553 draw_layer_tile(map, layer, &colbox, start_col, start_row, start_x, start_y, r, c); | |
554 } | |
555 } | |
556 | |
557 texture_finish(&colbox); | |
558 } | |
559 | |
560 static void | |
561 draw_collide(const struct map *map) | |
562 { | |
563 struct texture box = {0}; | |
564 | |
565 if (map->flags & MAP_FLAGS_SHOW_COLLIDE && texture_new(&box, 64, 64) == 0) { | |
566 /* Draw collide box around player if requested. */ | |
567 texture_set_alpha_mod(&box, 100); | |
568 texture_set_blend_mode(&box, TEXTURE_BLEND_BLEND); | |
569 PAINTER_BEGIN(&box); | |
570 painter_set_color(0x4f8fbaff); | |
571 painter_clear(); | |
572 PAINTER_END(); | |
573 texture_scale(&box, 0, 0, 64, 64, | |
574 map->player_x - map->view_x, map->player_y - map->view_y, | |
575 map->player_sprite->cellw, map->player_sprite->cellh, 0.f); | |
576 | |
577 /* Do the same for every objects. */ | |
578 PAINTER_BEGIN(&box); | |
579 painter_set_color(0xa8ca58ff); | |
580 painter_clear(); | |
581 PAINTER_END(); | |
582 | |
583 for (size_t i = 0; i < map->blocksz; ++i) { | |
584 texture_scale(&box, 0, 0, 64, 64, | |
585 map->blocks[i].x - map->view_x, map->blocks[i].y - map->view_y, | |
586 map->blocks[i].w, map->blocks[i].h, | |
587 0.f); | |
588 } | |
589 | |
590 texture_finish(&box); | |
591 } | |
592 } | |
593 | |
594 int | |
595 map_init(struct map *map) | |
596 { | |
597 assert(map); | |
598 | |
599 init(map); | |
600 tileset_start(map->tileset); | |
601 | |
602 return 0; | |
603 } | |
604 | |
605 void | |
606 map_handle(struct map *map, const union event *ev) | |
607 { | |
608 assert(map); | |
609 assert(ev); | |
610 | |
611 switch (ev->type) { | |
612 case EVENT_KEYDOWN: | |
613 handle_keydown(map, ev); | |
614 break; | |
615 case EVENT_KEYUP: | |
616 handle_keyup(map, ev); | |
617 break; | |
618 default: | |
619 break; | |
620 } | |
621 | |
622 action_stack_handle(&map->astack_par, ev); | |
623 action_stack_handle(&map->astack_seq, ev); | |
624 } | |
625 | |
626 void | |
627 map_update(struct map *map, unsigned int ticks) | |
628 { | |
629 assert(map); | |
630 | |
631 action_stack_update(&map->astack_par, ticks); | |
632 action_stack_update(&map->astack_seq, ticks); | |
633 | |
634 tileset_update(map->tileset, ticks); | |
635 | |
636 /* No movements if the sequential actions are running. */ | |
637 if (action_stack_completed(&map->astack_seq)) | |
638 move(map, ticks); | |
639 } | |
640 | |
641 void | |
642 map_draw(const struct map *map) | |
643 { | |
644 assert(map); | |
645 | |
646 /* Draw the texture about background/foreground. */ | |
647 draw_layer(map, &map->layers[MAP_LAYER_TYPE_BACKGROUND]); | |
648 draw_layer(map, &map->layers[MAP_LAYER_TYPE_FOREGROUND]); | |
649 | |
650 walksprite_draw( | |
651 &map->player_ws, | |
652 map->player_angle, | |
653 map->player_x - map->view_x, | |
654 map->player_y - map->view_y); | |
655 | |
656 draw_layer(map, &map->layers[MAP_LAYER_TYPE_ABOVE]); | |
657 draw_collide(map); | |
658 | |
659 action_stack_draw(&map->astack_par); | |
660 action_stack_draw(&map->astack_seq); | |
661 } | |
662 | |
663 void | |
664 map_finish(struct map *map) | |
665 { | |
666 assert(map); | |
667 | |
668 action_stack_finish(&map->astack_par); | |
669 action_stack_finish(&map->astack_seq); | |
670 | |
671 memset(map, 0, sizeof (*map)); | |
672 } |