mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 02:48:14 +03:00
DrawDungeon2: Implement pathfinding functions
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user