fp: First draft swarming on entity
This commit is contained in:
parent
9fde0594e1
commit
3829a2bdc9
@ -880,35 +880,54 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
if (closest_terry_dist < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 2.f))) {
|
if (closest_terry_dist < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 2.f))) {
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
|
FP_SentinelListLink<FP_GameWaypoint> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
|
||||||
if (first_waypoint->data.entity != closest_terry->handle) {
|
if (first_waypoint->data.entity != closest_terry->handle) {
|
||||||
|
|
||||||
|
FP_GameDirection aggro_direction = FP_GameDirection_Count;
|
||||||
|
DQN_FOR_UINDEX(dir_index, FP_GameDirection_Count) {
|
||||||
|
FP_GameEntityHandle slot_entity_handle = closest_terry->aggro_slot[dir_index];
|
||||||
|
FP_GameEntity *slot_entity = FP_Game_GetEntity(game, slot_entity_handle);
|
||||||
|
if (FP_Game_IsNilEntity(slot_entity)) {
|
||||||
|
aggro_direction = DQN_CAST(FP_GameDirection)dir_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
|
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
|
||||||
link->data.entity = closest_terry->handle;
|
FP_GameWaypoint *waypoint = &link->data;
|
||||||
|
waypoint->entity = closest_terry->handle;
|
||||||
|
|
||||||
|
if (aggro_direction != FP_GameDirection_Count) {
|
||||||
|
waypoint->type = FP_GameWaypointType_Side;
|
||||||
|
waypoint->type_direction = aggro_direction;
|
||||||
|
closest_terry->aggro_slot[aggro_direction] = entity->handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (entity->waypoints.size) {
|
while (entity->waypoints.size) {
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *waypoint_link = entity->waypoints.sentinel->next;
|
FP_SentinelListLink<FP_GameWaypoint> *waypoint_link = entity->waypoints.sentinel->next;
|
||||||
FP_GameEntity *waypoint = FP_Game_GetEntity(game, waypoint_link->data.entity);
|
FP_GameWaypoint const *waypoint = &waypoint_link->data;
|
||||||
if (FP_Game_IsNilEntity(waypoint)) {
|
FP_GameEntity *waypoint_entity = FP_Game_GetEntity(game, waypoint_link->data.entity);
|
||||||
|
if (FP_Game_IsNilEntity(waypoint_entity)) {
|
||||||
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
|
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: We found a waypoint that is valid to move towards
|
// NOTE: We found a waypoint that is valid to move towards
|
||||||
Dqn_V2 waypoint_pos = FP_Game_CalcEntityWorldPos(game, waypoint->handle);
|
Dqn_V2 target_pos = FP_Game_CalcWaypointWorldPos(game, waypoint);
|
||||||
Dqn_V2 entity_to_waypoint = waypoint_pos - entity_pos;
|
Dqn_V2 entity_to_waypoint = target_pos - entity_pos;
|
||||||
|
|
||||||
// NOTE: Check if we've arrived at the waypoint
|
// NOTE: Check if we've arrived at the waypoint
|
||||||
Dqn_f32 dist_to_waypoint_sq = Dqn_V2_LengthSq(entity_to_waypoint);
|
Dqn_f32 dist_to_waypoint_sq = Dqn_V2_LengthSq(entity_to_waypoint);
|
||||||
|
|
||||||
Dqn_f32 arrival_threshold = {};
|
Dqn_f32 arrival_threshold = {};
|
||||||
switch (waypoint_link->data.arrive) {
|
switch (waypoint->arrive) {
|
||||||
case FP_GameWaypointArrive_Default: {
|
case FP_GameWaypointArrive_Default: {
|
||||||
arrival_threshold = FP_Game_MetersToPixelsNx1(game, 1.f);
|
arrival_threshold = FP_Game_MetersToPixelsNx1(game, 1.f);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameWaypointArrive_WhenWithinEntitySize: {
|
case FP_GameWaypointArrive_WhenWithinEntitySize: {
|
||||||
arrival_threshold = DQN_MAX(waypoint->local_hit_box_size.w, waypoint->local_hit_box_size.h) * waypoint_link->data.value;
|
arrival_threshold = DQN_MAX(waypoint_entity->local_hit_box_size.w, waypoint_entity->local_hit_box_size.h) * waypoint_link->data.value;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +939,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: We have arrived at the waypoint
|
// NOTE: We have arrived at the waypoint
|
||||||
if ((entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint->type == FP_EntityType_Terry) {
|
if ((entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry) {
|
||||||
// NOTE: We had a waypoint to move to Terry because he has
|
// NOTE: We had a waypoint to move to Terry because he has
|
||||||
// drawn our aggro and we've arrived at Terry
|
// drawn our aggro and we've arrived at Terry
|
||||||
|
|
||||||
@ -1330,6 +1349,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
|||||||
TELY_Render_TextureColourV4(renderer, sprite->asset.sheet->tex_handle, src_rect, dest_rect, TELY_COLOUR_WHITE_V4);
|
TELY_Render_TextureColourV4(renderer, sprite->asset.sheet->tex_handle, src_rect, dest_rect, TELY_COLOUR_WHITE_V4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Render waypoint entities ==========================================================
|
||||||
if (entity->flags & FP_GameEntityFlag_MobSpawner) {
|
if (entity->flags & FP_GameEntityFlag_MobSpawner) {
|
||||||
Dqn_V2 start = world_pos;
|
Dqn_V2 start = world_pos;
|
||||||
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
|
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
|
||||||
@ -1357,19 +1377,12 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
|||||||
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4);
|
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4);
|
||||||
|
|
||||||
// NOTE: Draw the waypoints that the entity is moving along
|
// NOTE: Draw the waypoints that the entity is moving along
|
||||||
if (entity->waypoints.size) {
|
|
||||||
Dqn_V2 start = world_pos;
|
Dqn_V2 start = world_pos;
|
||||||
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate(&entity->waypoints, &link); ) {
|
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate(&entity->waypoints, &link); ) {
|
||||||
FP_GameEntity *waypoint = FP_Game_GetEntity(game, link->data.entity);
|
Dqn_V2 end = FP_Game_CalcWaypointWorldPos(game, &link->data);
|
||||||
if (FP_Game_IsNilEntity(waypoint))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Dqn_V2 end = FP_Game_CalcEntityWorldPos(game, waypoint->handle);
|
|
||||||
TELY_Render_LineColourV4(renderer, start, end, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4, 2.f);
|
TELY_Render_LineColourV4(renderer, start, end, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4, 2.f);
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else if (game->hot_entity == entity->handle || (entity->flags & FP_GameEntityFlag_DrawHitBox)) {
|
} else if (game->hot_entity == entity->handle || (entity->flags & FP_GameEntityFlag_DrawHitBox)) {
|
||||||
Dqn_V4 hot_colour = game->hot_entity == entity->handle ? TELY_COLOUR_RED_TOMATO_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_YELLOW_SANDY_V4, .5f);
|
Dqn_V4 hot_colour = game->hot_entity == entity->handle ? TELY_COLOUR_RED_TOMATO_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_YELLOW_SANDY_V4, .5f);
|
||||||
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, hot_colour);
|
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, hot_colour);
|
||||||
|
@ -630,3 +630,48 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
|||||||
DQN_ASSERT(result.size == slice_size);
|
DQN_ASSERT(result.size == slice_size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameWaypoint const *waypoint)
|
||||||
|
{
|
||||||
|
Dqn_V2 result = {};
|
||||||
|
if (!game || !waypoint)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
FP_GameEntity *waypoint_entity = FP_Game_GetEntity(game, waypoint->entity);
|
||||||
|
if (FP_Game_IsNilEntity(waypoint_entity))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// NOTE: We found a waypoint that is valid to move towards
|
||||||
|
switch (waypoint->type) {
|
||||||
|
case FP_GameWaypointType_At: {
|
||||||
|
result = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameWaypointType_Side: {
|
||||||
|
Dqn_Rect entity_rect = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
||||||
|
switch (waypoint->type_direction) {
|
||||||
|
case FP_GameDirection_Up: {
|
||||||
|
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y - entity_rect.size.h * .5f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Down: {
|
||||||
|
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h + (entity_rect.size.h * .5f));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Left: {
|
||||||
|
result = Dqn_V2_InitNx2(entity_rect.pos.x - entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Right: {
|
||||||
|
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +63,25 @@ enum FP_GameWaypointArrive
|
|||||||
FP_GameWaypointArrive_WhenWithinEntitySize,
|
FP_GameWaypointArrive_WhenWithinEntitySize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FP_GameWaypointType
|
||||||
|
{
|
||||||
|
FP_GameWaypointType_At, // Move to the specified entity
|
||||||
|
FP_GameWaypointType_Side, // Move to the side of the entity specified by the direction
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FP_GameDirection
|
||||||
|
{
|
||||||
|
FP_GameDirection_Up,
|
||||||
|
FP_GameDirection_Down,
|
||||||
|
FP_GameDirection_Left,
|
||||||
|
FP_GameDirection_Right,
|
||||||
|
FP_GameDirection_Count,
|
||||||
|
};
|
||||||
|
|
||||||
struct FP_GameWaypoint
|
struct FP_GameWaypoint
|
||||||
{
|
{
|
||||||
|
FP_GameWaypointType type;
|
||||||
|
FP_GameDirection type_direction;
|
||||||
FP_GameEntityHandle entity;
|
FP_GameEntityHandle entity;
|
||||||
FP_GameWaypointArrive arrive;
|
FP_GameWaypointArrive arrive;
|
||||||
Dqn_f32 value;
|
Dqn_f32 value;
|
||||||
@ -93,14 +110,6 @@ struct FP_GameEntityAction
|
|||||||
uint64_t end_at_clock_ms;
|
uint64_t end_at_clock_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FP_GameDirection
|
|
||||||
{
|
|
||||||
FP_GameDirection_Up,
|
|
||||||
FP_GameDirection_Down,
|
|
||||||
FP_GameDirection_Left,
|
|
||||||
FP_GameDirection_Right,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FP_GameRenderSprite
|
struct FP_GameRenderSprite
|
||||||
{
|
{
|
||||||
Dqn_V2 offset;
|
Dqn_V2 offset;
|
||||||
@ -134,6 +143,7 @@ struct FP_GameEntity
|
|||||||
Dqn_FArray<FP_GameRenderSprite, 2> extra_cosmetic_anims;
|
Dqn_FArray<FP_GameRenderSprite, 2> extra_cosmetic_anims;
|
||||||
|
|
||||||
FP_SentinelList<FP_GameWaypoint> waypoints;
|
FP_SentinelList<FP_GameWaypoint> waypoints;
|
||||||
|
FP_GameEntityHandle aggro_slot[FP_GameDirection_Count];
|
||||||
|
|
||||||
// NOTE: The entity hit box is positioned at the center of the entity.
|
// NOTE: The entity hit box is positioned at the center of the entity.
|
||||||
Dqn_V2 local_hit_box_size;
|
Dqn_V2 local_hit_box_size;
|
||||||
|
Loading…
Reference in New Issue
Block a user