fp: Add inventory and consume coins on building purchase
This commit is contained in:
parent
4628731bef
commit
fd0612ac1c
153
feely_pona.cpp
153
feely_pona.cpp
@ -1682,11 +1682,23 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
if (entity->flags & FP_GameEntityFlag_CameraTracking)
|
||||
game->camera.world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle) - Dqn_V2_InitV2I(platform->core.window_size) * .5f;
|
||||
|
||||
game->build_mode_can_place_building = false;
|
||||
if (game->active_menu == FP_GameActiveMenu_Build) {
|
||||
FP_GamePlaceableBuilding placeable_building = PLACEABLE_BUILDINGS[game->build_mode_building_index];
|
||||
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, placeable_building, entity->handle);
|
||||
Dqn_V2 placement_pos = Dqn_Rect_Center(dest_rect);
|
||||
FP_GamePlaceableBuilding placeable_building = PLACEABLE_BUILDINGS[game->build_mode_building_index];
|
||||
game->build_mode_can_place_building = false;
|
||||
|
||||
uint8_t *inventory_count = nullptr;
|
||||
if (placeable_building.type == FP_EntityType_ChurchTerry)
|
||||
inventory_count = &entity->inventory.churchs;
|
||||
else if (placeable_building.type == FP_EntityType_KennelTerry)
|
||||
inventory_count = &entity->inventory.kennels;
|
||||
else if (placeable_building.type == FP_EntityType_ClubTerry)
|
||||
inventory_count = &entity->inventory.clubs;
|
||||
else if (placeable_building.type == FP_EntityType_AirportTerry)
|
||||
inventory_count = &entity->inventory.airports;
|
||||
|
||||
bool have_building_inventory = inventory_count && (*inventory_count) > 0;
|
||||
if (have_building_inventory && game->active_menu == FP_GameActiveMenu_Build) {
|
||||
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, placeable_building, entity->handle);
|
||||
Dqn_V2 placement_pos = Dqn_Rect_Center(dest_rect);
|
||||
|
||||
for (FP_GameEntityIterator zone_it = {};
|
||||
FP_Game_DFSPreOrderWalkEntityTree(game, &zone_it, game->root_entity);
|
||||
@ -1728,6 +1740,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
DQN_ASSERT(placeable_building.type == FP_EntityType_KennelTerry);
|
||||
FP_Entity_CreateKennelTerry(game, placement_pos, "Kennel Terry");
|
||||
}
|
||||
|
||||
(*inventory_count)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2203,15 +2217,17 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
Dqn_V2 player_pos = FP_Game_CalcEntityWorldPos(game, game->player);
|
||||
{
|
||||
struct FP_MerchantToMenuMapping {
|
||||
FP_GameEntityHandle merchant;
|
||||
Dqn_String8 menu_anim;
|
||||
Dqn_String8 building;
|
||||
Dqn_V2 building_offset01;
|
||||
FP_GameEntityHandle merchant;
|
||||
Dqn_String8 menu_anim;
|
||||
Dqn_String8 building;
|
||||
Dqn_V2 building_offset01;
|
||||
uint8_t *inventory_count;
|
||||
uint32_t *base_price;
|
||||
} merchants[] = {
|
||||
{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)},
|
||||
{game->merchant_terry, g_anim_names.merchant_terry_menu, g_anim_names.club_terry_dark, Dqn_V2_InitNx2(0.015f, +0.04f), &player->inventory.clubs, &player->inventory.clubs_base_price},
|
||||
{game->merchant_graveyard, g_anim_names.merchant_graveyard_menu, g_anim_names.church_terry_dark, Dqn_V2_InitNx2(0.04f, -0.15f), &player->inventory.churchs, &player->inventory.churchs_base_price},
|
||||
{game->merchant_gym, g_anim_names.merchant_gym_menu, g_anim_names.kennel_terry, Dqn_V2_InitNx2(0, +0), &player->inventory.kennels, &player->inventory.kennels_base_price},
|
||||
{game->merchant_phone_company, g_anim_names.merchant_phone_company_menu, g_anim_names.airport_terry, Dqn_V2_InitNx2(0, -0.1f), &player->inventory.airports, &player->inventory.airports_base_price},
|
||||
};
|
||||
|
||||
bool activated_merchant = false;
|
||||
@ -2222,11 +2238,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
|
||||
if (dist_squared > DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4)))
|
||||
continue;
|
||||
activated_merchant = true;
|
||||
|
||||
// NOTE: Render animated merchant menu =============================
|
||||
uint64_t const buy_duration_ms = 500;
|
||||
Dqn_Rect merchant_menu_rect = {};
|
||||
activated_merchant = true;
|
||||
Dqn_Rect merchant_menu_rect = {};
|
||||
{
|
||||
FP_GameRenderSprite *sprite = &game->player_merchant_menu;
|
||||
if (!sprite->asset.anim || sprite->asset.anim->label != mapping.menu_anim) {
|
||||
@ -2263,35 +2278,51 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
};
|
||||
|
||||
// NOTE: Render the merchant button for buildings ==================
|
||||
uint64_t const buy_duration_ms = 500;
|
||||
bool const have_enough_coins = player->coins >= *mapping.base_price;
|
||||
{
|
||||
// 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 (have_enough_coins) {
|
||||
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)
|
||||
game->player_trigger_purchase_building_timestamp = game->clock_ms;
|
||||
} else if (TELY_Platform_InputScanCodeIsReleased(input, key)) {
|
||||
if (game->clock_ms > game->player_trigger_purchase_building_timestamp) {
|
||||
if (mapping.inventory_count) {
|
||||
player->coins -= *mapping.base_price;
|
||||
*mapping.base_price *= 2;
|
||||
(*mapping.inventory_count)++;
|
||||
}
|
||||
} else {
|
||||
game->player_trigger_purchase_building_timestamp = UINT64_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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 =================================
|
||||
Dqn_V4 tex_mod_colour = have_enough_coins ? TELY_COLOUR_WHITE_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, .5f);
|
||||
{
|
||||
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];
|
||||
@ -2304,9 +2335,9 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
dest_rect,
|
||||
Dqn_V2_Zero /*rotate origin*/,
|
||||
0.f /*rotation*/,
|
||||
TELY_COLOUR_WHITE_V4);
|
||||
tex_mod_colour);
|
||||
|
||||
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_TextF(renderer, Dqn_Rect_InterpolatedPoint(dest_rect, Dqn_V2_InitNx2(0.5f, -1)), Dqn_V2_InitNx2(0.5, 0.f), "$%u", *mapping.base_price);
|
||||
}
|
||||
|
||||
// NOTE: Render the merchant shop item building ================
|
||||
@ -2322,7 +2353,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
dest_rect,
|
||||
Dqn_V2_Zero /*rotate origin*/,
|
||||
0.f /*rotation*/,
|
||||
TELY_COLOUR_WHITE_V4);
|
||||
tex_mod_colour);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2385,27 +2416,26 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
}
|
||||
|
||||
// NOTE: Render player avatar HUD ==========================================
|
||||
Dqn_f32 ui_start_y = 32.f;
|
||||
Dqn_Rect player_avatar_rect = {};
|
||||
player_avatar_rect.pos = Dqn_V2_InitNx1(32.f);
|
||||
{
|
||||
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
|
||||
DQN_DEFER { TELY_Render_PopTransform(renderer); };
|
||||
|
||||
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, FP_EntityType_Terry, FP_EntityTerryState_Idle, FP_GameDirection_Down);
|
||||
Dqn_Rect dest = {};
|
||||
dest.size = render_data.render_size;
|
||||
dest.pos.y = ui_start_y;
|
||||
dest.pos.x = ui_start_y;
|
||||
player_avatar_rect.size = render_data.render_size;
|
||||
|
||||
TELY_Render_TextureColourV4(renderer,
|
||||
render_data.sheet->tex_handle,
|
||||
render_data.sheet_rect,
|
||||
dest,
|
||||
player_avatar_rect,
|
||||
Dqn_V2_Zero,
|
||||
0.f,
|
||||
TELY_COLOUR_WHITE_V4);
|
||||
|
||||
TELY_Render_PushFont(renderer, game->talkco_font);
|
||||
Dqn_V2 next_pos = Dqn_Rect_InterpolatedPoint(dest, Dqn_V2_InitNx2(1.f, 0));
|
||||
DQN_DEFER { TELY_Render_PopFont(renderer); };
|
||||
Dqn_V2 next_pos = Dqn_Rect_InterpolatedPoint(player_avatar_rect, Dqn_V2_InitNx2(1.f, 0));
|
||||
TELY_Render_TextF(renderer, next_pos, Dqn_V2_Zero, "Terry");
|
||||
|
||||
Dqn_f32 font_height = TELY_Render_FontHeight(renderer, &platform->assets);
|
||||
@ -2432,16 +2462,14 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
|
||||
next_pos.y += font_height;
|
||||
TELY_Render_TextF(renderer, next_pos, Dqn_V2_Zero, "[J|K] Melee/Range");
|
||||
|
||||
TELY_Render_PopFont(renderer);
|
||||
}
|
||||
|
||||
if (!FP_Game_IsNilEntityHandle(game, game->clicked_entity) && game->active_menu == FP_GameActiveMenu_Build) {
|
||||
if (!FP_Game_IsNilEntityHandle(game, game->clicked_entity)) {
|
||||
// NOTE: Render building blueprint =========================================================
|
||||
{
|
||||
if (game->active_menu == FP_GameActiveMenu_Build) {
|
||||
FP_GameEntity *entity = FP_Game_GetEntity(game, game->clicked_entity);
|
||||
FP_GamePlaceableBuilding placeable_building = PLACEABLE_BUILDINGS[game->build_mode_building_index];
|
||||
FP_EntityRenderData club_terry_render_data = FP_Entity_GetRenderData(game, placeable_building.type, placeable_building.state, entity->direction);
|
||||
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, placeable_building.type, placeable_building.state, entity->direction);
|
||||
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, placeable_building, entity->handle);
|
||||
|
||||
Dqn_V4 colour = game->build_mode_can_place_building ?
|
||||
@ -2450,8 +2478,8 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
|
||||
TELY_Render_RectColourV4(renderer, dest_rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_BLUE_CADET_V4, 0.5f));
|
||||
TELY_Render_TextureColourV4(renderer,
|
||||
club_terry_render_data.sheet->tex_handle,
|
||||
club_terry_render_data.sheet_rect,
|
||||
render_data.sheet->tex_handle,
|
||||
render_data.sheet_rect,
|
||||
dest_rect,
|
||||
Dqn_V2_Zero /*rotate origin*/,
|
||||
0.f /*rotation*/,
|
||||
@ -2462,18 +2490,16 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
{
|
||||
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
|
||||
DQN_DEFER { TELY_Render_PopTransform(renderer); };
|
||||
|
||||
game->build_mode_building_index = DQN_CLAMP(game->build_mode_building_index, 0, DQN_ARRAY_UCOUNT(PLACEABLE_BUILDINGS) - 1);
|
||||
|
||||
Dqn_f32 building_ui_size = 150.f;
|
||||
Dqn_f32 building_ui_size = 64.f;
|
||||
Dqn_f32 padding = 10.f;
|
||||
Dqn_f32 total_size = DQN_ARRAY_UCOUNT(PLACEABLE_BUILDINGS) * building_ui_size + ((DQN_ARRAY_UCOUNT(PLACEABLE_BUILDINGS) - 1) * padding);
|
||||
Dqn_f32 start_x = (platform->core.window_size.x * .5f) - (total_size * .5f);
|
||||
Dqn_f32 start_x = player_avatar_rect.pos.x;
|
||||
DQN_FOR_UINDEX (building_index, DQN_ARRAY_UCOUNT(PLACEABLE_BUILDINGS)) {
|
||||
FP_GamePlaceableBuilding building = PLACEABLE_BUILDINGS[building_index];
|
||||
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, building.type, building.state, FP_GameDirection_Down);
|
||||
Dqn_Rect rect = Dqn_Rect_InitNx4(start_x + (building_index * building_ui_size) + (padding * building_index),
|
||||
ui_start_y,
|
||||
Dqn_Rect_InterpolatedPoint(player_avatar_rect, Dqn_V2_InitNx2(0, 1.70)).y,
|
||||
building_ui_size,
|
||||
building_ui_size);
|
||||
|
||||
@ -2493,6 +2519,21 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
||||
0.f /*rotation*/,
|
||||
texture_colour);
|
||||
|
||||
uint32_t building_count = 0;
|
||||
if (building.type == FP_EntityType_ClubTerry)
|
||||
building_count = player->inventory.clubs;
|
||||
else if (building.type == FP_EntityType_AirportTerry)
|
||||
building_count = player->inventory.airports;
|
||||
else if (building.type == FP_EntityType_KennelTerry)
|
||||
building_count = player->inventory.kennels;
|
||||
else if (building.type == FP_EntityType_ChurchTerry)
|
||||
building_count = player->inventory.churchs;
|
||||
|
||||
TELY_Render_PushFont(renderer, game->talkco_font);
|
||||
DQN_DEFER { TELY_Render_PopFont(renderer); };
|
||||
|
||||
Dqn_V2 label_p = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(0.5f, 1.25f));
|
||||
TELY_Render_TextF(renderer, label_p, Dqn_V2_InitNx2(0.5f, 0.5f), "x %u", building_count);
|
||||
|
||||
TELY_RenderCommandRect *cmd = TELY_Render_RectColourV4(renderer, rect, TELY_RenderShapeMode_Line, outline_colour);
|
||||
cmd->thickness = 2.f;
|
||||
|
@ -446,6 +446,11 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
|
||||
entity->flags |= FP_GameEntityFlag_CameraTracking;
|
||||
entity->terry_mobile_data_plan_cap = DQN_KILOBYTES(16);
|
||||
entity->terry_mobile_data_plan = entity->terry_mobile_data_plan_cap;
|
||||
|
||||
entity->inventory.airports_base_price = 4;
|
||||
entity->inventory.churchs_base_price = 2;
|
||||
entity->inventory.kennels_base_price = 2;
|
||||
entity->inventory.clubs_base_price = 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,19 @@ struct FP_GameRenderSprite
|
||||
uint64_t started_at_clock_ms;
|
||||
};
|
||||
|
||||
struct FP_GameInventory
|
||||
{
|
||||
uint32_t airports_base_price;
|
||||
uint32_t clubs_base_price;
|
||||
uint32_t kennels_base_price;
|
||||
uint32_t churchs_base_price;
|
||||
|
||||
uint8_t airports;
|
||||
uint8_t clubs;
|
||||
uint8_t kennels;
|
||||
uint8_t churchs;
|
||||
};
|
||||
|
||||
struct FP_GameEntity
|
||||
{
|
||||
FP_GameEntity *next;
|
||||
@ -198,6 +211,7 @@ struct FP_GameEntity
|
||||
Dqn_usize terry_mobile_data_plan_cap;
|
||||
|
||||
Dqn_usize coins;
|
||||
FP_GameInventory inventory;
|
||||
};
|
||||
|
||||
struct FP_GameEntityIterator
|
||||
@ -286,7 +300,6 @@ struct FP_Game
|
||||
FP_GameActiveMenu active_menu;
|
||||
bool build_mode_can_place_building;
|
||||
Dqn_usize build_mode_building_index;
|
||||
|
||||
};
|
||||
|
||||
struct FP_GameAStarNode
|
||||
|
Loading…
Reference in New Issue
Block a user