mirror of
https://git.planet-casio.com/Slyvtt/Collab_RPG.git
synced 2024-12-28 20:43:42 +01:00
Début de pathfinding pour les NPCs
This commit is contained in:
parent
15570a8d91
commit
96f413eb14
4 changed files with 147 additions and 39 deletions
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; i<game->map_level->nbextradata; i++ )
|
||||
|
|
159
src/npc.c
159
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; u<nbNPC; u++ )
|
||||
{
|
||||
/* if the NPC has a path to follow AND is not currently in pause */
|
||||
/* (talking with the player) */
|
||||
if (npcRPG[u].hasPath==1 && npcRPG[u].paused==false)
|
||||
{
|
||||
float vecX = (float) (npcRPG[u].xpath[ npcRPG[u].currentPoint ] +
|
||||
npcRPG[u].x) - npcRPG[u].curx;
|
||||
float vecY = (float) (npcRPG[u].ypath[ npcRPG[u].currentPoint ] +
|
||||
npcRPG[u].y) - npcRPG[u].cury;
|
||||
float vecN = length(vecX, vecY);
|
||||
npc->path_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; u<nbNPC; u++ )
|
||||
{
|
||||
update_npc(&npcRPG[u]);
|
||||
}
|
||||
}
|
||||
|
||||
void update_npc(NPC *npc)
|
||||
{
|
||||
/* if the NPC has no path and is paused, skip it */
|
||||
if (!npc->hasPath && 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; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
|
||||
for (uint32_t u=0; u<game->map_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; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
|
||||
for (uint32_t u=0; u<game->map_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; u<nbNPC; u++) //uint pour enlever un warning
|
||||
for (uint32_t u=0; u<nbNPC; u++)
|
||||
{
|
||||
NPC *Data = &npcRPG[u];
|
||||
|
||||
/* TODO : This is for debugging purpose, JUste to render the path */
|
||||
/* to be followed by the NPC when this will be implemented */
|
||||
/* Render the path if in debug*/
|
||||
#if DEBUGMODE
|
||||
if (Data->hasPath==1) /* this NPC has a trajectory */
|
||||
{
|
||||
|
|
17
src/npc.h
17
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue