fp: Add debug visualisation for A*
This commit is contained in:
parent
38410073cf
commit
9106230079
@ -605,9 +605,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
||||
// NOTE: Stalk entity ======================================================================
|
||||
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||
{
|
||||
Dqn_Profiler_ZoneScopeWithIndex("FP_Update: Path finding", FP_ProfileZone_FPUpdate_PathFinding);
|
||||
FP_GameEntity *stalk_entity = FP_Game_GetEntity(game, entity->stalk_entity);
|
||||
if (stalk_entity->handle.id) {
|
||||
Dqn_Profiler_ZoneScopeWithIndex("FP_Update: Path finding", FP_ProfileZone_FPUpdate_PathFinding);
|
||||
Dqn_V2 stalk_world_pos = FP_Game_CalcEntityWorldPos(game, stalk_entity->handle);
|
||||
Dqn_V2I stalk_tile = Dqn_V2I_InitNx2(stalk_world_pos.x / game->tile_size, stalk_world_pos.y / game->tile_size);
|
||||
if (entity->stalk_entity_last_known_tile != stalk_tile) {
|
||||
|
@ -8,6 +8,10 @@ enum FP_ProfileZone
|
||||
FP_ProfileZone_FPUpdate = TELY_ProfileZone_Count,
|
||||
FP_ProfileZone_FPUpdate_EntityLoop,
|
||||
FP_ProfileZone_FPUpdate_PathFinding,
|
||||
FP_ProfileZone_FPUpdate_AStar,
|
||||
FP_ProfileZone_FPUpdate_AStarEnumerateCollidables,
|
||||
FP_ProfileZone_FPUpdate_AStarExpand,
|
||||
FP_ProfileZone_FPUpdate_AStarExploreNeighbours,
|
||||
FP_ProfileZone_FPUpdate_Attacks,
|
||||
FP_ProfileZone_FPRender,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -167,6 +167,7 @@ struct FP_GameAStarNode
|
||||
{
|
||||
Dqn_usize cost;
|
||||
Dqn_usize heuristic;
|
||||
Dqn_V2I tile;
|
||||
Dqn_V2I came_from;
|
||||
bool non_traversable;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user