From 206773607ca5286e122c71ff4847e3e784d1cc78 Mon Sep 17 00:00:00 2001 From: doyle Date: Mon, 23 Oct 2023 22:13:03 +1100 Subject: [PATCH] fp: Integrate new billboard --- Data/Textures/atlas.png | 4 +- Data/Textures/atlas.txt | 4 +- Data/Textures/atlas/map_billboard_build.png | 3 + Data/Textures/sprite_spec.txt | 4 +- feely_pona.cpp | 181 ++++++++++++-------- feely_pona.h | 1 + feely_pona_entity.cpp | 1 + feely_pona_entity.h | 1 + feely_pona_game.h | 23 +-- 9 files changed, 132 insertions(+), 90 deletions(-) create mode 100644 Data/Textures/atlas/map_billboard_build.png diff --git a/Data/Textures/atlas.png b/Data/Textures/atlas.png index 1fa157b..8fe9ac0 100644 --- a/Data/Textures/atlas.png +++ b/Data/Textures/atlas.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e37949880028de417355bb2b2cfba5d62996ead8a3518ed3b4a9583c274b481 -size 15251464 +oid sha256:1af25af25837f1833bcf5618465c6942069ba1a54fcaf4de8e5f5fd08e09a7de +size 15725606 diff --git a/Data/Textures/atlas.txt b/Data/Textures/atlas.txt index efdce85..cbfa084 100644 --- a/Data/Textures/atlas.txt +++ b/Data/Textures/atlas.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e825367e12d0e2f48c80c843bfe4faba80473d8fde2af14cfec407fde5f7579 -size 14174 +oid sha256:59fc17e448a908e169d82e560832ec6ed4ad178dedc62460ab78aca8d6467bde +size 14257 diff --git a/Data/Textures/atlas/map_billboard_build.png b/Data/Textures/atlas/map_billboard_build.png new file mode 100644 index 0000000..068617c --- /dev/null +++ b/Data/Textures/atlas/map_billboard_build.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf244e11436c5fca93c0527d089bf50f031460324ca842f64b0910fa37464ad5 +size 300287 diff --git a/Data/Textures/sprite_spec.txt b/Data/Textures/sprite_spec.txt index c5940f3..136519f 100644 --- a/Data/Textures/sprite_spec.txt +++ b/Data/Textures/sprite_spec.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ba632d5b14ef6b414f9d17fa86837a7e51d45fd62fc4152303c3620e8b7839e -size 2260 +oid sha256:380fbdd5e0ad67191e872da54b8dc83c2bcc2235536830d18a7f5f1619d3bef1 +size 2283 diff --git a/feely_pona.cpp b/feely_pona.cpp index be121cd..782a7cd 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -18,23 +18,23 @@ static FP_ParticleDescriptor FP_DefaultFloatUpParticleDescriptor(Dqn_String8 ani return result; } -static void FP_EmitParticle(FP_GamePlay *play, FP_ParticleDescriptor descriptor, Dqn_usize count) +static void FP_EmitParticle(FP_Game *game, FP_ParticleDescriptor descriptor, Dqn_usize count) { DQN_FOR_UINDEX (index, count) { - uint32_t particle_index = play->particle_next_index++ & (DQN_ARRAY_UCOUNT(play->particles) - 1); - FP_Particle *particle = play->particles + particle_index; + uint32_t particle_index = game->play.particle_next_index++ & (DQN_ARRAY_UCOUNT(game->play.particles) - 1); + FP_Particle *particle = game->play.particles + particle_index; if (particle->alive) continue; - particle->anim_name = descriptor.anim_name; + particle->anim_name = Dqn_String8_Copy(Dqn_Arena_Allocator(game->frame_arena), descriptor.anim_name); particle->alive = true; particle->pos = descriptor.pos; - particle->velocity.x = descriptor.velocity.x + (descriptor.velocity_variance.x * (Dqn_PCG32_NextF32(&play->rng) - 0.5f)); - particle->velocity.y = descriptor.velocity.y + (descriptor.velocity_variance.y * (Dqn_PCG32_NextF32(&play->rng) - 0.5f)); + particle->velocity.x = descriptor.velocity.x + (descriptor.velocity_variance.x * (Dqn_PCG32_NextF32(&game->play.rng) - 0.5f)); + particle->velocity.y = descriptor.velocity.y + (descriptor.velocity_variance.y * (Dqn_PCG32_NextF32(&game->play.rng) - 0.5f)); particle->colour_begin = descriptor.colour_begin; particle->colour_end = descriptor.colour_end; - particle->start_ms = play->clock_ms; - particle->end_ms = play->clock_ms + descriptor.duration_ms; + particle->start_ms = game->play.clock_ms; + particle->end_ms = game->play.clock_ms + descriptor.duration_ms; } } @@ -385,6 +385,7 @@ static void FP_PlayReset(FP_Game *game, TELY_Platform *platform) FP_Entity_CreateBillboard(game, Dqn_V2_InitNx2(2047, -720), FP_EntityBillboardState_RangeAttack, "Range Attack Billboard"); FP_Entity_CreateBillboard(game, Dqn_V2_InitNx2(-936, -500), FP_EntityBillboardState_Monkey, "Monkey Billboard"); FP_Entity_CreateBillboard(game, Dqn_V2_InitNx2(1898, 771), FP_EntityBillboardState_Strafe, "Strafe Billboard"); + FP_Entity_CreateBillboard(game, Dqn_V2_InitNx2(1068, 619), FP_EntityBillboardState_Build, "Build Billboard"); // NOTE: Camera ================================================================================ play->camera.world_pos = {}; @@ -2025,7 +2026,7 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput 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); + FP_EmitParticle(game, particle_desc, 3); } } @@ -2155,7 +2156,7 @@ static void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput particle_desc.colour_begin = TELY_COLOUR_WHITE_V4; particle_desc.colour_end = TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, 0.f); particle_desc.duration_ms = 1000; - FP_EmitParticle(&game->play, particle_desc, Dqn_PCG32_Range(&game->play.rng, 1, 3)); + FP_EmitParticle(game, particle_desc, Dqn_PCG32_Range(&game->play.rng, 1, 3)); // NOTE: God mode override ========================================================= if (game->play.heart == defender->handle) { @@ -2346,6 +2347,56 @@ static Dqn_String8 FP_ScanCodeToLabel(Dqn_Arena *arena, TELY_PlatformInputScanCo return result; } +static void FP_DrawBillboardKeyBindHint(TELY_Renderer *renderer, + TELY_Assets *assets, + FP_Game *game, + Dqn_usize player_index, + FP_GameControlMode mode, + FP_GameKeyBind key_bind, + Dqn_V2 draw_p, + bool draw_player_prefix) +{ + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 player_prefix = {}; + if (draw_player_prefix) + player_prefix = Dqn_String8_InitF(scratch.allocator, "P%zu ", player_index); + + if (mode == FP_GameControlMode_Gamepad) { + Dqn_String8 tex_name = {}; + if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_A) + tex_name = g_anim_names.merchant_button_a; + else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_B) + tex_name = g_anim_names.merchant_button_b; + else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_X) + tex_name = g_anim_names.merchant_button_x; + else if (key_bind.gamepad_key == TELY_PlatformInputGamepadKey_Y) + tex_name = g_anim_names.merchant_button_y; + + if (tex_name.size) { + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, tex_name); + Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + + Dqn_V2 text_size = TELY_Asset_MeasureText(TELY_Render_Font(renderer, assets), player_prefix); + TELY_Render_Text(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), player_prefix); + + Dqn_Rect gamepad_btn_rect = {}; + gamepad_btn_rect.size = button_rect.size; + gamepad_btn_rect.pos = Dqn_V2_InitNx2(draw_p.x + (text_size.x * 1.25f), draw_p.y - button_rect.size.y); + + TELY_Render_TextureColourV4(renderer, + game->atlas_sprite_sheet.tex_handle, + button_rect, + gamepad_btn_rect, + Dqn_V2_Zero /*rotate origin*/, + 0.f /*rotation*/, + TELY_COLOUR_WHITE_V4); + } + } else { + Dqn_String8 key_bind_label = FP_ScanCodeToLabel(scratch.arena, key_bind.scan_code); + TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), "%.*s%.*s", DQN_STRING_FMT(player_prefix), DQN_STRING_FMT(key_bind_label)); + } +} + static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer, TELY_Audio *audio) { Dqn_Profiler_ZoneScopeWithIndex("FP_Render", FP_ProfileZone_FPRender); @@ -2764,90 +2815,74 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren } if (entity->type == FP_EntityType_Billboard) { + TELY_Render_PushFont(renderer, game->talkco_font); + DQN_DEFER { TELY_Render_PopFont(renderer); }; DQN_FOR_UINDEX (player_index, game->play.players.size) { FP_GameEntityHandle player_handle = game->play.players.data[player_index]; FP_GameEntity const *player = FP_Game_GetEntity(game, player_handle); FP_GameControls const *controls = &player->controls; - - FP_EntityBillboardState state = DQN_CAST(FP_EntityBillboardState) entity->action.state; - FP_GameKeyBind const *key_bind = nullptr; - Dqn_V2 draw_p = {}; - Dqn_V4 colour = TELY_COLOUR_BLACK_V4; - + FP_EntityBillboardState state = DQN_CAST(FP_EntityBillboardState) entity->action.state; switch (state) { case FP_EntityBillboardState_Attack: { - key_bind = &controls->attack; - draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.6f, 0.2f)); - colour = colour_accent_yellow; + Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.6f, 0.2f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, colour_accent_yellow); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->attack, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); } break; case FP_EntityBillboardState_Dash: { - key_bind = &controls->dash; - draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.505f, -0.08f)); - colour = TELY_Colour_V4InitRGBU32(0xFFE726); + Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.505f, -0.08f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFFE726)); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->dash, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); } break; case FP_EntityBillboardState_Monkey: { } break; case FP_EntityBillboardState_RangeAttack: { - key_bind = &controls->range_attack; - draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.20f, -0.13f)); - colour = TELY_Colour_V4InitRGBU32(0x364659); + Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.20f, -0.13f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0x364659)); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->range_attack, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); } break; case FP_EntityBillboardState_Strafe: { - key_bind = &controls->strafe; - draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.36f, -0.15f)); - colour = TELY_Colour_V4InitRGBU32(0xFF68A8); - } break; - } - draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; - - if (key_bind) { - TELY_Render_PushColourV4(renderer, colour); - TELY_Render_PushFont(renderer, game->talkco_font); - DQN_DEFER { - TELY_Render_PopFont(renderer); + Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.36f, -0.15f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8)); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->strafe, draw_p, true /*draw_player_prefix*/); TELY_Render_PopColourV4(renderer); - }; + } break; - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_String8 player_prefix = Dqn_String8_InitF(scratch.allocator, "P%zu", player_index); - if (controls->mode == FP_GameControlMode_Gamepad) { - Dqn_String8 tex_name = {}; - if (key_bind->gamepad_key == TELY_PlatformInputGamepadKey_A) - tex_name = g_anim_names.merchant_button_a; - else if (key_bind->gamepad_key == TELY_PlatformInputGamepadKey_B) - tex_name = g_anim_names.merchant_button_b; - else if (key_bind->gamepad_key == TELY_PlatformInputGamepadKey_X) - tex_name = g_anim_names.merchant_button_x; - else if (key_bind->gamepad_key == TELY_PlatformInputGamepadKey_Y) - tex_name = g_anim_names.merchant_button_y; + case FP_EntityBillboardState_Build: { + Dqn_V2 draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.065f, 0.2f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, colour_accent_yellow); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->build_mode, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); - if (tex_name.size) { - TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, tex_name); - Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.35f, 0.2f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8)); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->move_building_ui_cursor_left, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); - Dqn_V2 text_size = TELY_Asset_MeasureText(TELY_Render_Font(renderer, assets), player_prefix); - TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), "P%zu", player_index); + draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.44f, 0.2f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_Colour_V4InitRGBU32(0xFF68A8)); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->move_building_ui_cursor_right, draw_p, false /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); - Dqn_Rect gamepad_btn_rect = {}; - gamepad_btn_rect.size = button_rect.size; - gamepad_btn_rect.pos = Dqn_V2_InitNx2(draw_p.x + (text_size.x * 1.25f), draw_p.y - button_rect.size.y); - - TELY_Render_TextureColourV4(renderer, - game->atlas_sprite_sheet.tex_handle, - button_rect, - gamepad_btn_rect, - Dqn_V2_Zero /*rotate origin*/, - 0.f /*rotation*/, - TELY_COLOUR_WHITE_V4); - } - } else { - Dqn_String8 key_bind_label = FP_ScanCodeToLabel(scratch.arena, key_bind->scan_code); - TELY_Render_TextF(renderer, draw_p, Dqn_V2_InitNx2(0, +1.f), "%.*s %.*s", DQN_STRING_FMT(player_prefix), DQN_STRING_FMT(key_bind_label)); - } + draw_p = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0.665f, 0.2f)); + draw_p.y += TELY_Render_FontHeight(renderer, assets) * player_index; + TELY_Render_PushColourV4(renderer, TELY_COLOUR_BLACK_V4); + FP_DrawBillboardKeyBindHint(renderer, assets, game, player_index, controls->mode, controls->attack, draw_p, true /*draw_player_prefix*/); + TELY_Render_PopColourV4(renderer); + } break; } } } @@ -3188,7 +3223,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren (*mapping.inventory_count)++; dollar_buy_particle.pos = dollar_text_label_pos; - FP_EmitParticle(&game->play, dollar_buy_particle, 1); + FP_EmitParticle(game, dollar_buy_particle, 1); } } else { game->play.player_trigger_purchase_building_timestamp = UINT64_MAX; @@ -3311,7 +3346,7 @@ static void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *ren TELY_Audio_Play(audio, game->audio[FP_GameAudio_Ching], 1.f); dollar_buy_particle.pos = dollar_text_label_pos; - FP_EmitParticle(&game->play, dollar_buy_particle, 1); + FP_EmitParticle(game, dollar_buy_particle, 1); if (mapping.merchant == game->play.merchant_terry) { player->base_attack += DQN_CAST(uint32_t)(FP_DEFAULT_DAMAGE * 1.2f); diff --git a/feely_pona.h b/feely_pona.h index 93ad21d..6b834cd 100644 --- a/feely_pona.h +++ b/feely_pona.h @@ -72,6 +72,7 @@ struct FP_GlobalAnimations Dqn_String8 map_billboard_monkey = DQN_STRING8("map_billboard_monkey"); Dqn_String8 map_billboard_range_attack = DQN_STRING8("map_billboard_range_attack"); Dqn_String8 map_billboard_strafe = DQN_STRING8("map_billboard_strafe"); + Dqn_String8 map_billboard_build = DQN_STRING8("map_billboard_build"); Dqn_String8 map_police = DQN_STRING8("map_police"); Dqn_String8 merchant_button_a = DQN_STRING8("merchant_button_a"); diff --git a/feely_pona_entity.cpp b/feely_pona_entity.cpp index 1aa8cf8..e1211c7 100644 --- a/feely_pona_entity.cpp +++ b/feely_pona_entity.cpp @@ -400,6 +400,7 @@ static FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType case FP_EntityBillboardState_Monkey: result.anim_name = g_anim_names.map_billboard_monkey; break; case FP_EntityBillboardState_RangeAttack: result.anim_name = g_anim_names.map_billboard_range_attack; break; case FP_EntityBillboardState_Strafe: result.anim_name = g_anim_names.map_billboard_strafe; break; + case FP_EntityBillboardState_Build: result.anim_name = g_anim_names.map_billboard_build; result.height.meters = 6.25f; break; } } break; diff --git a/feely_pona_entity.h b/feely_pona_entity.h index 585694f..5761804 100644 --- a/feely_pona_entity.h +++ b/feely_pona_entity.h @@ -137,6 +137,7 @@ enum FP_EntityBillboardState FP_EntityBillboardState_Monkey, FP_EntityBillboardState_RangeAttack, FP_EntityBillboardState_Strafe, + FP_EntityBillboardState_Build, }; struct FP_EntityRenderData diff --git a/feely_pona_game.h b/feely_pona_game.h index 0b69aec..9b620e1 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -431,17 +431,18 @@ struct FP_GamePlay 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_AssetFontHandle talkco_font_xlarge; - TELY_AssetAudioHandle audio[FP_GameAudio_Count]; - TELY_AssetSpriteSheet atlas_sprite_sheet; - TELY_RFui rfui; - FP_GamePlay play; + 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_AssetFontHandle talkco_font_xlarge; + TELY_AssetAudioHandle audio[FP_GameAudio_Count]; + TELY_AssetSpriteSheet atlas_sprite_sheet; + TELY_RFui rfui; + FP_GamePlay play; + Dqn_Arena *frame_arena; }; struct FP_GameAStarNode