#include #include #include "vga.h" #include "map.h" #include "data.h" #include "entities.h" #include "player.h" #include "effect.h" #define MAX_ENTITY 16 static Entity entities[MAX_ENTITY]; static uint8_t last; static uint8_t sort_cnt; static Entity *sort[MAX_ENTITY + 1]; static Entity player_ent; void entities_init() { memset(entities, 0, sizeof(Entity) * MAX_ENTITY); last = 0; memset(&player_ent, 0, sizeof(Entity)); player_ent.used = USED_PLAYER; sort_cnt = 0; } Entity *entities_new() { for (uint8_t i = 0; i < MAX_ENTITY; i++) { if (entities[i].used == USED_FREE) { memset(&entities[i], 0, sizeof(Entity)); entities[i].used = USED_FG; if (i >= last) last = i + 1; return &entities[i]; } } return NULL; } void entities_update() { for (uint8_t i = 0; i < last; i++) if (entities[i].used) { entities[i].ox = entities[i].x; entities[i].oy = entities[i].y; entities[i].update(&entities[i]); } } void entities_sort() { sort_cnt = 0; for (uint8_t i = 0; i < last; i++) if (entities[i].used) sort[sort_cnt++] = &entities[i]; player_ent.y = player_y(); sort[sort_cnt++] = &player_ent; /* using insertion sort; * * The sorting criteria is the y coordinate unless the entities * share a 16px area in which we check the value of used that defines 3 * layers: bg, fb and player. * */ Entity *t; uint8_t i = 1; while (i < sort_cnt) { uint8_t j = i; while (j > 0 && ( ((sort[j - 1]->y >> 4) == (sort[j]->y >> 4) && sort[j - 1]->used > sort[j]->used) || sort[j - 1]->y > sort[j]->y )) { t = sort[j]; sort[j] = sort[j - 1]; sort[j - 1] = t; j--; } i++; } } void entities_draw() { Rect dst = { 0, 0, 16, 16 }; player_erase(); for (uint8_t i = 0; i < last; i++) { if (entities[i].erase) { dst.x = entities[i].ox; dst.y = entities[i].oy + MAP_OFFS_Y; blit_copy16(&dst); entities[i].erase = 0; } } /* draw in order to avoid flickering */ for (uint8_t i = 0; i < sort_cnt; i++) switch (sort[i]->used) { case USED_FREE: break; case USED_FG: case USED_BG: dst.x = sort[i]->x; dst.y = sort[i]->y + MAP_OFFS_Y; blitrc(binary_sprites_start, &sort[i]->frames[sort[i]->dir * 4 + sort[i]->frame], &dst); sort[i]->erase = 1; break; case USED_PLAYER: player_draw(); break; } } void entities_warp_out_all() { Entity *e = entities; for (uint8_t i = 0; i < last; i++, e++) if (e->used) effect_out_init(e); }