From 4628731bef19e86c92c1da864c077b1933dd8a6d Mon Sep 17 00:00:00 2001 From: doyle Date: Sat, 7 Oct 2023 12:21:31 +1100 Subject: [PATCH] fp: Hook up the buildings to the merchant UI --- feely_pona.cpp | 219 ++++++++++++++++++++++++++++++++-------------- feely_pona_game.h | 3 +- 2 files changed, 155 insertions(+), 67 deletions(-) diff --git a/feely_pona.cpp b/feely_pona.cpp index 01f81e5..e56e143 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -5,7 +5,6 @@ Dqn_f32 const PHYSICS_STEP = 1 / 60.f; - Dqn_Rect FP_Game_GetBuildingPlacementRectForEntity(FP_Game *game, FP_GamePlaceableBuilding placeable_building, FP_GameEntityHandle handle) { Dqn_Rect result = {}; @@ -527,13 +526,18 @@ 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)) { - 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)) { - FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack); - } else if (acceleration_meters_per_s->x || acceleration_meters_per_s->y) { + if (game->active_menu == FP_GameActiveMenu_Nil) { + if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) || + TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_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)) { + FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack); + } + } + + + if (action->next_state == action->state && (acceleration_meters_per_s->x || acceleration_meters_per_s->y)) { FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Run); } } @@ -569,14 +573,18 @@ 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)) { - 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)) { - FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack); - } else if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_LeftControl) || - TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_A)) { + if (game->active_menu == FP_GameActiveMenu_Nil) { + if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) || + TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_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)) { + FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack); + } + } + + if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_LeftControl) || + TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_A)) { FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Dash); } } @@ -619,8 +627,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform case FP_GameDirection_Right: { dir_vector.x = +1.f; - entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x + entity->attack_box_size.w, - entity->local_hit_box_offset.y); + entity->attack_box_offset = Dqn_V2_InitNx2( + entity->local_hit_box_offset.x + entity->attack_box_size.w, + entity->local_hit_box_offset.y); } break; case FP_GameDirection_Up: { @@ -1708,7 +1717,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input } if (game->build_mode_can_place_building && - TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F)) { + TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) { if (placeable_building.type == FP_EntityType_ClubTerry) { FP_Entity_CreateClubTerry(game, placement_pos, "Club Terry"); } else if (placeable_building.type == FP_EntityType_ChurchTerry) { @@ -2196,11 +2205,13 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer) struct FP_MerchantToMenuMapping { FP_GameEntityHandle merchant; Dqn_String8 menu_anim; + Dqn_String8 building; + Dqn_V2 building_offset01; } merchants[] = { - {game->merchant_terry, g_anim_names.merchant_terry_menu}, - {game->merchant_graveyard, g_anim_names.merchant_graveyard_menu}, - {game->merchant_gym, g_anim_names.merchant_gym_menu}, - {game->merchant_phone_company, g_anim_names.merchant_phone_company_menu}, + {game->merchant_terry, g_anim_names.merchant_terry_menu, g_anim_names.club_terry_dark, Dqn_V2_InitNx2(0.015f, +0.04f)}, + {game->merchant_graveyard, g_anim_names.merchant_graveyard_menu, g_anim_names.airport_terry, Dqn_V2_InitNx2(0, -0.1f)}, + {game->merchant_gym, g_anim_names.merchant_gym_menu, g_anim_names.church_terry_dark, Dqn_V2_InitNx2(0.04f, -0.15f)}, + {game->merchant_phone_company, g_anim_names.merchant_phone_company_menu, g_anim_names.kennel_terry, Dqn_V2_InitNx2(0, +0)}, }; bool activated_merchant = false; @@ -2213,8 +2224,9 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer) continue; activated_merchant = true; - // NOTE: Render animated merchant menu - Dqn_Rect merchant_menu_rect = {}; + // NOTE: Render animated merchant menu ============================= + uint64_t const buy_duration_ms = 500; + Dqn_Rect merchant_menu_rect = {}; { FP_GameRenderSprite *sprite = &game->player_merchant_menu; if (!sprite->asset.anim || sprite->asset.anim->label != mapping.menu_anim) { @@ -2222,17 +2234,6 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer) sprite->started_at_clock_ms = game->clock_ms; } - bool trigger_buy_anim = false; - uint64_t buy_duration_ms = 500; - if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) { - game->player_trigger_purchase_timestamp = game->clock_ms + buy_duration_ms; - } else if (TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_J)) { - trigger_buy_anim = true; - if (game->clock_ms > game->player_trigger_purchase_timestamp) { - // TODO(doyle): Do buy logic - } - } - uint64_t elapsed_ms = game->clock_ms - sprite->started_at_clock_ms; uint16_t raw_anim_frame = DQN_CAST(uint16_t)(elapsed_ms / sprite->asset.anim->ms_per_frame); uint16_t anim_frame = raw_anim_frame % sprite->asset.anim->count; @@ -2252,40 +2253,126 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer) Dqn_V2_Zero /*rotate origin*/, 0.f /*rotation*/, TELY_COLOUR_WHITE_V4); - - if (trigger_buy_anim) { - uint64_t start_buy_time = game->player_trigger_purchase_timestamp - buy_duration_ms; - uint64_t elapsed_time = game->clock_ms - start_buy_time; - - Dqn_f32 buy_t = DQN_MIN(elapsed_time / DQN_CAST(Dqn_f32)buy_duration_ms, 1.f); - Dqn_Rect buy_lerp_rect = {}; - buy_lerp_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.68f, 0.215f)); - buy_lerp_rect.size.w = (merchant_menu_rect.size.w * 0.211f) * buy_t; - buy_lerp_rect.size.h = merchant_menu_rect.size.h * .611f; - - TELY_Render_RectColourV4(renderer, buy_lerp_rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, 0.5f)); - } } - // NOTE: Render the merchant button - TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.merchant_button_a); - Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index]; - Dqn_Rect dest_rect = {}; - dest_rect.size = button_rect.size * 1.5f; - dest_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.75f, 0.5f)); - TELY_Render_TextureColourV4(renderer, - game->atlas_sprite_sheet.tex_handle, - button_rect, - dest_rect, - Dqn_V2_Zero /*rotate origin*/, - 0.f /*rotation*/, - TELY_COLOUR_WHITE_V4); - TELY_Render_PushColourV4(renderer, TELY_COLOUR_WHITE_V4); TELY_Render_PushFont(renderer, game->talkco_font_large); - TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(dest_rect, Dqn_V2_InitNx2(0.5f, -1)), Dqn_V2_InitNx2(0.5, 0.f), "$2"); - TELY_Render_PopFont(renderer); - TELY_Render_PopColourV4(renderer); + DQN_DEFER { + TELY_Render_PopFont(renderer); + TELY_Render_PopColourV4(renderer); + }; + + // NOTE: Render the merchant button for buildings ================== + { + // NOTE: Buy trigger + animation =============================== + { + TELY_PlatformInputScanCode key = TELY_PlatformInputScanCode_J; + bool trigger_buy_anim = false; + if (TELY_Platform_InputScanCodeIsPressed(input, key)) { + game->player_trigger_purchase_building_timestamp = game->clock_ms + buy_duration_ms; + } else if (TELY_Platform_InputScanCodeIsDown(input, key)) { + trigger_buy_anim = true; + if (game->clock_ms > game->player_trigger_purchase_building_timestamp) { + // TODO(doyle): Do buy logic + } + } + + if (trigger_buy_anim) { + uint64_t start_buy_time = game->player_trigger_purchase_building_timestamp - buy_duration_ms; + uint64_t elapsed_time = game->clock_ms - start_buy_time; + + Dqn_f32 buy_t = DQN_MIN(elapsed_time / DQN_CAST(Dqn_f32)buy_duration_ms, 1.f); + Dqn_Rect buy_lerp_rect = {}; + buy_lerp_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.297f, 0.215f)); + buy_lerp_rect.size.w = (merchant_menu_rect.size.w * 0.38f) * buy_t; + buy_lerp_rect.size.h = merchant_menu_rect.size.h * .611f; + + TELY_Render_RectColourV4(renderer, buy_lerp_rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_BLUE_CADET_V4, 0.5f)); + } + } + + // NOTE: Render the (A) button ================================= + { + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.merchant_button_a); + Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + Dqn_Rect dest_rect = {}; + dest_rect.size = button_rect.size * 1.5f; + dest_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.345f, 0.5f)); + TELY_Render_TextureColourV4(renderer, + game->atlas_sprite_sheet.tex_handle, + button_rect, + dest_rect, + Dqn_V2_Zero /*rotate origin*/, + 0.f /*rotation*/, + TELY_COLOUR_WHITE_V4); + + TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(dest_rect, Dqn_V2_InitNx2(0.5f, -1)), Dqn_V2_InitNx2(0.5, 0.f), "$2"); + } + + // NOTE: Render the merchant shop item building ================ + { + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, mapping.building); + Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + Dqn_Rect dest_rect = {}; + dest_rect.size = tex_rect.size * 0.35f; + dest_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.42f, 0.25f) + mapping.building_offset01); + 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 the merchant button for buildings + { + // NOTE: Buy trigger + animation =============================== + { + TELY_PlatformInputScanCode key = TELY_PlatformInputScanCode_K; + bool trigger_buy_anim = false; + if (TELY_Platform_InputScanCodeIsPressed(input, key)) { + game->player_trigger_purchase_upgrade_timestamp = game->clock_ms + buy_duration_ms; + } else if (TELY_Platform_InputScanCodeIsDown(input, key)) { + trigger_buy_anim = true; + if (game->clock_ms > game->player_trigger_purchase_upgrade_timestamp) { + // TODO(doyle): Do buy logic + } + } + + if (trigger_buy_anim) { + uint64_t start_buy_time = game->player_trigger_purchase_upgrade_timestamp - buy_duration_ms; + uint64_t elapsed_time = game->clock_ms - start_buy_time; + + Dqn_f32 buy_t = DQN_MIN(elapsed_time / DQN_CAST(Dqn_f32)buy_duration_ms, 1.f); + Dqn_Rect buy_lerp_rect = {}; + buy_lerp_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.68f, 0.215f)); + buy_lerp_rect.size.w = (merchant_menu_rect.size.w * 0.211f) * buy_t; + buy_lerp_rect.size.h = merchant_menu_rect.size.h * .611f; + + TELY_Render_RectColourV4(renderer, buy_lerp_rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, 0.5f)); + } + } + + // NOTE: Render the (B) button ================================= + { + TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.merchant_button_b); + Dqn_Rect button_rect = game->atlas_sprite_sheet.rects.data[anim->index]; + Dqn_Rect dest_rect = {}; + dest_rect.size = button_rect.size * 1.5f; + dest_rect.pos = Dqn_Rect_InterpolatedPoint(merchant_menu_rect, Dqn_V2_InitNx2(0.75f, 0.5f)); + TELY_Render_TextureColourV4(renderer, + game->atlas_sprite_sheet.tex_handle, + button_rect, + dest_rect, + Dqn_V2_Zero /*rotate origin*/, + 0.f /*rotation*/, + TELY_COLOUR_WHITE_V4); + + TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(dest_rect, Dqn_V2_InitNx2(0.5f, -1)), Dqn_V2_InitNx2(0.5, 0.f), "$2"); + } + } } if (activated_merchant) { diff --git a/feely_pona_game.h b/feely_pona_game.h index c4a2632..c5f7ece 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -260,7 +260,8 @@ struct FP_Game FP_GameEntityHandle player; FP_GameRenderSprite player_merchant_menu; - uint64_t player_trigger_purchase_timestamp; + uint64_t player_trigger_purchase_upgrade_timestamp; + uint64_t player_trigger_purchase_building_timestamp; FP_GameEntityHandle merchant_terry; FP_GameEntityHandle merchant_graveyard;