fp: Rejig the mob spawner to use a fixed-waypoint path
This commit is contained in:
parent
bff3fc759d
commit
30a69e40e9
119
feely_pona.cpp
119
feely_pona.cpp
@ -205,6 +205,7 @@ void TELY_DLL_Init(void *user_data)
|
||||
// NOTE: Hero
|
||||
{
|
||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Terry");
|
||||
entity->type = FP_EntityType_Terry;
|
||||
entity->local_pos = Dqn_V2_InitNx2(1334, 396);
|
||||
entity->action_to_anim_mapping = game->terry_action_mappings;
|
||||
entity->size_scale = Dqn_V2_InitNx1(0.25f);
|
||||
@ -282,13 +283,31 @@ void TELY_DLL_Init(void *user_data)
|
||||
// NOTE: Mob spawner ===========================================================================
|
||||
{
|
||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob spawner");
|
||||
entity->local_pos = Dqn_V2_InitNx2(0, platform->core.window_size.y * .5f);
|
||||
entity->local_pos = Dqn_V2_InitNx2(50.f, platform->core.window_size.y * .5f);
|
||||
entity->flags |= FP_GameEntityFlag_Clickable;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByGamepad;
|
||||
entity->flags |= FP_GameEntityFlag_MobSpawner;
|
||||
entity->spawn_cap = 1;
|
||||
|
||||
entity->spawn_cap = 16;
|
||||
entity->spawn_list = TELY_ChunkPool_New(game->chunk_pool, FP_GameEntitySpawnList);
|
||||
entity->spawn_list->next = entity->spawn_list;
|
||||
entity->spawn_list->prev = entity->spawn_list;
|
||||
|
||||
FP_Game_PushParentEntity(game, entity->handle);
|
||||
{
|
||||
{
|
||||
FP_GameEntity *waypoint = FP_Game_MakeEntityPointerF(game, "Waypoint");
|
||||
waypoint->local_pos = Dqn_V2_InitNx2(800.f, 100.f);
|
||||
waypoint->flags |= FP_GameEntityFlag_Clickable;
|
||||
waypoint->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
||||
waypoint->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||
waypoint->flags |= FP_GameEntityFlag_MoveByGamepad;
|
||||
waypoint->flags |= FP_GameEntityFlag_MobSpawnerWaypoint;
|
||||
}
|
||||
}
|
||||
FP_Game_PopParentEntity(game);
|
||||
}
|
||||
|
||||
uint16_t font_size = 18;
|
||||
@ -676,13 +695,17 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
||||
FP_EntitySmoochieState *state = DQN_CAST(FP_EntitySmoochieState *)&entity->action.state;
|
||||
move_entity = *state == FP_EntitySmoochieState_Run || *state == FP_EntitySmoochieState_Idle;
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Merchant: break;
|
||||
}
|
||||
|
||||
acceleration = dir_vector * 10000000.f;
|
||||
if (dir_vector.x)
|
||||
entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
|
||||
else if (dir_vector.y)
|
||||
entity->direction = dir_vector.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
|
||||
if (move_entity) {
|
||||
acceleration = dir_vector * 10000000.f;
|
||||
if (dir_vector.x)
|
||||
entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
|
||||
else if (dir_vector.y)
|
||||
entity->direction = dir_vector.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,32 +741,31 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE: Render the waypoints
|
||||
for (FP_GameWaypoint *waypoint = entity->waypoints->next; waypoint != entity->waypoints; waypoint = waypoint->next) {
|
||||
Dqn_V2 circle_pos = Dqn_V2_InitNx2(waypoint->pos.x * game->tile_size + game->tile_size * .5f, waypoint->pos.y * game->tile_size + game->tile_size * .5f);
|
||||
TELY_Render_CircleColourV4(renderer, circle_pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_MAGENTA_V4);
|
||||
}
|
||||
// NOTE: Render the waypoints
|
||||
for (FP_GameWaypoint *waypoint = entity->waypoints->next; waypoint != entity->waypoints; waypoint = waypoint->next) {
|
||||
Dqn_V2 circle_pos = Dqn_V2_InitNx2(waypoint->pos.x, waypoint->pos.y);
|
||||
TELY_Render_CircleColourV4(renderer, circle_pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_MAGENTA_V4);
|
||||
}
|
||||
|
||||
if (entity->waypoints->next != entity->waypoints) {
|
||||
FP_GameWaypoint *waypoint = entity->waypoints->next;
|
||||
Dqn_V2I target_tile = entity->waypoints->next->pos;
|
||||
Dqn_V2 target_pos = Dqn_V2_InitNx2(target_tile.x * game->tile_size + game->tile_size *.5f, target_tile.y * game->tile_size + game->tile_size * .5f);
|
||||
Dqn_V2 entity_to_target_pos = target_pos - entity_world_pos;
|
||||
if (entity->waypoints->next != entity->waypoints) {
|
||||
FP_GameWaypoint *waypoint = entity->waypoints->next;
|
||||
Dqn_V2 target_pos = Dqn_V2_InitV2I(entity->waypoints->next->pos);
|
||||
Dqn_V2 entity_to_target_pos = target_pos - entity_world_pos;
|
||||
|
||||
if (Dqn_V2_LengthSq(entity_to_target_pos) < DQN_SQUARED(entity->local_hit_box_size.x * .5f)) {
|
||||
waypoint->next->prev = waypoint->prev;
|
||||
waypoint->prev->next = waypoint->next;
|
||||
TELY_ChunkPool_Dealloc(game->chunk_pool, waypoint);
|
||||
} else {
|
||||
Dqn_V2 entity_to_target_pos_norm = Dqn_V2_Normalise(entity_to_target_pos);
|
||||
if (acceleration.x == 0 && acceleration.y == 0) {
|
||||
acceleration = entity_to_target_pos_norm * 700'000.f;
|
||||
}
|
||||
if (Dqn_V2_LengthSq(entity_to_target_pos) < DQN_SQUARED(entity->local_hit_box_size.x * .5f)) {
|
||||
waypoint->next->prev = waypoint->prev;
|
||||
waypoint->prev->next = waypoint->next;
|
||||
TELY_ChunkPool_Dealloc(game->chunk_pool, waypoint);
|
||||
} else {
|
||||
Dqn_V2 entity_to_target_pos_norm = Dqn_V2_Normalise(entity_to_target_pos);
|
||||
if (acceleration.x == 0 && acceleration.y == 0) {
|
||||
acceleration = entity_to_target_pos_norm * 1'000'000.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE: Core equations of motion ==========================================================
|
||||
bool has_collision = false;
|
||||
@ -869,12 +891,51 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
||||
|
||||
// NOTE: Mob spawner =======================================================================
|
||||
if (entity->flags & FP_GameEntityFlag_MobSpawner) {
|
||||
if (entity->spawn_count < entity->spawn_cap) {
|
||||
// NOTE: Check if any spawned entities dies to remove it from the spawn cap tracker
|
||||
for (FP_GameEntitySpawnList *link = entity->spawn_list->next; link != entity->spawn_list;) {
|
||||
FP_GameEntity *spawned_entity = FP_Game_GetEntity(game, link->entity);
|
||||
if (spawned_entity) {
|
||||
// NOTE: Spawned entity is still alive
|
||||
link = link->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
DQN_ASSERT(entity->spawn_count);
|
||||
entity->spawn_count--;
|
||||
|
||||
// NOTE: Entity is dead remove it from the linked list
|
||||
FP_GameEntitySpawnList *link_to_delete = link;
|
||||
link->next->prev = link->prev;
|
||||
link->prev->next = link->next;
|
||||
link = link->next;
|
||||
TELY_ChunkPool_Dealloc(game->chunk_pool, link_to_delete);
|
||||
}
|
||||
|
||||
if (entity->spawn_count < entity->spawn_cap) { // NOTE: Spawn new entities
|
||||
if (input->timer_s >= entity->next_spawn_timestamp_s) {
|
||||
entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 5.f);
|
||||
entity->spawn_count++;
|
||||
|
||||
FP_Game_EntityAddMob(game, entity_world_pos);
|
||||
FP_GameEntitySpawnList *item = TELY_ChunkPool_New(game->chunk_pool, FP_GameEntitySpawnList);
|
||||
item->entity = FP_Game_EntityAddMob(game, entity_world_pos);
|
||||
FP_SentinelDoublyLinkedList_Insert(entity->spawn_list, item);
|
||||
|
||||
// NOTE: Setup the mob with a sentinel waypoint
|
||||
FP_GameEntity *mob = FP_Game_GetEntity(game, item->entity);
|
||||
mob->waypoints = TELY_ChunkPool_New(game->chunk_pool, FP_GameWaypoint);
|
||||
mob->waypoints->next = mob->waypoints;
|
||||
mob->waypoints->prev = mob->waypoints;
|
||||
|
||||
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
|
||||
if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0)
|
||||
continue;
|
||||
|
||||
// NOTE: Add the waypoint
|
||||
FP_GameWaypoint *waypoint = TELY_ChunkPool_New(game->chunk_pool, FP_GameWaypoint);
|
||||
Dqn_V2 waypoint_pos = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle);
|
||||
waypoint->pos = Dqn_V2I_InitV2(waypoint_pos);
|
||||
FP_SentinelDoublyLinkedList_Insert(mob->waypoints, waypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,12 @@
|
||||
#include "feely_pona_unity.h"
|
||||
#endif
|
||||
|
||||
#define FP_SentinelDoublyLinkedList_Insert(list, item) \
|
||||
item->next = list; \
|
||||
item->prev = list->prev; \
|
||||
item->next->prev = item; \
|
||||
item->prev->next = item;
|
||||
|
||||
enum FP_ProfileZone
|
||||
{
|
||||
FP_ProfileZone_FPUpdate = TELY_ProfileZone_Count,
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
enum FP_EntityType
|
||||
{
|
||||
FP_EntityType_Nil,
|
||||
FP_EntityType_Terry,
|
||||
FP_EntityType_Smoochie,
|
||||
FP_EntityType_Merchant,
|
||||
|
@ -292,6 +292,9 @@ static void FP_Game_DetachEntityIntoFreeList(FP_Game *game, FP_GameEntityHandle
|
||||
if (entity->name.size)
|
||||
TELY_ChunkPool_Dealloc(game->chunk_pool, entity->name.data);
|
||||
|
||||
if (entity->spawn_list)
|
||||
TELY_ChunkPool_Dealloc(game->chunk_pool, entity->spawn_list);
|
||||
|
||||
if (new_entity_generation > entity_generation) {
|
||||
// NOTE: Update the incremented handle disassociating all prior handles
|
||||
// to this entity which would reference older generation values
|
||||
@ -672,7 +675,7 @@ static FP_GameEntityHandle FP_Game_EntityAddMob(FP_Game *game, Dqn_V2 pos)
|
||||
entity->local_pos = pos;
|
||||
entity->size_scale = Dqn_V2_InitNx1(.25f);
|
||||
entity->action_to_anim_mapping = game->smoochie_action_mappings;
|
||||
entity->local_hit_box_size = Dqn_V2_InitV2I(game->smoochie_sprite_sheet.sprite_size);
|
||||
entity->local_hit_box_size = Dqn_V2_InitNx2(428, 471) * entity->size_scale;
|
||||
entity->flags |= FP_GameEntityFlag_Clickable;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||
|
@ -13,6 +13,7 @@ enum FP_GameEntityFlag
|
||||
FP_GameEntityFlag_DeriveHitBoxFromChildrenBoundingBox = 1 << 5,
|
||||
FP_GameEntityFlag_NonTraversable = 1 << 6,
|
||||
FP_GameEntityFlag_MobSpawner = 1 << 7,
|
||||
FP_GameEntityFlag_MobSpawnerWaypoint = 1 << 8,
|
||||
};
|
||||
|
||||
enum FP_GameShapeType
|
||||
@ -52,6 +53,13 @@ struct FP_GameWaypoint
|
||||
FP_GameWaypoint *prev;
|
||||
};
|
||||
|
||||
struct FP_GameEntitySpawnList
|
||||
{
|
||||
FP_GameEntityHandle entity;
|
||||
FP_GameEntitySpawnList *next;
|
||||
FP_GameEntitySpawnList *prev;
|
||||
};
|
||||
|
||||
enum FP_GameEntityActionFlag
|
||||
{
|
||||
FP_GameEntityActionFlag_StateTransition = 1 << 0,
|
||||
@ -112,6 +120,8 @@ struct FP_GameEntity
|
||||
Dqn_V2 attack_box_size;
|
||||
Dqn_V2 attack_box_offset;
|
||||
|
||||
Dqn_FArray<Dqn_V2, 8> spawner_waypoints;
|
||||
FP_GameEntitySpawnList *spawn_list;
|
||||
uint64_t next_spawn_timestamp_s;
|
||||
uint64_t spawn_count;
|
||||
uint64_t spawn_cap;
|
||||
|
Loading…
Reference in New Issue
Block a user