mirror of
https://git.planet-casio.com/Slyvtt/Collab_RPG.git
synced 2024-12-28 04:23:42 +01:00
npc : Simplification de npc_pathfinding + tentative collision de npcs + suppression de map_draw
This commit is contained in:
parent
1767643da1
commit
ee3b25a366
5 changed files with 87 additions and 143 deletions
99
src/map.c
99
src/map.c
|
@ -14,105 +14,6 @@ extern Map level4;
|
|||
|
||||
Map *worldRPG[] = {&level0, &level1, &level2, &level3, &level4, NULL};
|
||||
|
||||
// extern ExtraData *extraRPG[];
|
||||
|
||||
void map_render(Game *game) {
|
||||
|
||||
Map *map_level = game->map_level;
|
||||
Player *player = &game->player;
|
||||
|
||||
/* for all Layer (2 in the current configuration: Background is layer 0 and
|
||||
* foreground is layer 1 ) */
|
||||
/* x and y will contain the position in the loop. */
|
||||
unsigned char x, y;
|
||||
/* The positions where we start drawing the tiles will be in tx and
|
||||
* ty. */
|
||||
unsigned short int tx, ty;
|
||||
/* mx and my will contain how many pixels will be hidden on x and on
|
||||
* y. */
|
||||
unsigned char mx, my;
|
||||
/* dw and dh contain the amount of tiles that will be drawn on x and on
|
||||
* y. */
|
||||
unsigned char dw = DWIDTH / T_WIDTH + 2, dh = DHEIGHT / T_HEIGHT + 1;
|
||||
/* mw and mh will contain the height and the width of the map. */
|
||||
unsigned short int mw = map_level->w * T_WIDTH,
|
||||
mh = map_level->h * T_HEIGHT;
|
||||
/* tile contains the tile to draw. */
|
||||
short int tile;
|
||||
/* The position where I start drawing */
|
||||
unsigned short int sx, sy;
|
||||
/* The position of the tile in the tileset. */
|
||||
unsigned short int xtile, ytile;
|
||||
/* The layer we're drawing */
|
||||
unsigned char l;
|
||||
/* The index of the current tile we're drawing in the layer. */
|
||||
int current_index;
|
||||
/* Fix sx. */
|
||||
if(player->x < DWIDTH / 2) {
|
||||
/* If I can't center the player because I'm near the left border of
|
||||
* the map. */
|
||||
player->px = player->x;
|
||||
sx = 0;
|
||||
} else if(player->x + DWIDTH / 2 > mw) {
|
||||
/* If I can't center the player because I'm near the right border of
|
||||
* the map. */
|
||||
sx = mw - DWIDTH;
|
||||
player->px = player->x - sx;
|
||||
} else {
|
||||
/* I can center the player. */
|
||||
player->px = DWIDTH / 2;
|
||||
sx = player->x - player->px;
|
||||
}
|
||||
/* Fix sy. */
|
||||
if(player->y < DHEIGHT / 2) {
|
||||
/* If I can't center the player because I'm near the top border of
|
||||
* the map. */
|
||||
player->py = player->y;
|
||||
sy = 0;
|
||||
} else if(player->y + DHEIGHT / 2 > mh) {
|
||||
/* If I can't center the player because I'm near the bottom border
|
||||
* of the map. */
|
||||
sy = mh - DHEIGHT;
|
||||
player->py = player->y - sy;
|
||||
} else {
|
||||
/* I can center the player. */
|
||||
player->py = DHEIGHT / 2;
|
||||
sy = player->y - player->py;
|
||||
}
|
||||
tx = sx / T_WIDTH;
|
||||
ty = sy / T_HEIGHT;
|
||||
mx = sx - tx * T_WIDTH;
|
||||
my = sy - ty * T_HEIGHT;
|
||||
for(l = 0; l < map_level->nblayers - 1; l++) {
|
||||
/* Draw a layer of the map on screen. */
|
||||
for(y = 0; y < dh; y++) {
|
||||
for(x = 0; x < dw; x++) {
|
||||
/* I get the tile number if his position is inside the map. Then
|
||||
* I draw it. */
|
||||
if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
|
||||
ty + y < map_level->h) {
|
||||
/* index of the current tile */
|
||||
current_index = (y + ty) * map_level->w + tx + x;
|
||||
/* we get the ID of the tile in the current drawable layers
|
||||
*/
|
||||
tile = map_level->layers[l][current_index];
|
||||
|
||||
/* tile == -1 means nothing to be drawn */
|
||||
if(tile >= 0) {
|
||||
/* get x and y position in the tileset image */
|
||||
xtile = (tile % map_level->tileset_size) * T_WIDTH;
|
||||
ytile = (tile / map_level->tileset_size) * T_HEIGHT;
|
||||
/* render */
|
||||
dsubimage(x * T_WIDTH - mx, y * T_HEIGHT - my,
|
||||
map_level->tileset, xtile, ytile, T_WIDTH,
|
||||
T_HEIGHT, DIMAGE_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_render_by_layer(Game *game, int layer) {
|
||||
|
||||
Map *map_level = game->map_level;
|
||||
|
|
120
src/npc.c
120
src/npc.c
|
@ -4,6 +4,7 @@
|
|||
#include "dialogs.h"
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
|
||||
#include <gint/display.h>
|
||||
#include <gint/hardware.h>
|
||||
|
@ -20,6 +21,9 @@ extern bopti_image_t tiny_npc_police;
|
|||
NPC npc_stack[NPC_STACK_SIZE];
|
||||
uint32_t npc_count;
|
||||
|
||||
extern const char one_px_mov[8];
|
||||
extern const short int walkable_speed[WALKABLE_TILE_MAX];
|
||||
|
||||
NPC *npc_create() {
|
||||
if(npc_count == NPC_STACK_SIZE)
|
||||
return NULL;
|
||||
|
@ -54,6 +58,33 @@ void npc_remove(NPC *npc) {
|
|||
|
||||
void npc_remove_pos(uint32_t pos) { npc_remove(&npc_stack[pos]); }
|
||||
|
||||
/*Takes input in curx/cury*/
|
||||
bool npc_collision(Game *game, NPC *npc, int32_t dx, int32_t dy) {
|
||||
/* Handle a negative position differently than a positive one. */
|
||||
if(dx < 0)
|
||||
dx = dx / T_WIDTH - 1;
|
||||
else
|
||||
dx = dx / T_WIDTH;
|
||||
|
||||
if(dy < 0)
|
||||
dy = dy / T_HEIGHT - 1;
|
||||
else
|
||||
dy = dy / T_HEIGHT;
|
||||
|
||||
int on_walkable = map_get_walkable(game, dx, dy);
|
||||
|
||||
int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX)
|
||||
? walkable_speed[on_walkable]
|
||||
: 0;
|
||||
|
||||
/* if he's on a hard tile */
|
||||
if(!speed) {
|
||||
return true; /* He will collide with it. */
|
||||
}
|
||||
|
||||
return false; /* He won't collide with a hard tile. */
|
||||
}
|
||||
|
||||
float length(float x, float y) { return sqrtf(x * x + y * y); }
|
||||
|
||||
int npc_clear_path(NPC *npc) {
|
||||
|
@ -73,7 +104,7 @@ int npc_clear_path(NPC *npc) {
|
|||
npc->owns_path = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Takes input as absolute pixel position (/PXSIZE)*/
|
||||
int npc_append_path(int16_t x, int16_t y, NPC *npc) {
|
||||
npc->xpath = realloc(npc->xpath, npc->path_length * 2 + 2);
|
||||
npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
|
||||
|
@ -91,7 +122,8 @@ void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
|
|||
free(fscore);
|
||||
}
|
||||
|
||||
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc){
|
||||
/*Takes input as pixel position*/
|
||||
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
||||
uint8_t *map = full_map->walkable;
|
||||
uint32_t w = full_map->w;
|
||||
uint32_t h = full_map->h;
|
||||
|
@ -100,10 +132,11 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc){
|
|||
dest_x /= PXSIZE;
|
||||
dest_y /= PXSIZE;
|
||||
|
||||
if(dest_x < 0 || dest_y < 0 || dest_x >= w*T_WIDTH || dest_y >= h*T_HEIGHT)
|
||||
if(dest_x < 0 || dest_y < 0 || dest_x >= w * T_WIDTH ||
|
||||
dest_y >= h * T_HEIGHT)
|
||||
return 2;
|
||||
|
||||
/*if(map[dest_y*w + dest_x])
|
||||
/*if(map[(dest_y/T_HEIGHT)*w + dest_x/T_WIDTH])
|
||||
return 2;
|
||||
if(map[sy*w + sx])
|
||||
return 2;*/
|
||||
|
@ -111,24 +144,7 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc){
|
|||
if(!npc->owns_path || npc->path_length > 64)
|
||||
npc_clear_path(npc);
|
||||
|
||||
/*int bx;
|
||||
int by;
|
||||
int bscore = 0x7FFFFFFF;
|
||||
|
||||
for(int i = sx-1; i < sx+2; i++){
|
||||
for(int j = sy-1; j < sy+2; j++){
|
||||
int tscore = (dest_x-sx)*(dest_x-sx) + (dest_y-sy)*(dest_y-sy);
|
||||
if(tscore < bscore){
|
||||
bscore = tscore;
|
||||
bx = i;
|
||||
by = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bscore == 0x7FFFFFFF) return 3;*/
|
||||
|
||||
if(npc_append_path(dest_x,dest_y, npc))
|
||||
if(npc_append_path(dest_x, dest_y, npc))
|
||||
return 1;
|
||||
|
||||
npc->hasPath = true;
|
||||
|
@ -146,16 +162,16 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t start,
|
|||
int x, y;
|
||||
|
||||
for(i = 0; i < PATHFIND_MAX_ITER; i++) {
|
||||
x = ((prev%w)*T_WIDTH + T_WIDTH/2) << PRECISION;
|
||||
y = ((prev/w)*T_HEIGHT + T_HEIGHT/2) << PRECISION;
|
||||
if(npc_append_path(x,y,npc)) {
|
||||
x = ((prev % w) * T_WIDTH + T_WIDTH / 2) << PRECISION;
|
||||
y = ((prev / w) * T_HEIGHT + T_HEIGHT / 2) << PRECISION;
|
||||
if(npc_append_path(x, y, npc)) {
|
||||
goto as_recons_fail;
|
||||
}
|
||||
prev = came_from[prev];
|
||||
if(prev == start){
|
||||
x = ((prev%w)*T_WIDTH + T_WIDTH/2) << PRECISION;
|
||||
y = ((prev/w)*T_HEIGHT + T_HEIGHT/2) << PRECISION;
|
||||
if(npc_append_path(x,y,npc))
|
||||
if(prev == start) {
|
||||
x = ((prev % w) * T_WIDTH + T_WIDTH / 2) << PRECISION;
|
||||
y = ((prev / w) * T_HEIGHT + T_HEIGHT / 2) << PRECISION;
|
||||
if(npc_append_path(x, y, npc))
|
||||
goto as_recons_fail;
|
||||
break;
|
||||
}
|
||||
|
@ -198,8 +214,8 @@ uint32_t xyram = 0xe500e000 + 32;
|
|||
int __npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
||||
int32_t i, j;
|
||||
|
||||
int32_t w = full_map->w/T_WIDTH/PXSIZE;
|
||||
int32_t h = full_map->h/T_HEIGHT/PXSIZE;
|
||||
int32_t w = full_map->w / T_WIDTH / PXSIZE;
|
||||
int32_t h = full_map->h / T_HEIGHT / PXSIZE;
|
||||
int32_t x = (npc->curx >> PRECISION) / T_WIDTH;
|
||||
int32_t y = (npc->cury >> PRECISION) / T_HEIGHT;
|
||||
dest_x /= T_WIDTH;
|
||||
|
@ -286,7 +302,8 @@ int __npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
bscore = fscore[i];
|
||||
}
|
||||
if(bx == dest_x && by == dest_y) {
|
||||
if(is_alloc) as_clean(visited, gscore, fscore);
|
||||
if(is_alloc)
|
||||
as_clean(visited, gscore, fscore);
|
||||
return 0; /*as_reconstruct_path(came_from, w, h, spos,
|
||||
dest_y * w + dest_x, is_alloc npc)*/
|
||||
}
|
||||
|
@ -318,7 +335,7 @@ int __npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
}
|
||||
}
|
||||
|
||||
if(is_alloc){
|
||||
if(is_alloc) {
|
||||
as_clean(visited, gscore, fscore);
|
||||
free(came_from);
|
||||
}
|
||||
|
@ -329,17 +346,19 @@ int __npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
void update_npcs(Game *game) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < game->map_level->nbNPC; i++) {
|
||||
update_npc(&game->map_level->npcs[i]);
|
||||
update_npc(&game->map_level->npcs[i], game);
|
||||
}
|
||||
for(i = 0; i < npc_count; i++) {
|
||||
update_npc(&npc_stack[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]);
|
||||
game->mana = npc_pathfind(game->player.x, game->player.y,
|
||||
game->map_level, &npc_stack[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void update_npc(NPC *npc) {
|
||||
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->hasPath || npc->paused == true)
|
||||
return;
|
||||
|
@ -358,8 +377,29 @@ void update_npc(NPC *npc) {
|
|||
npc->currentPoint = npc->currentPoint % npc->path_length;
|
||||
}
|
||||
|
||||
npc->curx += vecX * (float)(1 << PRECISION);
|
||||
npc->cury += vecY * (float)(1 << PRECISION);
|
||||
int32_t new_x = npc->curx + (vecX * (float)(1 << PRECISION));
|
||||
int32_t new_y = npc->cury + (vecY * (float)(1 << PRECISION));
|
||||
|
||||
/*If the NPC has a static path, let him do as he wants*/
|
||||
if(!npc->owns_path) {
|
||||
npc->curx = new_x;
|
||||
npc->cury = new_y;
|
||||
return;
|
||||
}
|
||||
/*Otherwise check if he is colliding*/
|
||||
|
||||
/*Pos in tiles*/
|
||||
int32_t mpos_x = new_x;
|
||||
if(vecX > 0)
|
||||
mpos_x += 1 << PRECISION;
|
||||
int32_t mpos_y = new_y;
|
||||
if(vecY > 0)
|
||||
mpos_y += 1 << PRECISION;
|
||||
|
||||
if(!npc_collision(game, npc, mpos_x, mpos_x)) {
|
||||
npc->curx = new_x;
|
||||
npc->cury = new_y;
|
||||
}
|
||||
}
|
||||
|
||||
bopti_image_t *npc_sprites[FACES] = {&tiny_npc_male, &tiny_npc_female,
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
/*Maximum iterations before the pathfinding considers the target unreacheable*/
|
||||
#define PATHFIND_MAX_ITER 64
|
||||
|
||||
#define npc_from_curxy(a) (((a)>>PRECISION)/PXSIZE)
|
||||
/*The following macros take a curx/y format int, and convert them
|
||||
*to and from absolute pixel positon (pixel position/ PXSIZE)*/
|
||||
#define npc_from_curxy(a) (((a) >> PRECISION) / PXSIZE)
|
||||
|
||||
#define npc_to_curxy(a) (((a)*PXSIZE)<<PRECISION)
|
||||
#define npc_to_curxy(a) (((a)*PXSIZE) << PRECISION)
|
||||
|
||||
enum {
|
||||
|
||||
|
@ -59,7 +61,7 @@ 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 update_npc(NPC *npc, Game *game);
|
||||
/* Inits/Clears the NPC stack*/
|
||||
void npc_reload(Game *game);
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ const char one_px_mov[8] = {
|
|||
/* TODO: Search for all hard tiles in the tileset. hard_tiles is a list of their
|
||||
* IDs */
|
||||
/* The speed of the player on the diffrent tiles in the walkable layer. */
|
||||
#define WALKABLE_TILE_MAX 4
|
||||
const short int walkable_speed[WALKABLE_TILE_MAX] = {SPEED, 0, PXSIZE, PXSIZE};
|
||||
|
||||
/* How much damage the player takes on the diffrent tiles in the walkable
|
||||
|
|
|
@ -14,6 +14,8 @@ typedef struct {
|
|||
|
||||
#define FACES 4
|
||||
|
||||
#define WALKABLE_TILE_MAX 4
|
||||
|
||||
/* Structure 'Player' has been moved to game.h */
|
||||
/* to avoid circular references between map.h, game.h and player.h */
|
||||
/* only methods propotypes are now in dedicated header files */
|
||||
|
|
Loading…
Reference in a new issue