diff --git a/feely_pona.cpp b/feely_pona.cpp index 1276ee7..ea74930 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -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) { diff --git a/feely_pona.h b/feely_pona.h index df4b921..db6fd58 100644 --- a/feely_pona.h +++ b/feely_pona.h @@ -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, }; diff --git a/feely_pona_game.cpp b/feely_pona_game.cpp index 354d252..06f8e0c 100644 --- a/feely_pona_game.cpp +++ b/feely_pona_game.cpp @@ -468,10 +468,20 @@ static Dqn_Slice 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 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 astar_info = Dqn_DSMap_Init(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 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 FP_Game_AStarPathFind(FP_Game *game, Dqn_FArray 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 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 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 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 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 FP_Game_AStarPathFind(FP_Game *game, it = Dqn_DSMap_FindKeyU64(&astar_info, key_u64).value->came_from; } - Dqn_Slice result = Dqn_Slice_Alloc(arena, slice_size, Dqn_ZeroMem_No); + result = Dqn_Slice_Alloc(arena, slice_size, Dqn_ZeroMem_No); slice_size = 0; for (Dqn_V2I it = last_successful_tile; it != src_tile; ) { result.data[slice_size++] = it; diff --git a/feely_pona_game.h b/feely_pona_game.h index 34f4649..190c462 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -167,6 +167,7 @@ struct FP_GameAStarNode { Dqn_usize cost; Dqn_usize heuristic; + Dqn_V2I tile; Dqn_V2I came_from; bool non_traversable; };