fp: Implement the plane
This commit is contained in:
parent
15a591dcb7
commit
8ebbb64877
@ -160,6 +160,7 @@ static void FP_Game_MoveEntity(FP_Game *game, FP_GameEntityHandle entity_handle,
|
|||||||
Dqn_f32 global_earliest_t = SENTINEL_T;
|
Dqn_f32 global_earliest_t = SENTINEL_T;
|
||||||
Dqn_V2 global_earliest_pos_just_before_collide = {};
|
Dqn_V2 global_earliest_pos_just_before_collide = {};
|
||||||
|
|
||||||
|
if ((entity->flags & FP_GameEntityFlag_NoClip) == 0) {
|
||||||
for (FP_GameEntityIterator collider_it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &collider_it, game->root_entity); ) {
|
for (FP_GameEntityIterator collider_it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &collider_it, game->root_entity); ) {
|
||||||
FP_GameEntity *collider = collider_it.entity;
|
FP_GameEntity *collider = collider_it.entity;
|
||||||
if (collider->handle == entity->handle)
|
if (collider->handle == entity->handle)
|
||||||
@ -267,6 +268,8 @@ static void FP_Game_MoveEntity(FP_Game *game, FP_GameEntityHandle entity_handle,
|
|||||||
global_earliest_pos_just_before_collide = entity_pos + (d * earliest_t);
|
global_earliest_pos_just_before_collide = entity_pos + (d * earliest_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (global_earliest_t == SENTINEL_T) {
|
if (global_earliest_t == SENTINEL_T) {
|
||||||
entity->local_pos += delta_pos;
|
entity->local_pos += delta_pos;
|
||||||
@ -444,13 +447,14 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FP_Entity_CreateClubTerry(game, Dqn_V2_InitNx2(+500, -191), "Club Terry");
|
FP_Entity_CreateClubTerry(game, Dqn_V2_InitNx2(+500, -191), "Club Terry");
|
||||||
FP_Entity_CreateAirportTerry(game, Dqn_V2_InitNx2(+200, -191), "Airport Terry");
|
|
||||||
FP_Entity_CreateKennelTerry(game, Dqn_V2_InitNx2(-300, -191), "Kennel Terry");
|
FP_Entity_CreateKennelTerry(game, Dqn_V2_InitNx2(-300, -191), "Kennel Terry");
|
||||||
FP_Entity_CreateChurchTerry(game, Dqn_V2_InitNx2(-800, -191), "Church Terry");
|
FP_Entity_CreateChurchTerry(game, Dqn_V2_InitNx2(-800, -191), "Church Terry");
|
||||||
|
FP_Entity_CreateAirportTerry(game, Dqn_V2_InitNx2(-1200, -191), "Airport Terry");
|
||||||
|
|
||||||
game->tile_size = 37;
|
game->tile_size = 37;
|
||||||
Dqn_V2I max_tile = platform->core.window_size / game->tile_size;
|
Dqn_V2I max_tile = platform->core.window_size / game->tile_size;
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Mid lane mob spawner ==================================================================
|
// NOTE: Mid lane mob spawner ==================================================================
|
||||||
Dqn_V2 base_mid_p = Dqn_V2_InitNx2(1580, 0.f);
|
Dqn_V2 base_mid_p = Dqn_V2_InitNx2(1580, 0.f);
|
||||||
Dqn_V2 mid_lane_mob_spawner_pos = Dqn_V2_InitNx2(game->map->local_hit_box_size.w * -0.5f, 0.f);
|
Dqn_V2 mid_lane_mob_spawner_pos = Dqn_V2_InitNx2(game->map->local_hit_box_size.w * -0.5f, 0.f);
|
||||||
@ -460,7 +464,7 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
FP_Game_PushParentEntity(game, mob_spawner);
|
FP_Game_PushParentEntity(game, mob_spawner);
|
||||||
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-mid_lane_mob_spawner_pos.x + base_mid_p.x, base_mid_p.y), "Waypoint");
|
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-mid_lane_mob_spawner_pos.x + base_mid_p.x, base_mid_p.y), "Waypoint");
|
||||||
FP_Game_PopParentEntity(game);
|
FP_Game_PopParentEntity(game);
|
||||||
|
Dqn_FArray_Add(&game->mob_spawners, mob_spawner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Bottom lane spawner ===================================================================
|
// NOTE: Bottom lane spawner ===================================================================
|
||||||
@ -472,6 +476,7 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-bottom_lane_mob_spawner_pos.x + base_mid_p.x, 0.f), "Waypoint");
|
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-bottom_lane_mob_spawner_pos.x + base_mid_p.x, 0.f), "Waypoint");
|
||||||
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-bottom_lane_mob_spawner_pos.x + base_mid_p.x, -932.f), "Waypoint");
|
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-bottom_lane_mob_spawner_pos.x + base_mid_p.x, -932.f), "Waypoint");
|
||||||
FP_Game_PopParentEntity(game);
|
FP_Game_PopParentEntity(game);
|
||||||
|
Dqn_FArray_Add(&game->mob_spawners, mob_spawner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Top lane spawner ===================================================================
|
// NOTE: Top lane spawner ===================================================================
|
||||||
@ -482,6 +487,7 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-top_lane_mob_spawner_pos.x + base_mid_p.x, 0.f), "Waypoint");
|
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-top_lane_mob_spawner_pos.x + base_mid_p.x, 0.f), "Waypoint");
|
||||||
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-top_lane_mob_spawner_pos.x + base_mid_p.x, +915.f), "Waypoint");
|
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(-top_lane_mob_spawner_pos.x + base_mid_p.x, +915.f), "Waypoint");
|
||||||
FP_Game_PopParentEntity(game);
|
FP_Game_PopParentEntity(game);
|
||||||
|
Dqn_FArray_Add(&game->mob_spawners, mob_spawner);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -993,17 +999,63 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished) {
|
if (action_has_finished) {
|
||||||
if (!FP_Game_IsNilEntityHandle(game, entity->building_patron)) {
|
Dqn_V2 world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||||
FP_GameEntity *patron = FP_Game_GetEntity(game, entity->building_patron);
|
FP_GameEntityHandle plane_handle = FP_Entity_CreateAirportTerryPlane(game, world_pos, "Aiport Terry Plane");
|
||||||
patron->flags &= ~FP_GameEntityFlag_OccupiedInBuilding;
|
FP_GameEntity *plane = FP_Game_GetEntity(game, plane_handle);
|
||||||
}
|
|
||||||
|
// NOTE: Transfer the entity to the plane
|
||||||
|
plane->building_patron = entity->building_patron;
|
||||||
entity->building_patron = {};
|
entity->building_patron = {};
|
||||||
|
|
||||||
|
// NOTE: Add a waypoint for the plane to the mob spawn
|
||||||
|
{
|
||||||
|
uint32_t mob_spawner_index = Dqn_PCG32_Range(&game->rng, 0, DQN_CAST(uint32_t)game->mob_spawners.size);
|
||||||
|
FP_GameEntityHandle mob_spawner = game->mob_spawners.data[mob_spawner_index];
|
||||||
|
Dqn_V2 target_pos = FP_Game_CalcEntityWorldPos(game, mob_spawner);
|
||||||
|
plane->waypoints = FP_SentinelList_Init<FP_GameWaypoint>(game->chunk_pool);
|
||||||
|
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&plane->waypoints,
|
||||||
|
FP_SentinelList_Front(&plane->waypoints),
|
||||||
|
game->chunk_pool);
|
||||||
|
FP_GameWaypoint *waypoint = &link->data;
|
||||||
|
waypoint->entity = mob_spawner;
|
||||||
|
waypoint->type = FP_GameWaypointType_ClosestSide;
|
||||||
|
}
|
||||||
|
|
||||||
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryState_Idle);
|
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryState_Idle);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_AirportTerryPlane: {
|
||||||
|
FP_EntityAirportTerryPlaneState *state = DQN_CAST(FP_EntityAirportTerryPlaneState *)&action->state;
|
||||||
|
switch (*state) {
|
||||||
|
case FP_EntityAirportTerryPlaneState_Nil: {
|
||||||
|
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryPlaneState_Idle);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityAirportTerryPlaneState_Idle: {
|
||||||
|
if (entering_new_state) {
|
||||||
|
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||||
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FP_Game_IsNilEntityHandle(game, entity->building_patron))
|
||||||
|
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryPlaneState_FlyPassenger);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityAirportTerryPlaneState_FlyPassenger: {
|
||||||
|
if (entity->waypoints.size == 0) {
|
||||||
|
FP_GameEntity *patron = FP_Game_GetEntity(game, entity->building_patron);
|
||||||
|
patron->local_pos = entity->local_pos;
|
||||||
|
patron->flags &= ~(FP_GameEntityFlag_OccupiedInBuilding | FP_GameEntityFlag_PointOfInterestHeart);
|
||||||
|
FP_Game_DeleteEntity(game, entity->handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case FP_EntityType_Catfish: {
|
case FP_EntityType_Catfish: {
|
||||||
FP_EntityCatfishState *state = DQN_CAST(FP_EntityCatfishState *) & action->state;
|
FP_EntityCatfishState *state = DQN_CAST(FP_EntityCatfishState *) & action->state;
|
||||||
switch (*state) {
|
switch (*state) {
|
||||||
@ -1232,6 +1284,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
entity->attack_box_size = {};
|
entity->attack_box_size = {};
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case FP_EntityType_AirportTerryPlane: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,6 +1404,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
case FP_EntityType_ChurchTerry: break;
|
case FP_EntityType_ChurchTerry: break;
|
||||||
case FP_EntityType_KennelTerry: break;
|
case FP_EntityType_KennelTerry: break;
|
||||||
case FP_EntityType_PhoneMessageProjectile: break;
|
case FP_EntityType_PhoneMessageProjectile: break;
|
||||||
|
case FP_EntityType_AirportTerryPlane: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_entity) {
|
if (move_entity) {
|
||||||
@ -1595,19 +1649,20 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
if (FP_Game_IsNilEntityHandle(game, building->building_patron)) {
|
if (FP_Game_IsNilEntityHandle(game, building->building_patron)) {
|
||||||
building->building_patron = entity->handle;
|
building->building_patron = entity->handle;
|
||||||
|
|
||||||
|
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle);
|
||||||
|
Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
|
||||||
if (building->type == FP_EntityType_ClubTerry) {
|
if (building->type == FP_EntityType_ClubTerry) {
|
||||||
FP_Game_EntityTransitionState(game, building, FP_EntityClubTerryState_PartyTime);
|
FP_Game_EntityTransitionState(game, building, FP_EntityClubTerryState_PartyTime);
|
||||||
|
entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0
|
||||||
} else if (building->type == FP_EntityType_AirportTerry) {
|
} else if (building->type == FP_EntityType_AirportTerry) {
|
||||||
FP_Game_EntityTransitionState(game, building, FP_EntityAirportTerryState_FlyPassenger);
|
FP_Game_EntityTransitionState(game, building, FP_EntityAirportTerryState_FlyPassenger);
|
||||||
|
entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0
|
||||||
} else {
|
} else {
|
||||||
DQN_ASSERT(building->type == FP_EntityType_ChurchTerry);
|
DQN_ASSERT(building->type == FP_EntityType_ChurchTerry);
|
||||||
FP_Game_EntityTransitionState(game, building, FP_EntityChurchTerryState_ConvertPatron);
|
FP_Game_EntityTransitionState(game, building, FP_EntityChurchTerryState_ConvertPatron);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity->flags |= FP_GameEntityFlag_OccupiedInBuilding;
|
entity->flags |= FP_GameEntityFlag_OccupiedInBuilding;
|
||||||
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle);
|
|
||||||
Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
|
|
||||||
entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0
|
|
||||||
can_attack = false;
|
can_attack = false;
|
||||||
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
|
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
|
||||||
FP_SentinelList_Add(&entity->buildings_visited, game->chunk_pool, building->handle);
|
FP_SentinelList_Add(&entity->buildings_visited, game->chunk_pool, building->handle);
|
||||||
|
@ -7,6 +7,7 @@ enum FP_EntityType
|
|||||||
{
|
{
|
||||||
FP_EntityType_Nil,
|
FP_EntityType_Nil,
|
||||||
FP_EntityType_AirportTerry,
|
FP_EntityType_AirportTerry,
|
||||||
|
FP_EntityType_AirportTerryPlane,
|
||||||
FP_EntityType_Catfish,
|
FP_EntityType_Catfish,
|
||||||
FP_EntityType_ChurchTerry,
|
FP_EntityType_ChurchTerry,
|
||||||
FP_EntityType_Clinger,
|
FP_EntityType_Clinger,
|
||||||
@ -100,6 +101,13 @@ enum FP_EntityAirportTerryState
|
|||||||
FP_EntityAirportTerryState_FlyPassenger,
|
FP_EntityAirportTerryState_FlyPassenger,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FP_EntityAirportTerryPlaneState
|
||||||
|
{
|
||||||
|
FP_EntityAirportTerryPlaneState_Nil,
|
||||||
|
FP_EntityAirportTerryPlaneState_Idle,
|
||||||
|
FP_EntityAirportTerryPlaneState_FlyPassenger,
|
||||||
|
};
|
||||||
|
|
||||||
enum FP_EntityChurchTerryState
|
enum FP_EntityChurchTerryState
|
||||||
{
|
{
|
||||||
FP_EntityChurchTerryState_Nil,
|
FP_EntityChurchTerryState_Nil,
|
||||||
|
@ -250,6 +250,11 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
|
|||||||
result.anim_name = g_anim_names.terry_attack_phone_message;
|
result.anim_name = g_anim_names.terry_attack_phone_message;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_AirportTerryPlane: {
|
||||||
|
result.height.meters = 1.5f;
|
||||||
|
result.anim_name = g_anim_names.airport_terry_plane;
|
||||||
|
} break;
|
||||||
|
|
||||||
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,3 +692,29 @@ static FP_GameEntityHandle FP_Entity_CreatePhoneMessageProjectile(FP_Game *game,
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FP_GameEntityHandle FP_Entity_CreateAirportTerryPlane(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
FP_GameEntity *entity = FP_Game_MakeEntityPointerFV(game, fmt, args);
|
||||||
|
FP_GameEntityHandle result = entity->handle;
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
entity->type = FP_EntityType_AirportTerryPlane;
|
||||||
|
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
|
||||||
|
|
||||||
|
entity->local_pos = pos;
|
||||||
|
entity->sprite_height = render_data.height;
|
||||||
|
entity->flags |= FP_GameEntityFlag_NoClip;
|
||||||
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
|
|
||||||
|
entity->local_hit_box_offset = Dqn_V2_InitNx2(0, render_data.render_size.h * .1f);
|
||||||
|
entity->local_hit_box_size = Dqn_V2_InitNx2(render_data.render_size.w, render_data.render_size.h - (render_data.render_size.h * .4f));
|
||||||
|
entity->base_acceleration_per_s.meters = 32.f;
|
||||||
|
|
||||||
|
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||||
|
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -24,6 +24,7 @@ enum FP_GameEntityFlag
|
|||||||
FP_GameEntityFlag_TTL = 1 << 16,
|
FP_GameEntityFlag_TTL = 1 << 16,
|
||||||
FP_GameEntityFlag_Friendly = 1 << 17,
|
FP_GameEntityFlag_Friendly = 1 << 17,
|
||||||
FP_GameEntityFlag_Foe = 1 << 18,
|
FP_GameEntityFlag_Foe = 1 << 18,
|
||||||
|
FP_GameEntityFlag_NoClip = 1 << 19,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FP_GameShapeType
|
enum FP_GameShapeType
|
||||||
@ -325,6 +326,8 @@ struct FP_Game
|
|||||||
FP_GameActiveMenu active_menu;
|
FP_GameActiveMenu active_menu;
|
||||||
bool build_mode_can_place_building;
|
bool build_mode_can_place_building;
|
||||||
Dqn_usize build_mode_building_index;
|
Dqn_usize build_mode_building_index;
|
||||||
|
|
||||||
|
Dqn_FArray<FP_GameEntityHandle, 4> mob_spawners;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FP_GameAStarNode
|
struct FP_GameAStarNode
|
||||||
|
Loading…
Reference in New Issue
Block a user