fp: Add debug visualisation for A*
This commit is contained in:
+26
-5
@@ -468,10 +468,20 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
FP_GameEntityHandle entity,
|
||||
Dqn_V2I dest_tile)
|
||||
{
|
||||
Dqn_Profiler_ZoneScopeWithIndex("FP_Update: A*", FP_ProfileZone_FPUpdate_AStar);
|
||||
Dqn_usize tile_count_x = DQN_CAST(Dqn_usize)(platform->core.window_size.w / game->tile_size);
|
||||
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(platform->core.window_size.h / game->tile_size);
|
||||
|
||||
Dqn_Slice<Dqn_V2I> result = {};
|
||||
if (dest_tile.x < 0 || dest_tile.x > tile_count_x ||
|
||||
dest_tile.y < 0 || dest_tile.y > tile_count_y)
|
||||
return result;
|
||||
|
||||
Dqn_DSMap<FP_GameAStarNode> astar_info = Dqn_DSMap_Init<FP_GameAStarNode>(128);
|
||||
DQN_DEFER { Dqn_DSMap_Deinit(&astar_info); };
|
||||
|
||||
// NOTE: Enumerate the entities that are collidable ============================================
|
||||
auto zone_enum_collidables = Dqn_Profiler_BeginZoneWithIndex(DQN_STRING8("FP_Update: A* enumerate collidables"), FP_ProfileZone_FPUpdate_AStarEnumerateCollidables);
|
||||
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->root_entity); ) {
|
||||
FP_GameEntity const *walk_entity = it.entity;
|
||||
if (entity == walk_entity->handle)
|
||||
@@ -491,9 +501,11 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
uint64_t tile_u64 = (DQN_CAST(uint64_t)y << 32) | (DQN_CAST(uint64_t)x << 0);
|
||||
FP_GameAStarNode *node = Dqn_DSMap_MakeKeyU64(&astar_info, tile_u64).value;
|
||||
node->non_traversable = true;
|
||||
node->tile = Dqn_V2I_InitNx2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
Dqn_Profiler_EndZone(zone_enum_collidables);
|
||||
|
||||
// NOTE: Setup A* state ========================================================================
|
||||
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity);
|
||||
@@ -502,18 +514,17 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
Dqn_FArray<Dqn_V2I, 128> frontier = {};
|
||||
Dqn_FArray_Add(&frontier, src_tile);
|
||||
|
||||
Dqn_usize tile_count_x = DQN_CAST(Dqn_usize)(platform->core.window_size.w / game->tile_size);
|
||||
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(platform->core.window_size.h / game->tile_size);
|
||||
|
||||
// NOTE: Initialise the starting cost
|
||||
uint64_t src_tile_u64 = (DQN_CAST(uint64_t)src_tile.y << 32) | (DQN_CAST(uint64_t)src_tile.x << 0);
|
||||
Dqn_DSMap_MakeKeyU64(&astar_info, src_tile_u64);
|
||||
Dqn_DSMap_MakeKeyU64(&astar_info, src_tile_u64).value->tile = src_tile;
|
||||
|
||||
// NOTE: Do the A* process =====================================================================
|
||||
Dqn_usize last_successful_manhattan_dist = UINT64_MAX;
|
||||
Dqn_V2I last_successful_tile = src_tile;
|
||||
|
||||
auto zone_astar_expand = Dqn_Profiler_BeginZoneWithIndex(DQN_STRING8("FP_Update: A* expand"), FP_ProfileZone_FPUpdate_AStarExpand);
|
||||
while (frontier.size) {
|
||||
Dqn_Profiler_ZoneScopeWithIndex("FP_Update: A* neighbours", FP_ProfileZone_FPUpdate_AStarExploreNeighbours);
|
||||
Dqn_V2I curr_tile = Dqn_FArray_PopFront(&frontier, 1);
|
||||
if (curr_tile == dest_tile)
|
||||
break;
|
||||
@@ -543,6 +554,7 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
Dqn_usize new_cost = curr_cost + 1;
|
||||
uint64_t next_tile_u64 = (DQN_CAST(uint64_t)next_tile.y << 32) | (DQN_CAST(uint64_t)next_tile.x << 0);
|
||||
Dqn_DSMapResult<FP_GameAStarNode> next_cost_result = Dqn_DSMap_MakeKeyU64(&astar_info, next_tile_u64);
|
||||
next_cost_result.value->tile = next_tile;
|
||||
|
||||
if (next_cost_result.value->non_traversable)
|
||||
continue;
|
||||
@@ -585,6 +597,15 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
Dqn_FArray_Add(&frontier, next_tile);
|
||||
}
|
||||
}
|
||||
Dqn_Profiler_EndZone(zone_astar_expand);
|
||||
|
||||
TELY_Renderer *renderer = &platform->renderer;
|
||||
for (uint32_t old_index = 1 /*Sentinel*/; old_index < astar_info.occupied; old_index++) {
|
||||
Dqn_DSMapSlot<FP_GameAStarNode> const *slot = astar_info.slots + old_index;
|
||||
FP_GameAStarNode const *node = &slot->value;
|
||||
Dqn_V2 pos = FP_Game_TilePosToWorldPos(game, node->tile) + (game->tile_size * .5f);
|
||||
TELY_Render_CircleColourV4(renderer, pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_BLUE_CADET_V4);
|
||||
}
|
||||
|
||||
Dqn_usize slice_size = 0;
|
||||
for (Dqn_V2I it = last_successful_tile; it != src_tile; slice_size++) {
|
||||
@@ -592,7 +613,7 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
||||
it = Dqn_DSMap_FindKeyU64(&astar_info, key_u64).value->came_from;
|
||||
}
|
||||
|
||||
Dqn_Slice<Dqn_V2I> result = Dqn_Slice_Alloc<Dqn_V2I>(arena, slice_size, Dqn_ZeroMem_No);
|
||||
result = Dqn_Slice_Alloc<Dqn_V2I>(arena, slice_size, Dqn_ZeroMem_No);
|
||||
slice_size = 0;
|
||||
for (Dqn_V2I it = last_successful_tile; it != src_tile; ) {
|
||||
result.data[slice_size++] = it;
|
||||
|
||||
Reference in New Issue
Block a user