fp: Add perry splash screen on joining the fight

This commit is contained in:
doyle 2023-10-22 02:14:01 +11:00
parent 2b9925311f
commit 3b8a0d483f
7 changed files with 114 additions and 16 deletions

BIN
Data/Textures/atlas.png (Stored with Git LFS)

Binary file not shown.

BIN
Data/Textures/atlas.txt (Stored with Git LFS)

Binary file not shown.

BIN
Data/Textures/atlas/intro_screen_perry_joins_the_fight.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Data/Textures/sprite_spec.txt (Stored with Git LFS)

Binary file not shown.

View File

@ -127,6 +127,7 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
FP_GameEntityHandle player = play->players.data[play->players.size - 1];
Dqn_V2 player_pos = FP_Game_CalcEntityWorldPos(game, player);
terry_handle = FP_Entity_CreatePerry(game, player_pos, "Perry");
game->play.perry_joined = FP_GamePerryJoins_Enters;
} else {
terry_handle = FP_Entity_CreateTerry(game, Dqn_V2_InitNx2(1380, 11), "Perry");
}
@ -1294,9 +1295,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate);
game->play.update_counter++;
game->play.clock_ms = DQN_CAST(uint64_t)(platform->input.timer_s * 1000.f);
Dqn_ProfilerZone update_zone = Dqn_Profiler_BeginZoneWithIndex(DQN_STRING8("FP_Update: Entity loop"), FP_ProfileZone_FPUpdate_EntityLoop);
if (game->play.state == FP_GameState_Play) {
if (game->play.state == FP_GameState_Play && game->play.perry_joined != FP_GamePerryJoins_Enters) {
game->play.clock_ms = DQN_CAST(uint64_t)(platform->input.timer_s * 1000.f);
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'
@ -2176,6 +2177,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
game->play.state = FP_GameState_LoseGame;
}
game->play.global_camera_trauma01 = DQN_MAX(0.f, game->play.global_camera_trauma01 - 0.05f);
// NOTE: Camera ================================================================================
FP_GamePlay *play = &game->play;
@ -2261,6 +2264,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
// NOTE: The heart shake is trauma^3 to emphasise the severity of losing heart health
FP_GameEntity *heart = FP_Game_GetEntity(game, game->play.heart);
trauma01 = DQN_MAX(trauma01, DQN_SQUARED(heart->trauma01) * heart->trauma01);
trauma01 = DQN_MAX(trauma01, DQN_SQUARED(game->play.global_camera_trauma01));
// NOTE: Calculate camera position based on camera shake
Dqn_f32 max_shake_dist = 400.f;
@ -2273,7 +2277,6 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
shake_camera.world_pos += shake_offset * interp_rate;
}
FP_GameCameraM2x3 camera_xforms = FP_Game_CameraModelViewM2x3(shake_camera);
TELY_Render_PushTransform(renderer, camera_xforms.model_view);
Dqn_V2 world_mouse_p = Dqn_M2x3_MulV2(camera_xforms.view_model, input->mouse_p);
@ -2681,6 +2684,81 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
}
// NOTE: Draw perry ============================================================================
if (game->play.perry_joined == FP_GamePerryJoins_Enters) {
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
// NOTE: Shake the world ===================================================================
Dqn_Rect window_rect = {};
window_rect.size = Dqn_V2_InitV2I(platform->core.window_size);
Dqn_f32 tex_scalar = {};
{
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.intro_screen_terry);
Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index];
Dqn_f32 desired_width = window_rect.size.x * .25f;
tex_scalar = desired_width / tex_rect.size.w;
}
game->play.perry_join_bg_alpha += (1.f - game->play.perry_join_bg_alpha) * (DQN_CAST(Dqn_f32)input->delta_s * 8.f);
game->play.perry_join_bg_alpha = DQN_MIN(game->play.perry_join_bg_alpha, .8f);
TELY_Render_RectColourV4(renderer,
window_rect,
TELY_RenderShapeMode_Fill,
TELY_Colour_V4Alpha(TELY_COLOUR_BLACK_V4, game->play.perry_join_bg_alpha));
if (game->play.perry_join_bg_alpha > 0.5f) {
if (!game->play.perry_join_splash_screen_shake_triggered) {
game->play.global_camera_trauma01 = 1.f;
game->play.perry_join_splash_screen_shake_triggered = true;
game->play.perry_join_flash_alpha = 1.f;
game->play.perry_join_splash_screen_end_ms = DQN_CAST(uint64_t)((DQN_CAST(Dqn_f32)input->timer_s * 1000.f) + 2000);
}
}
if (game->play.perry_join_splash_screen_shake_triggered) {
game->play.perry_join_flash_alpha -= game->play.perry_join_bg_alpha * (DQN_CAST(Dqn_f32)input->delta_s * 4.f);
game->play.perry_join_flash_alpha = DQN_MAX(game->play.perry_join_flash_alpha, .0f);
TELY_Render_RectColourV4(renderer,
window_rect,
TELY_RenderShapeMode_Fill,
TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, game->play.perry_join_flash_alpha));
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.intro_screen_perry_joins_the_fight);
Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index];
Dqn_f32 sin_t = (DQN_SINF(DQN_CAST(Dqn_f32)input->timer_s * 3.f) + 1) / 2.f;
Dqn_Rect dest_rect = {};
dest_rect.size = tex_rect.size * (tex_scalar * 1.5f) + (tex_rect.size * (0.005f * sin_t));
dest_rect.pos = Dqn_Rect_InterpolatedPoint(window_rect, Dqn_V2_InitNx2(1, 1)) - dest_rect.size;
Dqn_f32 max_shake_dist = 50.f;
Dqn_f32 half_shake_dist = max_shake_dist * .5f;
Dqn_V2 shake_offset = {};
shake_offset.x = (Dqn_PCG32_NextF32(&game->play.rng) * max_shake_dist - half_shake_dist) * game->play.global_camera_trauma01;
shake_offset.y = (Dqn_PCG32_NextF32(&game->play.rng) * max_shake_dist - half_shake_dist) * game->play.global_camera_trauma01;
dest_rect.pos += shake_offset;
if ((input->timer_s * 1000) > (game->play.perry_join_splash_screen_end_ms)) {
game->play.perry_join_splash_pos_offset.x -= dest_rect.size.x * (12.f * DQN_CAST(Dqn_f32)input->delta_s);
dest_rect.pos += game->play.perry_join_splash_pos_offset;
if (dest_rect.pos.x < -dest_rect.size.x)
game->play.perry_joined = FP_GamePerryJoins_PostEnter;
}
TELY_Render_TextureColourV4(renderer,
game->atlas_sprite_sheet.tex_handle,
tex_rect,
dest_rect,
Dqn_V2_Zero /*rotate origin*/,
0.f /*rotation*/,
TELY_COLOUR_WHITE_V4);
}
}
// NOTE: Render overlay UI =====================================================================
if (!game->play.debug_hide_hud && (game->play.state == FP_GameState_Pause || game->play.state == FP_GameState_Play)) {
@ -3519,6 +3597,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
0.f /*rotation*/,
TELY_COLOUR_WHITE_V4);
}
} else {
// NOTE: Draw end screen logo ======================================================
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.end_screen);

View File

@ -62,6 +62,7 @@ struct FP_GlobalAnimations
Dqn_String8 intro_screen_subtitle = DQN_STRING8("intro_screen_subtitle");
Dqn_String8 intro_screen_terry = DQN_STRING8("intro_screen_terry");
Dqn_String8 intro_screen_title = DQN_STRING8("intro_screen_title");
Dqn_String8 intro_screen_perry_joins_the_fight = DQN_STRING8("intro_screen_perry_joins_the_fight");
Dqn_String8 kennel_terry = DQN_STRING8("kennel_terry");

View File

@ -342,6 +342,13 @@ enum FP_GameState
FP_GameState_LoseGame,
};
enum FP_GamePerryJoined
{
FP_GamePerryJoins_NotYet,
FP_GamePerryJoins_Enters,
FP_GamePerryJoins_PostEnter,
};
struct FP_GamePlay
{
TELY_ChunkPool *chunk_pool;
@ -392,7 +399,15 @@ struct FP_GamePlay
uint32_t enemies_spawned_this_wave;
uint64_t wave_cooldown_timestamp_ms;
Dqn_f32 global_camera_trauma01;
FP_GameState state;
FP_GamePerryJoined perry_joined;
Dqn_f32 perry_join_bg_alpha;
Dqn_f32 perry_join_flash_alpha;
bool perry_join_splash_screen_shake_triggered;
Dqn_V2 perry_join_splash_screen_pos;
uint64_t perry_join_splash_screen_end_ms;
Dqn_V2 perry_join_splash_pos_offset;
};
struct FP_Game