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"][1])
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.u32(i["dialogID"])
npc_struct += fxconv.u32(i["needAction"])
npc_struct += fxconv.string(i["name"])
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(0)
npc_struct += fxconv.u8(0) #current_point
xpath = 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(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: 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
map_struct += fxconv.ptr(npc_struct)
# Load signs

View file

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

View file

@ -143,16 +143,21 @@ typedef struct {
/* data for NPC's trajectories */
uint8_t hasPath;
uint8_t owns_path;
uint8_t owns_path; /*If the NPCs path is malloc()ed*/
uint8_t path_length;
uint8_t currentPoint;
int16_t *xpath;
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 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 __padding;

View file

@ -124,6 +124,7 @@ int main(void) {
_message_buffer = NULL;
_message_buffer = malloc(MESSAGE_BUFFER_SZ);
if(!_message_buffer) {
dclear(C_WHITE);
dtext(64, 64, C_BLACK,
"Failed to allocate the message buffer: not "
"enough RAM available. Press any key to quit.");
@ -131,6 +132,7 @@ int main(void) {
getkey();
return 0;
}
game_init(&game);
#if USB_FEATURE
@ -144,11 +146,6 @@ int main(void) {
dgray(DGRAY_ON);
#endif
#if DEBUGMODE
dupdate();
getkey();
#endif
do {
/* render the map */
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_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];
uint32_t npc_count;
@ -340,16 +366,50 @@ void update_npcs(Game *game) {
}
for(i = 0; i < npc_count; i++) {
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];
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)
return;

View file

@ -16,13 +16,40 @@
#define npc_to_curxy(a) (((a)*PXSIZE) << PRECISION)
enum {
typedef struct {
NPC_NONE = 0,
NPC_FRIENDLY = 1, // The player's team
NPC_HOSTILE = 2, // to the player
NPC_ALL = 3
/*TODO : Stats*/
/*AI weights - Values on 255*/
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 /!\
* Do not keep hard references to non-static NPCs, as they will likely move
* in the stack */