4 Commits

Author SHA1 Message Date
doylet efec333b61 fp: Redo the attack boxes 2023-10-08 16:46:49 +11:00
doylet 98e3245682 fp: Reset game on game completion 2023-10-08 16:46:47 +11:00
doylet 1889b9f9c5 fp: Wire up game reset 2023-10-08 16:46:44 +11:00
Jojangles 2102ffa094 fp: Add more sfx 2023-10-08 16:21:39 +11:00
10 changed files with 554 additions and 420 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
+394 -304
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -14,7 +14,7 @@ static bool FP_Entity_IsBuildingForMobs(FP_GameEntity *entity)
static Dqn_f32 FP_Entity_CalcSpriteScaleForDesiredHeight(FP_Game *game, FP_Meters height, Dqn_Rect sprite_rect)
{
Dqn_f32 sprite_in_meters = FP_Game_PixelsToMetersNx1(game, sprite_rect.size.y);
Dqn_f32 sprite_in_meters = FP_Game_PixelsToMetersNx1(game->play, sprite_rect.size.y);
Dqn_f32 result = height.meters / sprite_in_meters;
return result;
}
@@ -318,7 +318,7 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
entity->attack_cooldown_ms = 1000;
entity->faction = FP_GameEntityFaction_Foe;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.7f, entity->sprite_height.meters * .5f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game->play, 0.7f, entity->sprite_height.meters * .5f);
FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
@@ -341,7 +341,7 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
entity->is_dying = false;
entity->local_pos = pos;
entity->attack_cooldown_ms = 1000;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.7f, entity->sprite_height.meters * .6f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game->play, 0.7f, entity->sprite_height.meters * .6f);
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
@@ -375,7 +375,7 @@ static FP_GameEntityHandle FP_Entity_CreateCatfish(FP_Game *game, Dqn_V2 pos, DQ
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->attack_cooldown_ms = 1000;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.7f, entity->sprite_height.meters * .6f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game->play, 0.7f, entity->sprite_height.meters * .6f);
FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
@@ -434,7 +434,7 @@ static FP_GameEntityHandle FP_Entity_CreateMobSpawner(FP_Game *game, Dqn_V2 pos,
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->spawn_cap = spawn_cap;
entity->spawn_list = FP_SentinelList_Init<FP_GameEntityHandle>(game->chunk_pool);
entity->spawn_list = FP_SentinelList_Init<FP_GameEntityHandle>(game->play.chunk_pool);
return result;
}
@@ -456,10 +456,10 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->attack_cooldown_ms = 500;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters * .6f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game->play, 0.5f, entity->sprite_height.meters * .6f);
entity->hp_cap = FP_DEFAULT_DAMAGE * 3;
entity->hp = entity->hp_cap;
entity->coins = 0;//1'000'000;
entity->coins = 1'000'000;
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
@@ -756,7 +756,7 @@ static FP_GameEntityHandle FP_Entity_CreatePhoneMessageProjectile(FP_Game *game,
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->attack_box_offset = entity->local_hit_box_offset;
entity->attack_box_size = entity->local_hit_box_size;
entity->ttl_end_timestamp = game->clock_ms + 1000;
entity->ttl_end_timestamp = game->play.clock_ms + 1000;
entity->projectile_owner = owner;
entity->faction = FP_GameEntityFaction_Friendly;
return result;
+88 -55
View File
@@ -3,13 +3,13 @@
#include "feely_pona_unity.h"
#endif
#define FP_Game_MetersToPixelsNx1(game, val) ((val) * (game)->meters_to_pixels)
#define FP_Game_MetersToPixelsNx2(game, x, y) (Dqn_V2_InitNx2(x, y) * (game)->meters_to_pixels)
#define FP_Game_MetersToPixelsV2(game, xy) (xy * (game)->meters_to_pixels)
#define FP_Game_MetersToPixelsNx1(game, val) ((val) * (game).meters_to_pixels)
#define FP_Game_MetersToPixelsNx2(game, x, y) (Dqn_V2_InitNx2(x, y) * (game).meters_to_pixels)
#define FP_Game_MetersToPixelsV2(game, xy) (xy * (game).meters_to_pixels)
#define FP_Game_PixelsToMetersNx1(game, val) ((val) * (1.f/(game)->meters_to_pixels))
#define FP_Game_PixelsToMetersNx2(game, x, y) (Dqn_V2_InitNx2(x, y) * (1.f/(game)->meters_to_pixels))
#define FP_Game_PixelsToMetersV2(game, xy) (xy * (1.f/(game)->meters_to_pixels))
#define FP_Game_PixelsToMetersNx1(game, val) ((val) * (1.f/(game).meters_to_pixels))
#define FP_Game_PixelsToMetersNx2(game, x, y) (Dqn_V2_InitNx2(x, y) * (1.f/(game).meters_to_pixels))
#define FP_Game_PixelsToMetersV2(game, xy) (xy * (1.f/(game).meters_to_pixels))
static bool operator==(FP_GameEntityHandle const &lhs, FP_GameEntityHandle const &rhs)
{
@@ -50,12 +50,12 @@ static FP_GameEntity *FP_Game_GetEntity(FP_Game *game, FP_GameEntityHandle handl
if (!game)
return result;
result = game->entities.data;
result = game->play.entities.data;
uint64_t index_from_handle = handle.id & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
if (index_from_handle >= game->entities.size)
if (index_from_handle >= game->play.entities.size)
return result;
FP_GameEntity *candidate = game->entities.data + index_from_handle;
FP_GameEntity *candidate = game->play.entities.data + index_from_handle;
if (candidate->handle == handle)
result = candidate;
return result;
@@ -167,24 +167,24 @@ static bool FP_Game_DFSPostOrderWalkEntityTree(FP_Game *game, FP_GameEntityItera
// NOTE: Parent entity
static void FP_Game_PushParentEntity(FP_Game *game, FP_GameEntityHandle handle)
{
DQN_ASSERTF(game->parent_entity_stack.size >= 1, "Sentinel/nil entity has not been assigned as the 0th slot yet");
DQN_ASSERTF(game->play.parent_entity_stack.size >= 1, "Sentinel/nil entity has not been assigned as the 0th slot yet");
if (game)
Dqn_FArray_Add(&game->parent_entity_stack, handle);
Dqn_FArray_Add(&game->play.parent_entity_stack, handle);
}
static void FP_Game_PopParentEntity(FP_Game *game)
{
// NOTE: 0th slot is reserved for the nil entity
if (game && game->parent_entity_stack.size > 1)
Dqn_FArray_PopBack(&game->parent_entity_stack, 1);
if (game && game->play.parent_entity_stack.size > 1)
Dqn_FArray_PopBack(&game->play.parent_entity_stack, 1);
}
static FP_GameEntityHandle FP_Game_ActiveParentEntity(FP_Game const *game)
{
FP_GameEntityHandle result = {};
if (!game || !game->parent_entity_stack.size)
if (!game || !game->play.parent_entity_stack.size)
return result;
result = game->parent_entity_stack.data[game->parent_entity_stack.size - 1];
result = game->play.parent_entity_stack.data[game->play.parent_entity_stack.size - 1];
return result;
}
@@ -201,28 +201,28 @@ static FP_GameEntity *FP_Game_MakeEntityPointerFV(FP_Game *game, DQN_FMT_STRING_
if (!game)
return result;
DQN_ASSERTF(game->entities.size > 0, "Sentinel/nil entity has not been initialised yet");
DQN_ASSERTF(game->root_entity, "Sentinel/nil entity has not been assigned yet");
DQN_ASSERTF(game->play.entities.size > 0, "Sentinel/nil entity has not been initialised yet");
DQN_ASSERTF(game->play.root_entity, "Sentinel/nil entity has not been assigned yet");
result = game->root_entity; // TODO(doyle): Root entity or ... the nil entity?
if (game->entity_free_list) {
result = game->entity_free_list;
game->entity_free_list = game->entity_free_list->next;
result = game->play.root_entity; // TODO(doyle): Root entity or ... the nil entity?
if (game->play.entity_free_list) {
result = game->play.entity_free_list;
game->play.entity_free_list = game->play.entity_free_list->next;
result->next = nullptr;
} else {
if (game->entities.size >= (FP_GAME_ENTITY_HANDLE_INDEX_MAX + 1))
if (game->play.entities.size >= (FP_GAME_ENTITY_HANDLE_INDEX_MAX + 1))
return result;
result = Dqn_VArray_Make(&game->entities, Dqn_ZeroMem_Yes);
result = Dqn_VArray_Make(&game->play.entities, Dqn_ZeroMem_Yes);
if (!result)
return result;
result->handle.id = (game->entities.size - 1) & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
result->handle.id = (game->play.entities.size - 1) & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
}
result->sprite_height.meters = 1;
result->parent = FP_Game_ActiveParentEntityPointer(game);
result->name = TELY_ChunkPool_AllocFmtFV(game->chunk_pool, fmt, args);
result->buildings_visited = FP_SentinelList_Init<FP_GameEntityHandle>(game->chunk_pool);
result->name = TELY_ChunkPool_AllocFmtFV(game->play.chunk_pool, fmt, args);
result->buildings_visited = FP_SentinelList_Init<FP_GameEntityHandle>(game->play.chunk_pool);
result->action.sprite_alpha = 1.f;
result->stamina_cap = 93;
@@ -251,7 +251,7 @@ static FP_GameEntity *FP_Game_MakeEntityPointerFV(FP_Game *game, DQN_FMT_STRING_
DQN_ASSERT(!result->next);
DQN_ASSERT(result->handle.id);
DQN_ASSERT(result->parent->handle == game->parent_entity_stack.data[game->parent_entity_stack.size - 1]);
DQN_ASSERT(result->parent->handle == game->play.parent_entity_stack.data[game->play.parent_entity_stack.size - 1]);
return result;
}
@@ -308,7 +308,7 @@ static void FP_Game_DetachEntityIntoFreeList(FP_Game *game, FP_GameEntityHandle
return;
uint64_t const entity_index_from_handle = entity->handle.id & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
DQN_ASSERT(entity_index_from_handle < game->entities.size);
DQN_ASSERT(entity_index_from_handle < game->play.entities.size);
uint64_t const entity_generation_raw = entity->handle.id & FP_GAME_ENTITY_HANDLE_GENERATION_MASK;
uint64_t const entity_generation = entity_generation_raw >> FP_GAME_ENTITY_HANDLE_GENERATION_RSHIFT;
@@ -330,22 +330,23 @@ static void FP_Game_DetachEntityIntoFreeList(FP_Game *game, FP_GameEntityHandle
parent->last_child = entity->prev;
if (entity->name.size)
TELY_ChunkPool_Dealloc(game->chunk_pool, entity->name.data);
TELY_ChunkPool_Dealloc(game->play.chunk_pool, entity->name.data);
FP_SentinelList_Deinit(&entity->spawn_list, game->chunk_pool);
FP_SentinelList_Deinit(&entity->waypoints, game->chunk_pool);
FP_SentinelList_Deinit(&entity->buildings_visited, game->chunk_pool);
FP_SentinelList_Deinit(&entity->spawn_list, game->play.chunk_pool);
FP_SentinelList_Deinit(&entity->waypoints, game->play.chunk_pool);
FP_SentinelList_Deinit(&entity->buildings_visited, game->play.chunk_pool);
if (new_entity_generation > entity_generation) {
// NOTE: Update the incremented handle disassociating all prior handles
// to this entity which would reference older generation values
*entity = {};
entity->parent = game->play.root_entity;
entity->handle.id = entity_index_from_handle | (new_entity_generation << FP_GAME_ENTITY_HANDLE_GENERATION_RSHIFT);
// NOTE: Attach entity to the free list
entity->next = game->entity_free_list;
entity->next = game->play.entity_free_list;
entity->prev = nullptr;
game->entity_free_list = entity;
game->play.entity_free_list = entity;
} else {
// NOTE: We've cycled through all possible generations for this handle
// We will not increment it and freeze it so it is no longer allocated
@@ -357,10 +358,10 @@ static void FP_Game_DetachEntityIntoFreeList(FP_Game *game, FP_GameEntityHandle
static void FP_Game_DeleteEntity(FP_Game *game, FP_GameEntityHandle handle)
{
uint64_t index_from_handle = handle.id & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
if (!game || !DQN_CHECK(index_from_handle < game->entities.size))
if (!game || !DQN_CHECK(index_from_handle < game->play.entities.size))
return;
FP_GameEntity *root = game->entities.data + index_from_handle;
FP_GameEntity *root = game->play.entities.data + index_from_handle;
if (root->handle != handle)
return;
@@ -381,8 +382,8 @@ static Dqn_V2 FP_Game_CalcEntityWorldPos(FP_Game const *game, FP_GameEntityHandl
if (!game)
return result;
FP_GameEntity const *first = FP_Game_GetEntity(DQN_CAST(FP_Game *) game, handle);
for (FP_GameEntity const *entity = first; entity != game->root_entity; entity = entity->parent)
FP_GameEntity const *first = FP_Game_GetEntity(DQN_CAST(FP_Game *)game, handle);
for (FP_GameEntity const *entity = first; entity != game->play.root_entity; entity = entity->parent)
result += entity->local_pos;
return result;
}
@@ -413,6 +414,37 @@ static Dqn_Rect FP_Game_CalcEntityAttackWorldHitBox(FP_Game const *game, FP_Game
return result;
}
static Dqn_FArray<Dqn_Rect, FP_GameDirection_Count> FP_Game_CalcEntityMeleeAttackBoxes(FP_Game const *game, FP_GameEntityHandle handle)
{
Dqn_FArray<Dqn_Rect, FP_GameDirection_Count> result = {};
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, handle);
DQN_FOR_UINDEX (dir_index, FP_GameDirection_Count) {
Dqn_Rect *rect = Dqn_FArray_Make(&result, Dqn_ZeroMem_Yes);
rect->size = hit_box.size;
switch (dir_index) {
case FP_GameDirection_Left: {
rect->pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(-1.f, 0.f));
} break;
case FP_GameDirection_Right: {
rect->pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(+1.f, 0.f));
} break;
case FP_GameDirection_Up: {
rect->pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.f, -1.f));
} break;
case FP_GameDirection_Down: {
rect->pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.f, +1.f));
} break;
case FP_GameDirection_Count: break;
}
}
return result;
}
static Dqn_Rect FP_Game_CalcEntityArrayWorldBoundingBox(FP_Game const *game, FP_GameEntityHandle const *handles, Dqn_usize count)
{
Dqn_Rect result = {};
@@ -472,19 +504,19 @@ static void FP_Game_EntityActionReset(FP_Game *game, FP_GameEntityHandle entity_
if (!entity)
return;
entity->action.sprite = sprite;
entity->action.started_at_clock_ms = game->clock_ms;
entity->action.end_at_clock_ms = DQN_MAX(duration_ms, game->clock_ms + duration_ms);
entity->action.started_at_clock_ms = game->play.clock_ms;
entity->action.end_at_clock_ms = DQN_MAX(duration_ms, game->play.clock_ms + duration_ms);
}
static Dqn_V2I FP_Game_WorldPosToTilePos(FP_Game *game, Dqn_V2 world_pos)
{
Dqn_V2I result = Dqn_V2I_InitNx2(world_pos.x / game->tile_size, world_pos.y / game->tile_size);
Dqn_V2I result = Dqn_V2I_InitNx2(world_pos.x / game->play.tile_size, world_pos.y / game->play.tile_size);
return result;
}
static Dqn_V2 FP_Game_TilePosToWorldPos(FP_Game *game, Dqn_V2I tile_pos)
{
Dqn_V2 result = Dqn_V2_InitNx2(tile_pos.x * game->tile_size, tile_pos.y * game->tile_size);
Dqn_V2 result = Dqn_V2_InitNx2(tile_pos.x * game->play.tile_size, tile_pos.y * game->play.tile_size);
return result;
}
@@ -495,8 +527,8 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
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_usize tile_count_x = DQN_CAST(Dqn_usize)(platform->core.window_size.w / game->play.tile_size);
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(platform->core.window_size.h / game->play.tile_size);
Dqn_Slice<Dqn_V2I> result = {};
if (dest_tile.x < 0 || dest_tile.x > tile_count_x ||
@@ -509,7 +541,7 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
// NOTE: Enumerate the entities that are collidable ============================================
bool dest_tile_is_non_traversable = false;
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); ) {
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->play.root_entity); ) {
FP_GameEntity const *walk_entity = it.entity;
if (entity == walk_entity->handle)
continue;
@@ -644,7 +676,7 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
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);
Dqn_V2 pos = FP_Game_TilePosToWorldPos(game, node->tile) + (game->play.tile_size * .5f);
TELY_Render_CircleColourV4(renderer, pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_BLUE_CADET_V4);
}
#endif
@@ -737,7 +769,7 @@ FP_GameFindClosestEntityResult FP_Game_FindClosestEntityWithType(FP_Game *game,
result.dist_squared = DQN_F32_MAX;
result.pos = Dqn_V2_InitNx1(DQN_F32_MAX);
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->play.root_entity); ) {
FP_GameEntity *it_entity = it.entity;
if (it_entity->type != type)
continue;
@@ -791,11 +823,11 @@ static void FP_Game_EntityTransitionState(FP_Game *game, FP_GameEntity *entity,
case FP_EntityType_Terry: {
if (desired_state == FP_EntityTerryState_Attack ||
desired_state == FP_EntityTerryState_RangeAttack) {
if (!FP_Game_CanEntityAttack(entity, game->clock_ms)) {
if (!FP_Game_CanEntityAttack(entity, game->play.clock_ms)) {
// NOTE: Cooldown not met do not transition
return;
}
entity->last_attack_timestamp = game->clock_ms;
entity->last_attack_timestamp = game->play.clock_ms;
if (desired_state == FP_EntityTerryState_RangeAttack) {
if (entity->terry_mobile_data_plan < FP_TERRY_MOBILE_DATA_PER_RANGE_ATTACK)
@@ -809,31 +841,31 @@ static void FP_Game_EntityTransitionState(FP_Game *game, FP_GameEntity *entity,
case FP_EntityType_Smoochie: {
if (desired_state == FP_EntitySmoochieState_Attack) {
if (!FP_Game_CanEntityAttack(entity, game->clock_ms)) {
if (!FP_Game_CanEntityAttack(entity, game->play.clock_ms)) {
// NOTE: Cooldown not met do not transition
return;
}
entity->last_attack_timestamp = game->clock_ms;
entity->last_attack_timestamp = game->play.clock_ms;
}
} break;
case FP_EntityType_Clinger: {
if (desired_state == FP_EntityClingerState_Attack) {
if (!FP_Game_CanEntityAttack(entity, game->clock_ms)) {
if (!FP_Game_CanEntityAttack(entity, game->play.clock_ms)) {
// NOTE: Cooldown not met do not transition
return;
}
entity->last_attack_timestamp = game->clock_ms;
entity->last_attack_timestamp = game->play.clock_ms;
}
} break;
case FP_EntityType_Catfish: {
if (desired_state == FP_EntityClingerState_Attack) {
if (!FP_Game_CanEntityAttack(entity, game->clock_ms)) {
if (!FP_Game_CanEntityAttack(entity, game->play.clock_ms)) {
// NOTE: Cooldown not met do not transition
return;
}
entity->last_attack_timestamp = game->clock_ms;
entity->last_attack_timestamp = game->play.clock_ms;
}
} break;
@@ -893,3 +925,4 @@ static void FP_GameRenderCameraFollowScanlines(TELY_Renderer *renderer,
TELY_Render_LineColourV4(renderer, start, end, TELY_Colour_V4Alpha(TELY_COLOUR_BLACK_V4, 0.1f), scanline_thickness);
}
}
+26 -18
View File
@@ -260,6 +260,9 @@ enum FP_GameAudio
FP_GameAudio_TestAudio,
FP_GameAudio_TerryHit,
FP_GameAudio_Smooch,
FP_GameAudio_Woosh,
FP_GameAudio_Ching,
FP_GameAudio_Church,
FP_GameAudio_Count,
};
@@ -274,27 +277,17 @@ enum FP_GameState
{
FP_GameState_IntroScreen,
FP_GameState_Play,
FP_GameState_WinGame,
};
struct FP_Game
struct FP_GamePlay
{
Dqn_f32 delta_s_accumulator;
uint16_t tile_size;
TELY_ChunkPool *chunk_pool;
TELY_AssetFontHandle inter_regular_font_large;
TELY_AssetFontHandle inter_regular_font;
TELY_AssetFontHandle inter_italic_font;
TELY_AssetFontHandle jetbrains_mono_font;
TELY_AssetFontHandle talkco_font;
TELY_AssetFontHandle talkco_font_large;
TELY_AssetAudioHandle audio[FP_GameAudio_Count];
Dqn_Slice<TELY_AssetSpriteAnimation> hero_sprite_anims;
TELY_AssetSpriteSheet hero_sprite_sheet;
Dqn_FArray<FP_GameEntityHandle, 8> parent_entity_stack;
uint16_t tile_size;
Dqn_f32 delta_s_accumulator;
Dqn_Arena arena;
Dqn_VArray<FP_GameEntity> entities;
TELY_AssetSpriteSheet atlas_sprite_sheet;
Dqn_FArray<FP_GameEntityHandle, 8> parent_entity_stack;
FP_GameEntity *root_entity;
FP_GameEntity *entity_free_list;
@@ -318,14 +311,13 @@ struct FP_Game
FP_GameEntityHandle prev_active_entity;
FP_GameCamera camera;
TELY_RFui rfui;
Dqn_f32 meters_to_pixels;
uint64_t clock_ms;
uint64_t update_counter;
Dqn_PCG32 rng;
bool debug_ui;
bool god_mode;
FP_GameInGameMenu in_game_menu;
bool build_mode_can_place_building;
Dqn_usize build_mode_building_index;
@@ -341,6 +333,22 @@ struct FP_Game
FP_GameState state;
};
struct FP_Game
{
TELY_AssetFontHandle inter_regular_font_large;
TELY_AssetFontHandle inter_regular_font;
TELY_AssetFontHandle inter_italic_font;
TELY_AssetFontHandle jetbrains_mono_font;
TELY_AssetFontHandle talkco_font;
TELY_AssetFontHandle talkco_font_large;
TELY_AssetAudioHandle audio[FP_GameAudio_Count];
Dqn_Slice<TELY_AssetSpriteAnimation> hero_sprite_anims;
TELY_AssetSpriteSheet hero_sprite_sheet;
TELY_AssetSpriteSheet atlas_sprite_sheet;
TELY_RFui rfui;
FP_GamePlay play;
};
struct FP_GameAStarNode
{
Dqn_usize cost;
+12 -12
View File
@@ -351,10 +351,10 @@ void FP_UnitTests(TELY_Platform *platform)
chunk_pool.arena = &platform->arena;
FP_Game *game = Dqn_Arena_New(&platform->arena, FP_Game, Dqn_ZeroMem_Yes);
game->chunk_pool = &chunk_pool;
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
game->root_entity = Dqn_VArray_Make(&game->entities, Dqn_ZeroMem_No);
Dqn_FArray_Add(&game->parent_entity_stack, game->root_entity->handle);
game->play.chunk_pool = &chunk_pool;
game->play.entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
game->play.root_entity = Dqn_VArray_Make(&game->play.entities, Dqn_ZeroMem_No);
Dqn_FArray_Add(&game->play.parent_entity_stack, game->play.root_entity->handle);
{
// NOTE: Setup entity-tree =================================================================
@@ -384,7 +384,7 @@ void FP_UnitTests(TELY_Platform *platform)
FP_GameEntity *pre_order_walk[9] = {};
Dqn_usize pre_order_walk_count = 0;
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->root_entity);) {
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->play.root_entity);) {
DQN_ASSERT(pre_order_walk_count < DQN_ARRAY_UCOUNT(pre_order_walk));
pre_order_walk[pre_order_walk_count++] = it.entity;
}
@@ -404,7 +404,7 @@ void FP_UnitTests(TELY_Platform *platform)
FP_GameEntity *post_order_walk[9] = {};
Dqn_usize post_order_walk_count = 0;
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity);) {
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->play.root_entity);) {
DQN_ASSERT(post_order_walk_count < DQN_ARRAY_UCOUNT(post_order_walk));
post_order_walk[post_order_walk_count++] = it.entity;
}
@@ -421,11 +421,11 @@ void FP_UnitTests(TELY_Platform *platform)
DQN_ASSERT(post_order_walk[8] == f);
// NOTE: Cleanup ===========================================================================
FP_Game_DeleteEntity(game, game->root_entity->handle);
DQN_ASSERT(game->root_entity->first_child == nullptr);
DQN_ASSERT(game->root_entity->last_child == nullptr);
DQN_ASSERT(game->root_entity->next == nullptr);
DQN_ASSERT(game->root_entity->prev == nullptr);
DQN_ASSERT(game->root_entity->parent == nullptr);
FP_Game_DeleteEntity(game, game->play.root_entity->handle);
DQN_ASSERT(game->play.root_entity->first_child == nullptr);
DQN_ASSERT(game->play.root_entity->last_child == nullptr);
DQN_ASSERT(game->play.root_entity->next == nullptr);
DQN_ASSERT(game->play.root_entity->prev == nullptr);
DQN_ASSERT(game->play.root_entity->parent == nullptr);
}
}