npc : Ajout de npc_stack et réecriture des fonctions + Résolution de warnings

This commit is contained in:
attilavs2 2024-08-01 15:05:42 +02:00
parent 6c47d5d83c
commit fd28af1005
5 changed files with 125 additions and 61 deletions

View file

@ -1,5 +1,9 @@
#include "events.h" #include "events.h"
#include <gint/display.h>
#include <gint/keyboard.h> /*debug*/
#include <math.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -17,9 +21,9 @@ int events_bind_variable(EventHandler *handler, int *var, char *name) {
char op_chars[OP_AMOUNT + 1] = " =+-/*%"; 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; } int _op_add(int a, int b) { return a + b; }

View file

@ -84,14 +84,14 @@ void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */ /* nothing to do for the player so we quit */
if(game->player.canDoSomething) if(game->player.canDoSomething)
dimage(5, 5, &SignAction_img); dimage(5, 5, &SignAction_img);
int i; uint32_t i;
Player *player = &game->player; Player *player = &game->player;
for(i = 0; i < game->map_level->nbPortal; i++) { for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i]; Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE && if(player->x >= (int)portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE && player->x < (int)portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE && player->y >= (int)portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) { player->y < (int)portal->collider.y2 * PXSIZE) {
dimage(5, 5, &SignAction_img); dimage(5, 5, &SignAction_img);
break; break;
} }
@ -107,7 +107,8 @@ void game_draw(Game *game) {
map_render_by_layer(game, FOREGROUND); map_render_by_layer(game, FOREGROUND);
game_render_indicator(game); game_render_indicator(game);
/*DEBUG*/ /*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, 16, C_BLACK, "Mana: %d", game->mana);
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y); 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; Player *player = &game->player;
if(keydown(KEY_SHIFT)) { if(keydown(KEY_SHIFT)) {
int i; uint32_t i;
for(i = 0; i < game->map_level->nbPortal; i++) { for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i]; Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE && if(player->x >= (int)portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE && player->x < (int)portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE && player->y >= (int)portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) { player->y < (int)portal->collider.y2 * PXSIZE) {
Portal *dest_portal = (Portal *)portal->portal; Portal *dest_portal = (Portal *)portal->portal;
Collider dest_collider = dest_portal->collider; Collider dest_collider = dest_portal->collider;
Map *dest_map = (Map *)portal->map; 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 */ /* Display Debug Information on screen */
#if DEBUGMODE #if DEBUGMODE
if(keydown(KEY_F1)) { if(keydown(KEY_F1)) {

View file

@ -16,8 +16,29 @@ 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 *npcRPG; #define NPC_STACK_SIZE 256
// uint32_t nbNPC = 0;
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); } 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); free(fscore);
} }
// TODO : Fix
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos, int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
int16_t dest, NPC *npc) { int16_t dest, NPC *npc) {
if(npc_clear_path(npc)) if(npc_clear_path(npc))
@ -100,9 +122,8 @@ as_recons_fail:
return 1; return 1;
} }
// Returns non zero error code on failure /* Custom a* implemetation
// Custom a* implemetation * Unoptimized, may become an issue */
// Unoptimized, may become an issue
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) { int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
int32_t i, j; 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++) { for(int iter = 0; iter < 64; iter++) {
bscore = 255; bscore = 255;
// Cheapest known tile /* Cheapest known tile */
/* Could be improved with a priority queue*/
for(i = 0; i <= w * h; i++) { for(i = 0; i <= w * h; i++) {
if(visited[i]) if(visited[i])
continue; 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 // Refactoring to make adding complexity cleaner
void update_npcs(Game *game) { void update_npcs(Game *game) {
for(uint32_t u = 0; u < game->map_level->nbNPC; u++) { uint32_t i;
update_npc(&game->map_level->npcs[u]); 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); npc->cury += vecY * (float)(1 << PRECISION);
} }
void npc_draw(Game *game) { bopti_image_t *npc_sprites[FACES] = {&tiny_npc_male, &tiny_npc_female,
Player *pl = &game->player; &tiny_npc_milkman, &tiny_npc_police};
size_t i;
const 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++) { void npc_draw_single(NPC *npc, Player *pl) {
NPC *Data = &game->map_level->npcs[u];
/* Render the path if in debug*/ /* Render the path if in debug and it has one*/
#if DEBUGMODE #if DEBUGMODE
if(!Data->hasPath) if(npc->hasPath) {
continue; /* this NPC has a trajectory */ int NbPoints = npc->path_length + 1;
int NbPoints = Data->path_length + 1;
for(int v = 0; v < NbPoints; v++) { for(int v = 0; v < NbPoints; v++) {
int16_t deltaX1 = 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)pl->wx;
int16_t deltaY1 = 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)pl->wy;
int16_t deltaX2 = int16_t deltaX2 =
((int16_t)(Data->x + Data->xpath[(v + 1) % NbPoints]) * ((int16_t)(npc->x + npc->xpath[(v + 1) % NbPoints]) * PXSIZE) -
PXSIZE) -
(int16_t)pl->wx; (int16_t)pl->wx;
int16_t deltaY2 = int16_t deltaY2 =
((int16_t)(Data->y + Data->ypath[(v + 1) % NbPoints]) * ((int16_t)(npc->y + npc->ypath[(v + 1) % NbPoints]) * PXSIZE) -
PXSIZE) -
(int16_t)pl->wy; (int16_t)pl->wy;
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2, dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
pl->py + deltaY2, PATH_COLOR); pl->py + deltaY2, PATH_COLOR);
} }
#endif // DEBUGMODE }
#endif /* DEBUGMODE */
int16_t delX = ((Data->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x; int16_t delX = ((npc->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
int16_t delY = ((Data->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y; int16_t delY = ((npc->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
bopti_image_t *face = npc_sprites[Data->face]; bopti_image_t *face = npc_sprites[npc->face];
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, 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; }

View file

@ -16,34 +16,41 @@ enum {
}; };
// Frees then malloc()s a new path to npc /* /!\ Warning /!\
// Useful if you want to safely edit a path * Do not keep hard references to non-static NPCs, as they will likely move
int npc_clear_path(NPC *npc); * in the stack */
// Adds point x,y to the path of npc /* Creates a new NPC in the NPC stack (Needs to be set to valid values !)
// Won't work on static NPCs, use npc_clear_path before or make them on the heap * Returns NULL on failure */
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
NPC *npc_create(); 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); 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 /* Draws the player player. This function should be called after drawing the
* map! */ * map! */
void npc_draw(Game *game); void npc_draw(Game *game);
/* Updates the static NPCs and the NPC stack */
void update_npcs(Game *game); void update_npcs(Game *game);
/* Updates the singular NPC npc. Be careful with it ! */
void update_npc(NPC *npc); void update_npc(NPC *npc);
/* Inits/Clears the NPC stack*/
void reload_npc(Game *game); void npc_reload(Game *game);
#endif #endif

View file

@ -106,6 +106,8 @@ void player_move(Game *game, Direction direction) {
if(target->y < game->map_level->y) { if(target->y < game->map_level->y) {
player->y = target->h * T_HEIGHT; player->y = target->h * T_HEIGHT;
} }
npc_reload(game);
game->map_level = target; game->map_level = target;
} }
} }