npc : Début d'ajout d'IA

This commit is contained in:
attilavs2 2024-08-12 16:28:35 +02:00
parent 3c6a2faf99
commit e37bf141c2
6 changed files with 123 additions and 23 deletions

View file

@ -309,15 +309,15 @@ def convert_map(input: str, output: str, params: dict, target):
npc_struct += fxconv.u32(i["position"][0]) npc_struct += fxconv.u32(i["position"][0])
npc_struct += fxconv.u32(i["position"][1]) npc_struct += fxconv.u32(i["position"][1])
npc_struct += fxconv.u16(i["face"]) npc_struct += fxconv.u16(i["face"])
npc_struct += fxconv.u8(0) npc_struct += fxconv.u8(0) #paused
npc_struct += fxconv.u8(i["hasDialog"]) npc_struct += fxconv.u8(i["hasDialog"])
npc_struct += fxconv.u32(i["dialogID"]) npc_struct += fxconv.u32(i["dialogID"])
npc_struct += fxconv.u32(i["needAction"]) npc_struct += fxconv.u32(i["needAction"])
npc_struct += fxconv.string(i["name"]) npc_struct += fxconv.string(i["name"])
npc_struct += fxconv.u8(len(i["path"]) > 2) npc_struct += fxconv.u8(len(i["path"]) > 2)
npc_struct += fxconv.u8(0) npc_struct += fxconv.u8(0) #owns_path
npc_struct += fxconv.u8(len(i["path"])//2) npc_struct += fxconv.u8(len(i["path"])//2)
npc_struct += fxconv.u8(0) npc_struct += fxconv.u8(0) #current_point
xpath = bytes() xpath = bytes()
ypath = bytes() ypath = bytes()
@ -330,9 +330,11 @@ def convert_map(input: str, output: str, params: dict, target):
npc_struct += fxconv.ptr(xpath) npc_struct += fxconv.ptr(xpath)
npc_struct += fxconv.ptr(ypath) npc_struct += fxconv.ptr(ypath)
npc_struct += fxconv.u32(0) # TODO: Type npc_struct += fxconv.u16(0) # Type - leave as
npc_struct += fxconv.u8(0) # TODO: Group npc_struct += fxconv.u8(0) # TODO: Group
npc_struct += fxconv.u8(0) # TODO: Hostile to npc_struct += fxconv.u8(0) # Hostile to - leave as
npc_struct += fxconv.u8(0) # state - leave as
npc_struct += fxconv.u8(0) # Padding
npc_struct += fxconv.u16(0) # Padding npc_struct += fxconv.u16(0) # Padding
map_struct += fxconv.ptr(npc_struct) map_struct += fxconv.ptr(npc_struct)
# Load signs # Load signs

View file

@ -11,18 +11,21 @@
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
extern bopti_image_t SignAction_img; extern bopti_image_t SignAction_img;
extern bopti_image_t player_male_img; extern bopti_image_t player_male_img;
extern bopti_image_t tiny_npc_male; extern bopti_image_t tiny_npc_male;
extern Dialog *dialogRPG; extern Dialog *dialogRPG;
// extern NPC *npcRPG;
// extern uint32_t nbNPC;
#define MAX_INTERACTION_DISTANCE 12 #define MAX_INTERACTION_DISTANCE 12
void game_init(Game *game) { void game_init(Game *game) {
/*Seed the stdlib rand() function*/
uint32_t randseed = time(NULL);
srand(randseed);
game->map_level = worldRPG[0]; game->map_level = worldRPG[0];
/* NPC animation */ /* NPC animation */
animation_new(&game->npc_animation, &tiny_npc_male, 3, 250); animation_new(&game->npc_animation, &tiny_npc_male, 3, 250);
@ -279,9 +282,15 @@ void game_get_inputs(Game *game) {
mynpc->xpath = NULL; mynpc->xpath = NULL;
mynpc->ypath = NULL; mynpc->ypath = NULL;
} }
while(keydown(KEY_F1)){
clearevents();
}
} }
if(keydown(KEY_F2)) { if(keydown(KEY_F2)) {
npc_remove_pos(0); npc_remove_pos(0);
while(keydown(KEY_F2)){
clearevents();
}
} }
/* Display Debug Information on screen */ /* Display Debug Information on screen */

View file

@ -143,16 +143,21 @@ typedef struct {
/* data for NPC's trajectories */ /* data for NPC's trajectories */
uint8_t hasPath; uint8_t hasPath;
uint8_t owns_path; uint8_t owns_path; /*If the NPCs path is malloc()ed*/
uint8_t path_length; uint8_t path_length;
uint8_t currentPoint; uint8_t currentPoint;
int16_t *xpath; int16_t *xpath;
int16_t *ypath; int16_t *ypath;
int type : 32; /*Should be one of NPC_ - 0 for static NPCs*/
uint16_t type;
/*The follwing should be one of NPC_T*/
uint8_t current_group; uint8_t current_group;
uint8_t hostile_to_group; uint8_t hostile_to_group;
/*state should be one of NPC_S*/
uint8_t state;
uint8_t __temp;
/* uint16_t to keep the struct aligned */ /* uint16_t to keep the struct aligned */
uint16_t __padding; uint16_t __padding;

View file

@ -124,6 +124,7 @@ int main(void) {
_message_buffer = NULL; _message_buffer = NULL;
_message_buffer = malloc(MESSAGE_BUFFER_SZ); _message_buffer = malloc(MESSAGE_BUFFER_SZ);
if(!_message_buffer) { if(!_message_buffer) {
dclear(C_WHITE);
dtext(64, 64, C_BLACK, dtext(64, 64, C_BLACK,
"Failed to allocate the message buffer: not " "Failed to allocate the message buffer: not "
"enough RAM available. Press any key to quit."); "enough RAM available. Press any key to quit.");
@ -131,6 +132,7 @@ int main(void) {
getkey(); getkey();
return 0; return 0;
} }
game_init(&game); game_init(&game);
#if USB_FEATURE #if USB_FEATURE
@ -144,11 +146,6 @@ int main(void) {
dgray(DGRAY_ON); dgray(DGRAY_ON);
#endif #endif
#if DEBUGMODE
dupdate();
getkey();
#endif
do { do {
/* render the map */ /* render the map */
game_draw(&game); game_draw(&game);

View file

@ -18,6 +18,32 @@ extern bopti_image_t tiny_npc_female;
extern bopti_image_t tiny_npc_milkman; extern bopti_image_t tiny_npc_milkman;
extern bopti_image_t tiny_npc_police; extern bopti_image_t tiny_npc_police;
NPC_TypeData npc_typedat[NPC_Type_Count] = {
/*NPC_Static*/
{0, 0, 0, 0},
/*NPC_Guard*/
{
.agressivity = 75,
.cowardice = 85,
.lazyness = 50,
.wanderlust = 150
},
/*NPC_Bandit*/
{
.agressivity = 110,
.cowardice = 85,
.lazyness = 40,
.wanderlust = 60
},
/*NPC_Monster*/
{
.agressivity = 170,
.cowardice = 50,
.lazyness = 40,
.wanderlust = 80
}
};
NPC npc_stack[NPC_STACK_SIZE]; NPC npc_stack[NPC_STACK_SIZE];
uint32_t npc_count; uint32_t npc_count;
@ -340,16 +366,50 @@ void update_npcs(Game *game) {
} }
for(i = 0; i < npc_count; i++) { for(i = 0; i < npc_count; i++) {
update_npc(&npc_stack[i], game); update_npc(&npc_stack[i], game);
/*Temp debug*/ }
game->mana = npc_pathfind(game->player.x, game->player.y, }
game->map_level, &npc_stack[i]);
void npc_ai(NPC *npc, Game *game){
NPC_TypeData *tdat = &npc_typedat[npc->type];
uint32_t idle_chance = 0;
uint32_t wander_chance = 0;
uint32_t flee_chance = 0;
uint32_t attack_chance = 0;
switch(npc->state){
case NPC_S_IDLE : {
/*TODO : Expand conditions to switch states*/
break;
}
case NPC_S_WANDER : {
/*TODO : Choose a random close point to pathfind to */
break;
}
case NPC_S_FLEE : {
/*TODO : Pathfind to a point away from the player*/
break;
}
case NPC_S_ATTACK : {
/*TODO : Attack !*/
break;
}
default : {
/*Get real*/
npc->state = NPC_S_IDLE;
break;
}
} }
} }
extern const short int walkable_speed[WALKABLE_TILE_MAX]; extern const short int walkable_speed[WALKABLE_TILE_MAX];
void update_npc(NPC *npc, Game *game) { void update_npc(NPC *npc, Game *game) {
/* if the NPC has no path or is paused, skip it */ if(npc->type != NPC_Static)
npc_ai(npc, game);
/* if the NPC has no path or is paused, skip the moving part */
if(!npc->hasPath || npc->paused == true) if(!npc->hasPath || npc->paused == true)
return; return;

View file

@ -16,13 +16,40 @@
#define npc_to_curxy(a) (((a)*PXSIZE) << PRECISION) #define npc_to_curxy(a) (((a)*PXSIZE) << PRECISION)
enum { typedef struct {
NPC_NONE = 0, /*TODO : Stats*/
NPC_FRIENDLY = 1, // The player's team
NPC_HOSTILE = 2, // to the player /*AI weights - Values on 255*/
NPC_ALL = 3 uint8_t agressivity; /*Attack*/
uint8_t cowardice; /*Flee*/
uint8_t lazyness; /*Idle*/
uint8_t wanderlust; /*Wandering*/
} NPC_TypeData;
enum {
NPC_Static = 0, /*~= none, disqualifies from all AI*/
NPC_Guard = 1,
NPC_Bandit = 2,
NPC_Monster = 3,
NPC_Type_Count
}; };
enum {
NPC_T_NONE = 0,
NPC_T_FRIENDLY = 1, /* The player's team */
NPC_T_HOSTILE = 2, /* to the player */
NPC_T_ALL = 3
};
enum {
NPC_S_IDLE = 0,
NPC_S_ATTACK = 1,
NPC_S_FLEE = 2,
NPC_S_WANDER = 3
};
/* /!\ Warning /!\ /* /!\ Warning /!\
* Do not keep hard references to non-static NPCs, as they will likely move * Do not keep hard references to non-static NPCs, as they will likely move
* in the stack */ * in the stack */