DrawDungeon2: Implement pathfinding functions

This commit is contained in:
kichikuou
2025-07-14 20:51:44 +09:00
parent 3c7634522a
commit fbd105b697
5 changed files with 74 additions and 4 deletions
+2
View File
@@ -91,6 +91,7 @@ struct dgn_cell {
int32_t south_event2;
int32_t east_event2;
int32_t west_event2;
int pathfinding_cost;
struct dgn_cell **visible_cells;
};
@@ -139,5 +140,6 @@ static inline bool dgn_is_in_map(struct dgn *dgn, uint32_t x, uint32_t y, uint32
struct dgn_cell **dgn_get_visible_cells(struct dgn *dgn, int x, int y, int z, int *nr_cells_out);
struct dgn *dgn_generate_drawdungeon2(int level);
void dgn_paint_step(struct dgn *dgn, int x, int y);
#endif /* SYSTEM4_DGN_H */
+1
View File
@@ -76,6 +76,7 @@ void dungeon_set_walked_all(int surface);
int dungeon_calc_conquer(int surface);
bool dungeon_load_walk_data(int surface, int map, struct page **page);
bool dungeon_save_walk_data(int surface, int map, struct page **page);
void dungeon_paint_step(int surface, int x, int y, int z);
struct dungeon_context *dungeon_get_context(int surface);
+60
View File
@@ -559,6 +559,7 @@ struct dgn *dgn_generate_drawdungeon2(int level)
cell->roof_orientation = -1;
cell->roof_texture = -1;
cell->roof_underside_texture = -1;
cell->pathfinding_cost = -1;
if (map[x][z] == '#') {
continue;
@@ -593,3 +594,62 @@ struct dgn *dgn_generate_drawdungeon2(int level)
}
return dgn;
}
// Set pathfinding_cost for each cell on the shortest path to the exit cell
void dgn_paint_step(struct dgn *dgn, int start_x, int start_y)
{
int nr_cells = dgn_nr_cells(dgn);
for (int i = 0; i < nr_cells; i++) {
dgn->cells[i].pathfinding_cost = -1;
}
// BFS.
short dist[DD2_MAP_WIDTH][DD2_MAP_HEIGHT] = {0};
struct { int8_t x, y; } prev[DD2_MAP_WIDTH][DD2_MAP_HEIGHT];
struct point_list queue = {0};
int queue_ptr = 0;
dist[start_x][start_y] = 1;
point_list_add(&queue, start_x, start_y);
while (queue_ptr < queue.size) {
int cx = queue.p[queue_ptr].x;
int cy = queue.p[queue_ptr].y;
if (cx == dgn->exit_x && cy == dgn->exit_y)
break;
queue_ptr++;
// Add adjacent cells to the queue
const int dx_offsets[] = {0, 0, -1, 1};
const int dy_offsets[] = {-1, 1, 0, 0};
for (int i = 0; i < 4; i++) {
int nx = cx + dx_offsets[i];
int ny = cy + dy_offsets[i];
if (nx >= 0 && nx < DD2_MAP_WIDTH && ny >= 0 && ny < DD2_MAP_HEIGHT &&
!dist[nx][ny] && dgn->cells[dgn_cell_index(dgn, nx, 0, ny)].floor >= 0) {
dist[nx][ny] = dist[cx][cy] + 1;
prev[nx][ny].x = cx;
prev[nx][ny].y = cy;
point_list_add(&queue, nx, ny);
}
}
}
if (queue_ptr >= queue.size) {
// The exit is not reachable from the start (should not happen)
return;
}
// Backtrack from the exit to the start to paint the path
int x = dgn->exit_x;
int y = dgn->exit_y;
for (;;) {
struct dgn_cell *cell = &dgn->cells[dgn_cell_index(dgn, x, 0, y)];
cell->pathfinding_cost = dist[x][y] - 1; // -1 to make the start cell 0
if (x == start_x && y == start_y)
break;
int px = prev[x][y].x;
int py = prev[x][y].y;
x = px;
y = py;
}
}
+8
View File
@@ -567,6 +567,14 @@ bool dungeon_save_walk_data(int surface, int map, struct page **page)
}
}
void dungeon_paint_step(int surface, int x, int y, int z)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return;
dgn_paint_step(ctx->dgn, x, z);
}
static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose)
{
cJSON *obj, *cam;
+3 -4
View File
@@ -413,16 +413,15 @@ static void DrawDungeon2_GetExitPos(int surface, int *x, int *y)
*y = ctx->dgn->exit_y;
}
//void DrawDungeon2_PaintStep(int nSurface, int nX, int nY, int nZ);
//int DrawDungeon2_GetMapStep(int nSurface, int nX, int nY, int nZ);
CELL_GETTER(DrawDungeon2_GetMapStep, -1, cell->pathfinding_cost);
HLL_LIBRARY(DrawDungeon2,
HLL_EXPORT(Init, DrawDungeon2_Init),
DRAW_DUNGEON_EXPORTS,
HLL_EXPORT(GetPlayerStartPos, DrawDungeon2_GetPlayerStartPos),
HLL_EXPORT(GetExitPos, DrawDungeon2_GetExitPos),
HLL_TODO_EXPORT(PaintStep, DrawDungeon2_PaintStep),
HLL_TODO_EXPORT(GetMapStep, DrawDungeon2_GetMapStep)
HLL_EXPORT(PaintStep, dungeon_paint_step),
HLL_EXPORT(GetMapStep, DrawDungeon2_GetMapStep)
);
static void DrawDungeon14_SetRasterScroll(int surface, int type)