fp: Add pause screen

This commit is contained in:
doyle 2023-10-09 21:35:51 +11:00
parent bd4783cc39
commit 81b3fc5c5d
4 changed files with 110 additions and 94 deletions

2
External/tely vendored

@ -1 +1 @@
Subproject commit 8d39ef2d8365e223114bbdc2ce2db2edaaf81163
Subproject commit 883007994e1077746ffe86f78d380559174d188f

View File

@ -640,10 +640,10 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (FP_Game_IsNilEntityHandle(game, entity->carried_monkey)) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Attack);
} else if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_K) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_Y)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_Y)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack);
}
} else {
@ -706,10 +706,10 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (FP_Game_IsNilEntityHandle(game, entity->carried_monkey)) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Attack);
} else if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_K) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_Y)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_Y)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack);
}
}
@ -717,7 +717,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (FP_Game_IsNilEntityHandle(game, entity->carried_monkey)) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_LeftControl) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_A)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_A)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Dash);
}
} else {
@ -803,7 +803,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Attack);
} else if (acceleration_meters_per_s->x || acceleration_meters_per_s->y) {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Run);
@ -897,7 +897,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Attack);
}
}
@ -924,7 +924,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityClingerState_Attack);
} else if (acceleration_meters_per_s->x || acceleration_meters_per_s->y) {
FP_Game_EntityTransitionState(game, entity, FP_EntityClingerState_Run);
@ -967,7 +967,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityClingerState_Attack);
}
}
@ -1170,7 +1170,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityCatfishState_Attack);
} else if (acceleration_meters_per_s->x || acceleration_meters_per_s->y) {
FP_Game_EntityTransitionState(game, entity, FP_EntityCatfishState_Run);
@ -1212,7 +1212,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
TELY_Platform_InputGamepadKeyIsPressed(input, 0, TELY_PlatformInputGamepadKey_X)) {
FP_Game_EntityTransitionState(game, entity, FP_EntityCatfishState_Attack);
}
}
@ -1424,7 +1424,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
}
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Escape))
game->play.clicked_entity = {};
game->play.state = FP_GameState_Pause;
if (game->play.clicked_entity.id) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Delete))
@ -1589,10 +1589,12 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
it_entity->type != FP_EntityType_ChurchTerry)
continue;
// NOTE: Already converted, we cannot attend church again
if (entity->converted_faction && it_entity->type == FP_EntityType_ChurchTerry) {
// NOTE: Already converted, we cannot attend church again ======================
if (entity->converted_faction && it_entity->type == FP_EntityType_ChurchTerry)
continue;
if (it_entity->building_queue.size == Dqn_FArray_Max(&it_entity->building_queue))
continue;
}
bool already_visited_building = false;
for (FP_SentinelListLink<FP_GameEntityHandle> *link_it = {};
@ -2500,65 +2502,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
}
if (game->play.state == FP_GameState_IntroScreen || game->play.state == FP_GameState_WinGame || game->play.state == FP_GameState_LoseGame) {
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
TELY_Render_RectColourV4(
renderer,
Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)platform->core.window_size.x, DQN_CAST(Dqn_f32)platform->core.window_size.y),
TELY_RenderShapeMode_Fill,
TELY_Colour_V4Alpha(TELY_COLOUR_BLACK_V4, 0.8f));
// NOTE: Render overlay UI =====================================================================
if (game->play.state == FP_GameState_Pause || game->play.state == FP_GameState_Play) {
Dqn_V2I inset = platform->core.window_size * .05f;
Dqn_f32 min_inset = DQN_CAST(Dqn_f32)DQN_MIN(inset.x, inset.y);
Dqn_V2 draw_p = Dqn_V2_InitNx2(min_inset, min_inset);
TELY_Render_PushColourV4(renderer, TELY_COLOUR_WHITE_V4);
if (game->play.state == FP_GameState_IntroScreen) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Feely Pona"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to start"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
game->play.state = FP_GameState_Play;
} else if (game->play.state == FP_GameState_LoseGame) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry's heart has been crushed"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from the hoard of monsters"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Sayounara amigo"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
FP_PlayReset(game, platform);
} else {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry has been saved"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from his terrible calamity"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "He lives for yet another day and another love"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
FP_PlayReset(game, platform);
}
} else {
// NOTE: Render the merchant menus =========================================
// NOTE: Render the merchant menus =========================================================
FP_GameEntity *player = FP_Game_GetEntity(game, game->play.player);
Dqn_V2 player_pos = FP_Game_CalcEntityWorldPos(game, game->play.player);
{
@ -2805,7 +2752,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
}
// NOTE: Render player avatar HUD ==========================================
// NOTE: Render player avatar HUD ==========================================================
Dqn_Rect player_avatar_rect = {};
player_avatar_rect.pos = Dqn_V2_InitNx1(32.f);
Dqn_V2 next_pos = {};
@ -3027,7 +2974,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
#endif
}
// NOTE: Render the wave ===================================================
// NOTE: Render the wave ===================================================================
{
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
@ -3055,7 +3002,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
if (!FP_Game_IsNilEntityHandle(game, game->play.clicked_entity)) {
// NOTE: Render building blueprint =========================================================
// NOTE: Render building blueprint =====================================================
if (game->play.in_game_menu == FP_GameInGameMenu_Build) {
FP_GameEntity *entity = FP_Game_GetEntity(game, game->play.clicked_entity);
FP_GamePlaceableBuilding placeable_building = PLACEABLE_BUILDINGS[game->play.build_mode_building_index];
@ -3076,7 +3023,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
colour);
}
// NOTE: Render the building selector UI ===================================================
// NOTE: Render the building selector UI ===============================================
{
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
@ -3131,7 +3078,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
}
// NOTE: Render the heart health
// NOTE: Render the heart health ===========================================================
{
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
@ -3141,9 +3088,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
{
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.heart);
FP_GameEntity *heart = FP_Game_GetEntity(game, game->play.heart);
Dqn_f32 max_width = platform->core.window_size.x * .5f;
Dqn_V2 draw_p = Dqn_V2_InitNx2(platform->core.window_size.x * .25f, player_avatar_rect.pos.y + bar_height);
Dqn_f32 health_t = heart->hp / DQN_CAST(Dqn_f32)heart->hp_cap;
Dqn_Rect health_rect = Dqn_Rect_InitNx4(draw_p.x, draw_p.y, max_width, bar_height);
@ -3177,15 +3122,89 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(heart_icon_rect, Dqn_V2_InitNx2(1.f, 0.65f)), Dqn_V2_Zero, "Terry's Heart");
}
}
}
// NOTE: Add scanlines into the game for A E S T H E T I C S
// NOTE: Add scanlines into the game for A E S T H E T I C S ===================================
if (game->play.state == FP_GameState_Play) {
Dqn_V2 screen_size = Dqn_V2_InitNx2(platform->core.window_size.w, platform->core.window_size.h);
Dqn_f32 scanline_gap = 4.0f;
Dqn_f32 scanline_thickness = 3.0f;
FP_GameRenderCameraFollowScanlines(renderer, screen_size, game->play.camera.world_pos, scanline_gap, scanline_thickness);
}
// NOTE: UI ====================================================================================
// NOTE: Render the other game state modes =====================================================
if (game->play.state == FP_GameState_IntroScreen || game->play.state == FP_GameState_WinGame || game->play.state == FP_GameState_LoseGame || game->play.state == FP_GameState_Pause) {
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
TELY_Render_RectColourV4(
renderer,
Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)platform->core.window_size.x, DQN_CAST(Dqn_f32)platform->core.window_size.y),
TELY_RenderShapeMode_Fill,
TELY_Colour_V4Alpha(TELY_COLOUR_BLACK_V4, 0.8f));
Dqn_V2I inset = platform->core.window_size * .05f;
Dqn_f32 min_inset = DQN_CAST(Dqn_f32)DQN_MIN(inset.x, inset.y);
Dqn_V2 draw_p = Dqn_V2_InitNx2(min_inset, min_inset);
TELY_Render_PushColourV4(renderer, TELY_COLOUR_WHITE_V4);
if (game->play.state == FP_GameState_IntroScreen) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Feely Pona"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to start"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
game->play.state = FP_GameState_Play;
} else if (game->play.state == FP_GameState_LoseGame) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry's heart has been crushed"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from the hoard of monsters"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Sayounara amigo"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
FP_PlayReset(game, platform);
} else if (game->play.state == FP_GameState_Pause) {
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Paused"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to resume"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
game->play.state = FP_GameState_Play;
} else {
DQN_ASSERT(game->play.state == FP_GameState_WinGame);
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Terry has been saved"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "from his terrible calamity"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "He lives for yet another day and another love"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to restart"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
FP_PlayReset(game, platform);
}
}
// NOTE: Debug UI ==============================================================================
if (game->play.debug_ui) {
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };

View File

@ -755,10 +755,6 @@ static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameEntityHandle sr
#endif
}
} break;
case FP_GameWaypointType_Offset: {
result = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle);
} break;
}
result += waypoint->offset;

View File

@ -76,7 +76,6 @@ 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
FP_GameWaypointType_ClosestSide, // Move to the side of the entity closest to us
FP_GameWaypointType_Offset, // Move to the designed offset from the entity
};
enum FP_GameDirection
@ -238,6 +237,7 @@ struct FP_GameEntity
uint32_t count_of_entities_targetting_sides[FP_GameDirection_Count];
FP_GameEntityHandle carried_monkey;
Dqn_FArray<FP_GameEntityHandle, 8> building_queue;
};
struct FP_GameEntityIterator
@ -290,6 +290,7 @@ enum FP_GameState
{
FP_GameState_IntroScreen,
FP_GameState_Play,
FP_GameState_Pause,
FP_GameState_WinGame,
FP_GameState_LoseGame,
};