fp: Add dollar particle on buying upgrade

This commit is contained in:
doyle 2023-10-22 21:53:21 +11:00
parent 8d01a3631f
commit 5c8fda7f9b
3 changed files with 158 additions and 131 deletions

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

Binary file not shown.

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

Binary file not shown.

View File

@ -2160,7 +2160,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
particle_desc.duration_ms = 1000; particle_desc.duration_ms = 1000;
FP_EmitParticle(&game->play, particle_desc, Dqn_PCG32_Range(&game->play.rng, 1, 3)); FP_EmitParticle(&game->play, particle_desc, Dqn_PCG32_Range(&game->play.rng, 1, 3));
// NOTE: God mode override ========================================================= // NOTE: God mode override =========================================================
if (game->play.heart == defender->handle) { if (game->play.heart == defender->handle) {
if (game->play.god_mode) if (game->play.god_mode)
@ -2838,39 +2837,6 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
} }
} }
for (FP_Particle &particle_ : game->play.particles) {
FP_Particle *particle = &particle_;
if (!particle->alive)
continue;
Dqn_usize elapsed_ms = game->play.clock_ms - particle->start_ms;
Dqn_usize duration_ms = particle->end_ms - particle->start_ms;
Dqn_f32 t = DQN_MIN(1.f, elapsed_ms / DQN_CAST(Dqn_f32)duration_ms);
Dqn_V4 colour = {};
colour.r = Dqn_Lerp_F32(particle->colour_begin.r, t, particle->colour_end.r);
colour.b = Dqn_Lerp_F32(particle->colour_begin.b, t, particle->colour_end.b);
colour.g = Dqn_Lerp_F32(particle->colour_begin.g, t, particle->colour_end.g);
colour.a = Dqn_Lerp_F32(particle->colour_begin.a, t, particle->colour_end.a);
if (particle->anim_name.size) {
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, particle->anim_name);
Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index];
Dqn_Rect dest_rect = {};
dest_rect.size = tex_rect.size;
dest_rect.pos = particle->pos - (tex_rect.size * .5f);
TELY_Render_TextureColourV4(renderer,
game->atlas_sprite_sheet.tex_handle,
tex_rect,
dest_rect,
Dqn_V2_Zero /*rotate origin*/,
0.f /*rotation*/,
colour);
} else {
TELY_Render_CircleColourV4(renderer, particle->pos, 20.f, TELY_RenderShapeMode_Fill, colour);
}
}
// NOTE: Render overlay UI ===================================================================== // NOTE: Render overlay UI =====================================================================
if (!game->play.debug_hide_hud && (game->play.state == FP_GameState_Pause || game->play.state == FP_GameState_Play)) { if (!game->play.debug_hide_hud && (game->play.state == FP_GameState_Pause || game->play.state == FP_GameState_Play)) {
@ -2940,6 +2906,17 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
} }
// NOTE: Render the player(s) HUD and merchant menu interaction ============================ // 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;
}
Dqn_Rect first_player_avatar_rect = {}; Dqn_Rect first_player_avatar_rect = {};
DQN_FOR_UINDEX (player_index, game->play.players.size) { DQN_FOR_UINDEX (player_index, game->play.players.size) {
FP_GameEntityHandle player_handle = game->play.players.data[player_index]; FP_GameEntityHandle player_handle = game->play.players.data[player_index];
@ -3059,55 +3036,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
{ {
bool const have_enough_coins = player->coins >= *mapping.building_base_price; bool const have_enough_coins = player->coins >= *mapping.building_base_price;
FP_GameKeyBind key_bind = player->controls.buy_building; FP_GameKeyBind key_bind = player->controls.buy_building;
// NOTE: Buy trigger + animation ===============================
{
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp)
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp) {
if (mapping.inventory_count) {
player->coins -= *mapping.building_base_price;
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Ching], 1.f);
*mapping.building_base_price *= 1;
// NOTE: Raise the prices of everything else
invent->airports_base_price *= 1;
invent->clubs_base_price *= 1;
invent->kennels_base_price *= 1;
invent->churchs_base_price *= 1;
(*mapping.inventory_count)++;
}
} else {
game->play.player_trigger_purchase_building_timestamp = UINT64_MAX;
}
}
if (trigger_buy_anim) {
uint64_t start_buy_time = game->play.player_trigger_purchase_building_timestamp - buy_duration_ms;
uint64_t elapsed_time = game->play.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 ================================= // 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); Dqn_V2 dollar_text_label_pos = {};
Dqn_V4 tex_mod_colour = have_enough_coins ? TELY_COLOUR_WHITE_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, .5f);
{ {
// NOTE: Render the interaction button // NOTE: Render the interaction button
Dqn_Rect interact_btn_rect = {}; Dqn_Rect interact_btn_rect = {};
@ -3143,9 +3075,60 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
} }
// NOTE: Render the $ cost // NOTE: Render the $ cost
TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(interact_btn_rect, Dqn_V2_InitNx2(0.5f, -0.8f)), Dqn_V2_InitNx2(0.5, 0.f), "$%u", *mapping.building_base_price); dollar_text_label_pos = Dqn_Rect_InterpolatedPoint(interact_btn_rect, Dqn_V2_InitNx2(0.5f, -0.8f));
TELY_Render_TextF(renderer, dollar_text_label_pos, Dqn_V2_InitNx2(0.5, 0.f), "$%u", *mapping.building_base_price);
} }
// NOTE: Buy trigger + animation ===========================================
{
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp)
game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp) {
if (mapping.inventory_count) {
player->coins -= *mapping.building_base_price;
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Ching], 1.f);
*mapping.building_base_price *= 1;
// NOTE: Raise the prices of everything else
invent->airports_base_price *= 1;
invent->clubs_base_price *= 1;
invent->kennels_base_price *= 1;
invent->churchs_base_price *= 1;
(*mapping.inventory_count)++;
dollar_buy_particle.pos = dollar_text_label_pos;
FP_EmitParticle(&game->play, dollar_buy_particle, 1);
}
} else {
game->play.player_trigger_purchase_building_timestamp = UINT64_MAX;
}
}
if (trigger_buy_anim) {
uint64_t start_buy_time = game->play.player_trigger_purchase_building_timestamp - buy_duration_ms;
uint64_t elapsed_time = game->play.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 merchant shop item building ================ // NOTE: Render the merchant shop item building ================
{ {
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, mapping.building); TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, mapping.building);
@ -3167,55 +3150,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
{ {
bool const have_enough_coins = player->coins >= *mapping.upgrade_base_price; bool const have_enough_coins = player->coins >= *mapping.upgrade_base_price;
FP_GameKeyBind key_bind = player->controls.buy_upgrade; FP_GameKeyBind key_bind = player->controls.buy_upgrade;
// NOTE: Buy trigger + animation ===============================
{
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp)
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp) {
player->coins -= *mapping.upgrade_base_price;
*mapping.upgrade_base_price *= 1;
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Ching], 1.f);
if (mapping.merchant == game->play.merchant_terry) {
player->base_attack += DQN_CAST(uint32_t)(FP_DEFAULT_DAMAGE * 1.2f);
} else if (mapping.merchant == game->play.merchant_graveyard) {
player->stamina_cap += DQN_CAST(uint32_t)(FP_TERRY_DASH_STAMINA_COST * .5f);
} else if (mapping.merchant == game->play.merchant_gym) {
player->hp_cap += FP_DEFAULT_DAMAGE;
player->hp = player->hp_cap;
} else if (mapping.merchant == game->play.merchant_phone_company) {
player->terry_mobile_data_plan_cap += DQN_KILOBYTES(1);
}
} else {
game->play.player_trigger_purchase_upgrade_timestamp = UINT64_MAX;
}
}
if (trigger_buy_anim) {
uint64_t start_buy_time = game->play.player_trigger_purchase_upgrade_timestamp - buy_duration_ms;
uint64_t elapsed_time = game->play.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 ================================= // NOTE: Render the (B) button =================================
Dqn_V4 tex_mod_colour = have_enough_coins ? TELY_COLOUR_WHITE_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, .5f); Dqn_V4 tex_mod_colour = have_enough_coins ? TELY_COLOUR_WHITE_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, .5f);
Dqn_V2 dollar_text_label_pos = {};
{ {
Dqn_V2 interp_pos01 = Dqn_V2_InitNx2(0.7f, 0.41f); Dqn_V2 interp_pos01 = Dqn_V2_InitNx2(0.7f, 0.41f);
Dqn_Rect interact_btn_rect = {}; Dqn_Rect interact_btn_rect = {};
@ -3268,9 +3206,60 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
} }
// NOTE: Render the $ cost // NOTE: Render the $ cost
TELY_Render_TextF(renderer, Dqn_Rect_InterpolatedPoint(interact_btn_rect, Dqn_V2_InitNx2(1.f, -0.8f)), Dqn_V2_InitNx2(0.5, 0.f), "$%u", *mapping.upgrade_base_price); dollar_text_label_pos = Dqn_Rect_InterpolatedPoint(interact_btn_rect, Dqn_V2_InitNx2(1.f, -0.8f));
TELY_Render_TextF(renderer, dollar_text_label_pos, Dqn_V2_InitNx2(0.5, 0.f), "$%u", *mapping.upgrade_base_price);
} }
// NOTE: Buy trigger + animation ===========================================
{
bool trigger_buy_anim = false;
if (have_enough_coins) {
if (TELY_Platform_InputScanCodeIsPressed(input, key_bind.scan_code)) {
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms + buy_duration_ms;
} else if (TELY_Platform_InputScanCodeIsDown(input, key_bind.scan_code)) {
trigger_buy_anim = true;
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp)
game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms;
} else if (TELY_Platform_InputScanCodeIsReleased(input, key_bind.scan_code)) {
if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp) {
player->coins -= *mapping.upgrade_base_price;
*mapping.upgrade_base_price *= 1;
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);
if (mapping.merchant == game->play.merchant_terry) {
player->base_attack += DQN_CAST(uint32_t)(FP_DEFAULT_DAMAGE * 1.2f);
} else if (mapping.merchant == game->play.merchant_graveyard) {
player->stamina_cap += DQN_CAST(uint32_t)(FP_TERRY_DASH_STAMINA_COST * .5f);
} else if (mapping.merchant == game->play.merchant_gym) {
player->hp_cap += FP_DEFAULT_DAMAGE;
player->hp = player->hp_cap;
} else if (mapping.merchant == game->play.merchant_phone_company) {
player->terry_mobile_data_plan_cap += DQN_KILOBYTES(1);
}
} else {
game->play.player_trigger_purchase_upgrade_timestamp = UINT64_MAX;
}
}
if (trigger_buy_anim) {
uint64_t start_buy_time = game->play.player_trigger_purchase_upgrade_timestamp - buy_duration_ms;
uint64_t elapsed_time = game->play.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));
}
}
}
} }
} }
@ -3830,6 +3819,44 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
FP_GameRenderScanlines(renderer, scanline_gap, scanline_thickness, window_rect.size); FP_GameRenderScanlines(renderer, scanline_gap, scanline_thickness, window_rect.size);
} }
for (FP_Particle &particle_ : game->play.particles) {
FP_Particle *particle = &particle_;
if (!particle->alive)
continue;
Dqn_usize elapsed_ms = game->play.clock_ms - particle->start_ms;
Dqn_usize duration_ms = particle->end_ms - particle->start_ms;
Dqn_f32 t = DQN_MIN(1.f, elapsed_ms / DQN_CAST(Dqn_f32)duration_ms);
Dqn_V4 colour = {};
colour.r = Dqn_Lerp_F32(particle->colour_begin.r, t, particle->colour_end.r);
colour.b = Dqn_Lerp_F32(particle->colour_begin.b, t, particle->colour_end.b);
colour.g = Dqn_Lerp_F32(particle->colour_begin.g, t, particle->colour_end.g);
colour.a = Dqn_Lerp_F32(particle->colour_begin.a, t, particle->colour_end.a);
if (particle->anim_name.size) {
TELY_AssetSpriteAnimation *anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, particle->anim_name);
uint16_t const raw_anim_frame = DQN_CAST(uint16_t)(elapsed_ms / anim->ms_per_frame);
uint16_t anim_frame = raw_anim_frame % anim->count;
Dqn_Rect tex_rect = game->atlas_sprite_sheet.rects.data[anim->index + anim_frame];
Dqn_Rect dest_rect = {};
dest_rect.size = tex_rect.size;
dest_rect.pos = particle->pos - (tex_rect.size * .5f);
TELY_Render_TextureColourV4(renderer,
game->atlas_sprite_sheet.tex_handle,
tex_rect,
dest_rect,
Dqn_V2_Zero /*rotate origin*/,
0.f /*rotation*/,
colour);
} else {
TELY_Render_CircleColourV4(renderer, particle->pos, 20.f, TELY_RenderShapeMode_Fill, colour);
}
}
// NOTE: Debug UI ============================================================================== // NOTE: Debug UI ==============================================================================
DQN_MSVC_WARNING_PUSH DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE' DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'