From 96f413eb14885bf490b9ed6031b4d3bf82290659 Mon Sep 17 00:00:00 2001 From: attilavs2 Date: Sun, 21 Jul 2024 02:42:50 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9but=20de=20pathfinding=20pour=20les=20NP?= =?UTF-8?q?Cs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dialogs.c | 8 +-- src/game.c | 2 +- src/npc.c | 159 +++++++++++++++++++++++++++++++++++++++----------- src/npc.h | 17 +++++- 4 files changed, 147 insertions(+), 39 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index cdb5ce5..413bef2 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -68,7 +68,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, for(i=0;i<=BOX_HEIGHT;i++){ /* Redrawing the entire screen, because maybe there was no dialog displayed before. */ - update_npc(game); + update_npcs(game); draw(game); /* Fill the dialog box with white */ @@ -181,7 +181,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* Run another little fancy animation if we should. */ for(i=BOX_HEIGHT;i>0;i--){ /* It is the same as the start animation. */ - update_npc(game); + update_npcs(game); draw(game); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); @@ -302,7 +302,7 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) { /* Make a little animation because we looove little animations ;) */ for(i=DWIDTH/8+1;i>0;i--){ /* I'm drawing the same box as on the start animation */ - update_npc(game); + update_npcs(game); draw(game); showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, _i, false); @@ -379,4 +379,4 @@ void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNu showtext_dialog( game, face, text, true, true ); if (nextOther!=-1) initiate_dialog_sequence( game, face, nextOther ); } -} \ No newline at end of file +} diff --git a/src/game.c b/src/game.c index 135c336..bbdbccc 100644 --- a/src/game.c +++ b/src/game.c @@ -24,7 +24,7 @@ extern uint32_t nbNPC; void game_logic(Game *game) { - update_npc( game ); + update_npcs( game ); /* we check if interactions are possible close to the player */ for( uint32_t i=0; imap_level->nbextradata; i++ ) diff --git a/src/npc.c b/src/npc.c index 86a62b7..ac5cf24 100644 --- a/src/npc.c +++ b/src/npc.c @@ -15,7 +15,7 @@ extern bopti_image_t demo_PNJ_img; /* the color of the text to go to the next dialog phase */ -/* it improves readability to have somathing lighter */ +/* it improves readability to have something lighter */ #if defined(FXCG50) #define PATH_COLOR C_RED #else @@ -31,39 +31,133 @@ float length( float x, float y ) return sqrtf( x*x+y*y ); } -void update_npc( [[maybe_unused]] Game *game) +int npc_clear_path(NPC *npc) { - for( uint32_t u=0; upath_length = 0; + free(npc->xpath); + free(npc->ypath); + npc->xpath = malloc(4); + npc->ypath = malloc(4); + if(npc->xpath == NULL || npc->ypath == NULL) return 1; + return 0; +} - if (vecN>0.5f) - { - vecX /= vecN*2.0; - vecY /= vecN*2.0; - } - else - { - npcRPG[u].currentPoint++; - npcRPG[u].currentPoint = npcRPG[u].currentPoint % npcRPG[u].path_length; - } +//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) +{ + npc->path_length++; + realloc(npc->xpath, npc->path_length); + realloc(npc->ypath, npc->path_length); + if(npc->xpath == NULL || npc->ypath == NULL) return 1; + npc->xpath[npc->path_length-1] = x; + npc->ypath[npc->path_length-1] = y; +} - npcRPG[u].curx += vecX; - npcRPG[u].cury += vecY; - - } - } +uint8_t *as_reconstruct_path(uint8_t *came_from, int came_size, uint8_t *current, int curr_size) +{ } +//Returns non zero error code on failure +//Custom a* implemetation +//(Very much unfinished for now) +int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc) +{ + uint32_t w = full_map->w; + uint32_t h = full_map->h; + uint32_t x = npc->x; + uint32_t y = npc->y; + uint32_t spos = y*w+x; + uint8_t *map = full_map->walkable; + if(map[spos]) return 2; + + npc_clear_path(npc); + + uint8_t *came_from = malloc(w*h); + + uint8_t *gscore = malloc(w*h); + gscore[spos] = 0; + + uint8_t *fscore = malloc(w*h); + fscore[spos] = 0; + + int tx = x; + int ty = y; + int tpos = spos; + int bx; + int by; + int i, j; + + for(int iter=0; iter < 1024; iter++) + { + //Check surronding tiles for cost + bx = x-1; + by = y-1; + for(i = tx-1; i < tx+1; i++) + { + //Out of bounds (admissible) + if(i < 0) continue; + //Out of bounds (unforgiveable) + if(i > w) break; + for(j = ty-1; j < ty+1; j++) + { + //Out of bounds (admissible) + if(j < 0) continue; + //Out of bounds (joever for it) + if(j > h) break; + //Has collision + if(map[j*w+i]) continue; + if(i == dest_x && j == dest_y){ + return npc_append_path(i, j, npc); + } + //Calculate score (direct distance) + int deltX = tx-dest_x; + int deltY = ty-dest_y; + int tscore = sqrtf(deltX*deltX+deltY*deltY); + } + } + + } + return 1; +} + +//Refactoring to make adding complexity cleaner +void update_npcs([[maybe_unused]] Game *game) +{ + for( uint32_t u=0; uhasPath && npc->paused==true) return; + + float vecX = (float) (npc->xpath[ npc->currentPoint ] + + npc->x) - npc->curx; + float vecY = (float) (npc->ypath[ npc->currentPoint ] + + npc->y) - npc->cury; + float vecN = length(vecX, vecY); + + if (vecN>0.5f) + { + vecX /= vecN*2.0; + vecY /= vecN*2.0; + } + else + { + npc->currentPoint++; + npc->currentPoint = npc->currentPoint % npc->path_length; + } + + npc->curx += vecX; + npc->cury += vecY; + +} + +//TODO ; Add malloc() failure case void reload_npc(Game *game) { if (npcRPG!=NULL) @@ -76,7 +170,7 @@ void reload_npc(Game *game) nbNPC = 0; - for (uint32_t u=0; umap_level->nbextradata; u++) //uint pour enlever un warning + for (uint32_t u=0; umap_level->nbextradata; u++) { ExtraData *Data = &game->map_level->extradata[u]; @@ -89,7 +183,7 @@ void reload_npc(Game *game) npcRPG = (NPC*) malloc( nbNPC * sizeof(NPC) ); int currentNPC=0; - for (uint32_t u=0; umap_level->nbextradata; u++) //uint pour enlever un warning + for (uint32_t u=0; umap_level->nbextradata; u++) { ExtraData *Data = &game->map_level->extradata[u]; @@ -114,12 +208,11 @@ void reload_npc(Game *game) void npc_draw(Game *game) { Player *pl = &game->player; - for (uint32_t u=0; uhasPath==1) /* this NPC has a trajectory */ { diff --git a/src/npc.h b/src/npc.h index e7e1e12..b32f485 100644 --- a/src/npc.h +++ b/src/npc.h @@ -8,6 +8,15 @@ #include "game.h" #include "memory.h" +enum +{ + + NPC_NONE = 0, + NPC_FRIENDLY = 1, //The player's team + NPC_HOSTILE = 2, //to the player + NPC_ALL = 3 + +} NPC_groups; typedef struct { @@ -29,6 +38,10 @@ typedef struct int16_t *xpath; int16_t *ypath; + int8_t hostile_to_group; + + + /* is the current NPC in pause (during dialog) */ bool paused; } NPC; @@ -39,7 +52,9 @@ typedef struct * map! */ void npc_draw(Game *game); -void update_npc(Game *game); +void update_npcs(Game *game); + +void update_npc(NPC *npc); void reload_npc(Game *game);