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 <gint/display.h>
#include <gint/keyboard.h> /*debug*/
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@ -17,9 +21,9 @@ int events_bind_variable(EventHandler *handler, int *var, char *name) {
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; }

View file

@ -84,14 +84,14 @@ void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */
if(game->player.canDoSomething)
dimage(5, 5, &SignAction_img);
int i;
uint32_t i;
Player *player = &game->player;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
if(player->x >= (int)portal->collider.x1 * PXSIZE &&
player->x < (int)portal->collider.x2 * PXSIZE &&
player->y >= (int)portal->collider.y1 * PXSIZE &&
player->y < (int)portal->collider.y2 * PXSIZE) {
dimage(5, 5, &SignAction_img);
break;
}
@ -107,7 +107,8 @@ void game_draw(Game *game) {
map_render_by_layer(game, FOREGROUND);
game_render_indicator(game);
/*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, 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;
if(keydown(KEY_SHIFT)) {
int i;
uint32_t i;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
if(player->x >= (int)portal->collider.x1 * PXSIZE &&
player->x < (int)portal->collider.x2 * PXSIZE &&
player->y >= (int)portal->collider.y1 * PXSIZE &&
player->y < (int)portal->collider.y2 * PXSIZE) {
Portal *dest_portal = (Portal *)portal->portal;
Collider dest_collider = dest_portal->collider;
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 */
#if DEBUGMODE
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_police;
// NPC *npcRPG;
// uint32_t nbNPC = 0;
#define NPC_STACK_SIZE 256
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); }
@ -51,6 +72,7 @@ void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
free(fscore);
}
// TODO : Fix
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
int16_t dest, NPC *npc) {
if(npc_clear_path(npc))
@ -100,9 +122,8 @@ as_recons_fail:
return 1;
}
// Returns non zero error code on failure
// Custom a* implemetation
// Unoptimized, may become an issue
/* Custom a* implemetation
* Unoptimized, may become an issue */
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
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++) {
bscore = 255;
// Cheapest known tile
/* Cheapest known tile */
/* Could be improved with a priority queue*/
for(i = 0; i <= w * h; i++) {
if(visited[i])
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
void update_npcs(Game *game) {
for(uint32_t u = 0; u < game->map_level->nbNPC; u++) {
update_npc(&game->map_level->npcs[u]);
uint32_t i;
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);
}
void npc_draw(Game *game) {
Player *pl = &game->player;
size_t i;
const bopti_image_t *npc_sprites[FACES] = {
&tiny_npc_male, &tiny_npc_female, &tiny_npc_milkman, &tiny_npc_police};
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++) {
NPC *Data = &game->map_level->npcs[u];
void npc_draw_single(NPC *npc, Player *pl) {
/* Render the path if in debug*/
/* Render the path if in debug and it has one*/
#if DEBUGMODE
if(!Data->hasPath)
continue; /* this NPC has a trajectory */
int NbPoints = Data->path_length + 1;
if(npc->hasPath) {
int NbPoints = npc->path_length + 1;
for(int v = 0; v < NbPoints; v++) {
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 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 deltaX2 =
((int16_t)(Data->x + Data->xpath[(v + 1) % NbPoints]) *
PXSIZE) -
((int16_t)(npc->x + npc->xpath[(v + 1) % NbPoints]) * PXSIZE) -
(int16_t)pl->wx;
int16_t deltaY2 =
((int16_t)(Data->y + Data->ypath[(v + 1) % NbPoints]) *
PXSIZE) -
((int16_t)(npc->y + npc->ypath[(v + 1) % NbPoints]) * PXSIZE) -
(int16_t)pl->wy;
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
pl->py + deltaY2, PATH_COLOR);
}
#endif // DEBUGMODE
}
#endif /* DEBUGMODE */
int16_t delX = ((Data->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
int16_t delY = ((Data->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
bopti_image_t *face = npc_sprites[Data->face];
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face);
int16_t delX = ((npc->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
int16_t delY = ((npc->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
bopti_image_t *face = npc_sprites[npc->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
// Useful if you want to safely edit a path
int npc_clear_path(NPC *npc);
/* /!\ Warning /!\
* Do not keep hard references to non-static NPCs, as they will likely move
* in the stack */
// 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);
// realloc()s npcRPG to adequate size and returns a pointer to the new element
// Returns NULL on failure
/* Creates a new NPC in the NPC stack (Needs to be set to valid values !)
* Returns NULL on failure */
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);
/* 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
* map! */
void npc_draw(Game *game);
/* Updates the static NPCs and the NPC stack */
void update_npcs(Game *game);
/* Updates the singular NPC npc. Be careful with it ! */
void update_npc(NPC *npc);
void reload_npc(Game *game);
/* Inits/Clears the NPC stack*/
void npc_reload(Game *game);
#endif

View file

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