diff --git a/src/events.c b/src/events.c index ff66087..31ffdcc 100644 --- a/src/events.c +++ b/src/events.c @@ -1,5 +1,9 @@ #include "events.h" +#include +#include /*debug*/ +#include +#include #include #include @@ -17,9 +21,9 @@ int events_bind_variable(EventHandler *handler, int *var, char *name) { char op_chars[OP_AMOUNT + 1] = " =+-/*%"; -int _op_null(int a, int b) { return 0; } +int _op_null(GUNUSED int a, GUNUSED int b) { return 0; } -int _op_set(int a, int b) { return b; } +int _op_set(GUNUSED int a, int b) { return b; } int _op_add(int a, int b) { return a + b; } diff --git a/src/game.c b/src/game.c index 1b84b1f..bd918ae 100644 --- a/src/game.c +++ b/src/game.c @@ -84,14 +84,14 @@ void game_render_indicator(Game *game) { /* nothing to do for the player so we quit */ if(game->player.canDoSomething) dimage(5, 5, &SignAction_img); - int i; + uint32_t i; Player *player = &game->player; for(i = 0; i < game->map_level->nbPortal; i++) { Portal *portal = &game->map_level->portals[i]; - if(player->x >= portal->collider.x1 * PXSIZE && - player->x < portal->collider.x2 * PXSIZE && - player->y >= portal->collider.y1 * PXSIZE && - player->y < portal->collider.y2 * PXSIZE) { + if(player->x >= (int)portal->collider.x1 * PXSIZE && + player->x < (int)portal->collider.x2 * PXSIZE && + player->y >= (int)portal->collider.y1 * PXSIZE && + player->y < (int)portal->collider.y2 * PXSIZE) { dimage(5, 5, &SignAction_img); break; } @@ -107,7 +107,8 @@ void game_draw(Game *game) { map_render_by_layer(game, FOREGROUND); game_render_indicator(game); /*DEBUG*/ - dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life); + extern uint32_t npc_count; + dprint(8, 8, C_BLACK, "npc_count: %d", npc_count); dprint(8, 16, C_BLACK, "Mana: %d", game->mana); dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y); } @@ -145,13 +146,13 @@ void game_get_inputs(Game *game) { } Player *player = &game->player; if(keydown(KEY_SHIFT)) { - int i; + uint32_t i; for(i = 0; i < game->map_level->nbPortal; i++) { Portal *portal = &game->map_level->portals[i]; - if(player->x >= portal->collider.x1 * PXSIZE && - player->x < portal->collider.x2 * PXSIZE && - player->y >= portal->collider.y1 * PXSIZE && - player->y < portal->collider.y2 * PXSIZE) { + if(player->x >= (int)portal->collider.x1 * PXSIZE && + player->x < (int)portal->collider.x2 * PXSIZE && + player->y >= (int)portal->collider.y1 * PXSIZE && + player->y < (int)portal->collider.y2 * PXSIZE) { Portal *dest_portal = (Portal *)portal->portal; Collider dest_collider = dest_portal->collider; Map *dest_map = (Map *)portal->map; @@ -167,6 +168,23 @@ void game_get_inputs(Game *game) { } } + /*Temp debug*/ + if(keydown(KEY_F1)) { + NPC *mynpc = npc_create(); + if(mynpc) { + mynpc->curx = player->x; + mynpc->cury = player->y; + mynpc->x = 0; + mynpc->y = 0; + mynpc->hasPath = 0; + mynpc->face = 0; + mynpc->paused = 0; + mynpc->has_dialog = 0; + dprint(0, 50, 0, "succes"); + dupdate(); + } + } + /* Display Debug Information on screen */ #if DEBUGMODE if(keydown(KEY_F1)) { diff --git a/src/npc.c b/src/npc.c index 5479ba0..32dbc53 100644 --- a/src/npc.c +++ b/src/npc.c @@ -16,8 +16,29 @@ extern bopti_image_t tiny_npc_female; extern bopti_image_t tiny_npc_milkman; extern bopti_image_t tiny_npc_police; -// NPC *npcRPG; -// uint32_t nbNPC = 0; +#define NPC_STACK_SIZE 256 + +NPC npc_stack[NPC_STACK_SIZE]; +uint32_t npc_count; + +NPC *npc_create() { + if(npc_count == 256) + return NULL; + + return &npc_stack[npc_count++]; +} + +void npc_remove(NPC *npc) { + uint32_t pos = (uint32_t)npc - (uint32_t)npc_stack; + + if(pos == npc_count) { + npc_count--; + return; + } + memmove(npc, npc + sizeof(NPC), sizeof(NPC) * (npc_count - pos)); + + return; +} float length(float x, float y) { return sqrtf(x * x + y * y); } @@ -51,6 +72,7 @@ void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) { free(fscore); } +// TODO : Fix int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos, int16_t dest, NPC *npc) { if(npc_clear_path(npc)) @@ -100,9 +122,8 @@ as_recons_fail: return 1; } -// Returns non zero error code on failure -// Custom a* implemetation -// Unoptimized, may become an issue +/* Custom a* implemetation + * Unoptimized, may become an issue */ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) { int32_t i, j; @@ -150,7 +171,8 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) { for(int iter = 0; iter < 64; iter++) { bscore = 255; - // Cheapest known tile + /* Cheapest known tile */ + /* Could be improved with a priority queue*/ for(i = 0; i <= w * h; i++) { if(visited[i]) continue; @@ -203,8 +225,12 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) { // Refactoring to make adding complexity cleaner void update_npcs(Game *game) { - for(uint32_t u = 0; u < game->map_level->nbNPC; u++) { - update_npc(&game->map_level->npcs[u]); + uint32_t i; + for(i = 0; i < game->map_level->nbNPC; i++) { + update_npc(&game->map_level->npcs[i]); + } + for(i = 0; i < npc_count; i++) { + update_npc(&npc_stack[i]); } } @@ -231,45 +257,52 @@ void update_npc(NPC *npc) { npc->cury += vecY * (float)(1 << PRECISION); } -void npc_draw(Game *game) { - Player *pl = &game->player; - size_t i; - const bopti_image_t *npc_sprites[FACES] = { - &tiny_npc_male, &tiny_npc_female, &tiny_npc_milkman, &tiny_npc_police}; +bopti_image_t *npc_sprites[FACES] = {&tiny_npc_male, &tiny_npc_female, + &tiny_npc_milkman, &tiny_npc_police}; - for(uint32_t u = 0; u < game->map_level->nbNPC; u++) { - NPC *Data = &game->map_level->npcs[u]; +void npc_draw_single(NPC *npc, Player *pl) { -/* Render the path if in debug*/ + /* Render the path if in debug and it has one*/ #if DEBUGMODE - if(!Data->hasPath) - continue; /* this NPC has a trajectory */ - int NbPoints = Data->path_length + 1; + if(npc->hasPath) { + int NbPoints = npc->path_length + 1; for(int v = 0; v < NbPoints; v++) { int16_t deltaX1 = - ((int16_t)(Data->x + Data->xpath[v % NbPoints]) * PXSIZE) - + ((int16_t)(npc->x + npc->xpath[v % NbPoints]) * PXSIZE) - (int16_t)pl->wx; int16_t deltaY1 = - ((int16_t)(Data->y + Data->ypath[v % NbPoints]) * PXSIZE) - + ((int16_t)(npc->y + npc->ypath[v % NbPoints]) * PXSIZE) - (int16_t)pl->wy; int16_t deltaX2 = - ((int16_t)(Data->x + Data->xpath[(v + 1) % NbPoints]) * - PXSIZE) - + ((int16_t)(npc->x + npc->xpath[(v + 1) % NbPoints]) * PXSIZE) - (int16_t)pl->wx; int16_t deltaY2 = - ((int16_t)(Data->y + Data->ypath[(v + 1) % NbPoints]) * - PXSIZE) - + ((int16_t)(npc->y + npc->ypath[(v + 1) % NbPoints]) * PXSIZE) - (int16_t)pl->wy; dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2, pl->py + deltaY2, PATH_COLOR); } -#endif // DEBUGMODE + } +#endif /* DEBUGMODE */ - int16_t delX = ((Data->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x; - int16_t delY = ((Data->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y; - bopti_image_t *face = npc_sprites[Data->face]; - dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face); + int16_t delX = ((npc->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x; + int16_t delY = ((npc->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y; + bopti_image_t *face = npc_sprites[npc->face]; + dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face); +} + +void npc_draw(Game *game) { + Player *pl = &game->player; + + uint32_t u; + for(u = 0; u < game->map_level->nbNPC; u++) { + npc_draw_single(&game->map_level->npcs[u], pl); + } + for(u = 0; u < npc_count; u++) { + npc_draw_single(&npc_stack[u], pl); } } + +void npc_reload(GUNUSED Game *game) { npc_count = 0; } diff --git a/src/npc.h b/src/npc.h index d12161c..8c7f83e 100644 --- a/src/npc.h +++ b/src/npc.h @@ -16,34 +16,41 @@ enum { }; -// Frees then malloc()s a new path to npc -// Useful if you want to safely edit a path -int npc_clear_path(NPC *npc); +/* /!\ Warning /!\ + * Do not keep hard references to non-static NPCs, as they will likely move + * in the stack */ -// Adds point x,y to the path of npc -// Won't work on static NPCs, use npc_clear_path before or make them on the heap -int npc_append_path(uint16_t x, uint16_t y, NPC *npc); - -// Clears the NPCs path and creates a new one going to dest, -// avoiding non-walkable tiles -// Returns non-zero on failure -int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc); - -// realloc()s npcRPG to adequate size and returns a pointer to the new element -// Returns NULL on failure +/* Creates a new NPC in the NPC stack (Needs to be set to valid values !) + * Returns NULL on failure */ NPC *npc_create(); -// Pops the NPC from npcRPG +/* Pops the NPC from the NPC stack + * Consider this as a free */ void npc_remove(NPC *npc); +/* Frees then malloc()s a new path to npc + * Useful if you want to safely edit a path */ +int npc_clear_path(NPC *npc); + +/* Adds point x,y to the path of npc + * Won't work on static NPCs, use npc_clear_path before or make them on the + * heap */ +int npc_append_path(uint16_t x, uint16_t y, NPC *npc); + +/* Clears the NPCs path and creates a new one going to dest, + * avoiding non-walkable tiles + * Returns non-zero on failure */ +int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc); + /* Draws the player player. This function should be called after drawing the * map! */ void npc_draw(Game *game); +/* Updates the static NPCs and the NPC stack */ void update_npcs(Game *game); - +/* Updates the singular NPC npc. Be careful with it ! */ void update_npc(NPC *npc); - -void reload_npc(Game *game); +/* Inits/Clears the NPC stack*/ +void npc_reload(Game *game); #endif diff --git a/src/player.c b/src/player.c index 6751d15..1316b67 100644 --- a/src/player.c +++ b/src/player.c @@ -106,6 +106,8 @@ void player_move(Game *game, Direction direction) { if(target->y < game->map_level->y) { player->y = target->h * T_HEIGHT; } + npc_reload(game); + game->map_level = target; } }