From b78338bafc857d51e1e3dbc17f66acfbb75f0b6f Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 22 Oct 2023 22:41:21 +1100 Subject: [PATCH] fp: Draw the particles for drunk-ness and church-ness --- feely_pona.cpp | 97 +++++++++++++++++++++++++++++++++++++++-------- feely_pona_game.h | 2 + 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/feely_pona.cpp b/feely_pona.cpp index e2576f3..c177683 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -14,6 +14,19 @@ struct FP_ParticleDescriptor Dqn_usize duration_ms; }; +static FP_ParticleDescriptor FP_DefaultFloatUpParticleDescriptor(Dqn_String8 anim_name, Dqn_usize duration_ms) +{ + FP_ParticleDescriptor result = {}; + result.anim_name = anim_name; + result.velocity.y = -16.f; + result.velocity_variance.y = (result.velocity.y * .5f); + result.velocity_variance.x = DQN_ABS(result.velocity.y); + result.colour_begin = TELY_COLOUR_WHITE_V4; + result.colour_end = TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, 0.f); + result.duration_ms = duration_ms; + return result; +} + static void FP_EmitParticle(FP_GamePlay *play, FP_ParticleDescriptor descriptor, Dqn_usize count) { DQN_FOR_UINDEX (index, count) { @@ -1026,6 +1039,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform if (entering_new_state) { uint64_t duration_ms = 5000; FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite); + TELY_Audio_Play(audio, game->audio[FP_GameAudio_Plane], 1.f); } if (action_has_finished) { @@ -1173,6 +1187,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform patron->flags &= ~(FP_GameEntityFlag_OccupiedInBuilding | FP_GameEntityFlag_RespondsToBuildings); patron->faction = FP_GameEntityFaction_Friendly; patron->converted_faction = true; + TELY_Audio_Play(audio, game->audio[FP_GameAudio_Church], 1.f); } entity->building_patron = {}; FP_Game_EntityTransitionState(game, entity, FP_EntityChurchTerryState_Idle); @@ -2031,6 +2046,19 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input } entity->trauma01 = DQN_MAX(0.f, entity->trauma01 - 0.05f); + Dqn_Rect world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); + + if (entity->is_drunk) { + if (game->play.clock_ms > entity->drunk_particles_end_ms) { + Dqn_usize duration_ms = 2000; + FP_ParticleDescriptor particle_desc = FP_DefaultFloatUpParticleDescriptor(g_anim_names.particle_drunk, duration_ms); + particle_desc.velocity_variance.x *= 2.f; + particle_desc.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.5f, -0.1f)); + particle_desc.colour_begin.a = .8f; + entity->drunk_particles_end_ms = game->play.clock_ms + duration_ms; + FP_EmitParticle(&game->play, particle_desc, 3); + } + } // NOTE: Derive dynmamic bounding boxes ==================================================== if (entity->flags & FP_GameEntityFlag_DeriveHitBoxFromChildrenBoundingBox) { @@ -2490,11 +2518,6 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer, Dqn_V2_Zero /*rotate origin*/, 0.f /*rotate radians*/, sprite_colour); - - if (entity->converted_faction) { - Dqn_V2 label_p = Dqn_Rect_InterpolatedPoint(dest_rect, Dqn_V2_InitNx2(0, -0.25f)); - TELY_Render_TextF(renderer, label_p, Dqn_V2_InitNx2(0.f, 0.1f), "CONVERTED"); - } } DQN_FOR_UINDEX(anim_index, entity->extra_cosmetic_anims.size) { @@ -2547,6 +2570,57 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer, TELY_COLOUR_WHITE_V4); } + if (entity->is_drunk) { + bool show_martini = entity->handle.id & 1; + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, show_martini ? g_anim_names.particle_drunk_martini : g_anim_names.particle_drunk_bottle); + Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + Dqn_Rect dest_rect = {}; + dest_rect.size = tex_rect.size; + if (show_martini) { + dest_rect.size *= 1.5f; + dest_rect.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, + Dqn_V2_InitNx2(0.0f, 0.0f)) - (Dqn_V2_InitNx2(dest_rect.size.x * .6f, dest_rect.size.y * .7f)); + dest_rect.pos.y += (DQN_SINF(DQN_CAST(Dqn_f32)input->timer_s * 2.f) + 1.f / 2.f) * dest_rect.size.y * .005f; + } else { + dest_rect.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, + Dqn_V2_InitNx2(0.0f, 0.0f)) - (Dqn_V2_InitNx2(dest_rect.size.x * .7f, dest_rect.size.y * .9f)); + } + + dest_rect.pos.y += (DQN_SINF(DQN_CAST(Dqn_f32)input->timer_s * 2.f) + 1.f / 2.f) * dest_rect.size.y * .1f; + + 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); + } + + if (entity->converted_faction) { + bool show_halo = entity->handle.id & 1; + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, show_halo ? g_anim_names.particle_church_halo : g_anim_names.particle_church_cross); + Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + Dqn_Rect dest_rect = {}; + dest_rect.size = tex_rect.size; + if (show_halo) { + dest_rect.size *= .6f; + dest_rect.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, + Dqn_V2_InitNx2(0.5f, 0.0f)) - (Dqn_V2_InitNx2(dest_rect.size.x * .5f, dest_rect.size.y * 1.2f)); + } else { + dest_rect.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, + Dqn_V2_InitNx2(0.5f, 0.0f)) - (Dqn_V2_InitNx2(dest_rect.size.x * .5f, dest_rect.size.y * .9f)); + } + + 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); + } + if (entity->handle != game->play.heart && entity->hp != entity->hp_cap && entity->hp) { // NOTE: We don't draw health bar for the player either bool current_entity_is_a_player = false; @@ -2906,18 +2980,9 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer, } // NOTE: Render the player(s) HUD and merchant menu interaction ============================ - FP_ParticleDescriptor dollar_buy_particle = {}; - { - dollar_buy_particle.anim_name = g_anim_names.particle_purchase; - dollar_buy_particle.velocity.y = -16.f; - dollar_buy_particle.velocity_variance.y = (dollar_buy_particle.velocity.y * .5f); - dollar_buy_particle.velocity_variance.x = DQN_ABS(dollar_buy_particle.velocity.y); - dollar_buy_particle.colour_begin = TELY_COLOUR_WHITE_V4; - dollar_buy_particle.colour_end = TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, 0.f); - dollar_buy_particle.duration_ms = 2000; - } + FP_ParticleDescriptor dollar_buy_particle = FP_DefaultFloatUpParticleDescriptor(g_anim_names.particle_purchase, 2000 /*duration*/); + Dqn_Rect first_player_avatar_rect = {}; - Dqn_Rect first_player_avatar_rect = {}; DQN_FOR_UINDEX (player_index, game->play.players.size) { FP_GameEntityHandle player_handle = game->play.players.data[player_index]; FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); diff --git a/feely_pona_game.h b/feely_pona_game.h index d082366..0b69aec 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -271,6 +271,8 @@ struct FP_GameEntity uint32_t base_attack; bool is_drunk; + Dqn_usize drunk_particles_end_ms; + bool converted_faction; FP_GameEntityFaction faction;