3 Commits

Author SHA1 Message Date
Jojangles 0736314600 Add new sfx 2023-10-08 13:23:26 +11:00
doylet 87fb216256 fp: Add intro screen and remove nil states 2023-10-08 13:23:25 +11:00
Jojangles daa6cb4cb4 Change the numbers for better balancing 2023-10-08 13:13:18 +11:00
19 changed files with 1334 additions and 1299 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+146 -192
View File
@@ -353,7 +353,8 @@ void TELY_DLL_Init(void *user_data)
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Map");
entity->type = FP_EntityType_Map;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
entity->local_pos = {};
Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, entity->sprite_height, sprite_rect);
@@ -361,7 +362,7 @@ void TELY_DLL_Init(void *user_data)
entity->local_hit_box_size = sprite_rect_scaled;
FP_Entity_AddDebugEditorFlags(game, entity->handle);
FP_Game_EntityActionReset(game, entity->handle, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, render_data.sprite);
game->map = entity;
}
@@ -496,10 +497,12 @@ void TELY_DLL_Init(void *user_data)
game->merchant_phone_company = FP_Entity_CreateMerchantPhoneCompany(game, base_top_right, "PhoneCompany");
}
#if 0
FP_Entity_CreateClubTerry(game, Dqn_V2_InitNx2(+500, -191), "Club Terry");
FP_Entity_CreateKennelTerry(game, Dqn_V2_InitNx2(-300, -191), "Kennel Terry");
FP_Entity_CreateChurchTerry(game, Dqn_V2_InitNx2(-800, -191), "Church Terry");
FP_Entity_CreateAirportTerry(game, Dqn_V2_InitNx2(-1200, -191), "Airport Terry");
#endif
game->tile_size = 37;
Dqn_V2I max_tile = platform->core.window_size / game->tile_size;
@@ -508,10 +511,12 @@ void TELY_DLL_Init(void *user_data)
FP_Entity_CreateHeart(game, base_mid_p, "Heart");
uint16_t font_size = 18;
game->camera.world_pos = base_mid_p - Dqn_V2_InitV2I(platform->core.window_size * .5f);
game->camera.scale = Dqn_V2_InitNx1(1);
game->inter_regular_font = platform->func_load_font(assets, DQN_STRING8("Inter (Regular)"), DQN_STRING8("Data/Inter-Regular.otf"), font_size);
game->inter_italic_font = platform->func_load_font(assets, DQN_STRING8("Inter (Italic)"), DQN_STRING8("Data/Inter-Italic.otf"), font_size);
game->jetbrains_mono_font = platform->func_load_font(assets, DQN_STRING8("JetBrains Mono NL (Regular)"), DQN_STRING8("Data/JetBrainsMonoNL-Regular.ttf"), font_size);
game->inter_regular_font_large = platform->func_load_font(assets, DQN_STRING8("Inter (Regular)"), DQN_STRING8("Data/Inter-Regular.otf"), DQN_CAST(uint16_t)(font_size * 5.f));
game->inter_regular_font = platform->func_load_font(assets, DQN_STRING8("Inter (Regular)"), DQN_STRING8("Data/Inter-Regular.otf"), DQN_CAST(uint16_t)(font_size));
// game->inter_italic_font = platform->func_load_font(assets, DQN_STRING8("Inter (Italic)"), DQN_STRING8("Data/Inter-Italic.otf"), font_size);
// game->jetbrains_mono_font = platform->func_load_font(assets, DQN_STRING8("JetBrains Mono NL (Regular)"), DQN_STRING8("Data/JetBrainsMonoNL-Regular.ttf"), font_size);
game->talkco_font = platform->func_load_font(assets, DQN_STRING8("Talkco"), DQN_STRING8("Data/Talkco.otf"), font_size);
game->talkco_font_large = platform->func_load_font(assets, DQN_STRING8("Talkco"), DQN_STRING8("Data/Talkco.otf"), DQN_CAST(uint16_t)(font_size * 1.5f));
game->audio[FP_GameAudio_TestAudio] = platform->func_load_audio(assets, DQN_STRING8("Test Audio"), DQN_STRING8("Data/Audio/Purrple Cat - Moonwinds.qoa"));
@@ -535,8 +540,6 @@ FP_GetClosestPortalMonkeyResult FP_GetClosestPortalMonkey(FP_Game *game, FP_Game
FP_GameEntity *portal_monkey = FP_Game_GetEntity(game, portal_monkey_handle);
if (FP_Game_IsNilEntity(portal_monkey))
continue;
if (portal_monkey->action.state == FP_EntityPortalMonkeyState_DisablingPortal)
continue;
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, handle);
Dqn_V2 portal_monkey_pos = FP_Game_CalcEntityWorldPos(game, portal_monkey_handle);
Dqn_f32 dist_squared = Dqn_V2_LengthSq_V2x2(entity_pos, portal_monkey_pos);
@@ -555,18 +558,10 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
FP_GameEntityAction *action = &entity->action;
bool const we_are_clicked_entity = entity->handle == game->clicked_entity;
bool const entity_has_velocity = entity->velocity.x || entity->velocity.y;
bool const entering_new_state = action->state != action->next_state;
bool const entering_new_state = entity->alive_time_s == 0.f || action->state != action->next_state;
bool const action_has_finished = !entering_new_state && game->clock_ms >= action->end_at_clock_ms;
action->state = action->next_state;
// NOTE: Left-shift lets us strafe in the same direction
if (!TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_LeftShift)) {
if (acceleration_meters_per_s->x)
entity->direction = acceleration_meters_per_s->x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (acceleration_meters_per_s->y)
entity->direction = acceleration_meters_per_s->y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
}
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, entity->action.state, entity->direction);
switch (entity->type) {
case FP_EntityType_Terry: {
@@ -583,10 +578,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
}
switch (*state) {
case FP_EntityTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Idle);
} break;
case FP_EntityTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -594,7 +585,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
}
if (we_are_clicked_entity) {
if (game->active_menu == FP_GameActiveMenu_Nil) {
if (game->in_game_menu == FP_GameInGameMenu_Nil) {
bool picked_up_monkey_this_frame = false;
if (FP_Game_IsNilEntityHandle(game, entity->carried_monkey)) {
// NOTE: Check if we are nearby a monkey and picking it up
@@ -661,7 +652,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
if (we_are_clicked_entity) {
bool picked_up_monkey_this_frame = false;
if (game->active_menu == FP_GameActiveMenu_Nil) {
if (game->in_game_menu == FP_GameInGameMenu_Nil) {
if (FP_Game_IsNilEntityHandle(game, entity->carried_monkey)) {
// NOTE: Check if we are nearby a monkey and picking it up
FP_GetClosestPortalMonkeyResult closest_monkey = FP_GetClosestPortalMonkey(game, entity->handle);
@@ -740,31 +731,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
} break;
case FP_EntityType_PortalMonkey: {
FP_EntityPortalMonkeyState *state = DQN_CAST(FP_EntityPortalMonkeyState *) & action->state;
switch (*state) {
case FP_EntityPortalMonkeyState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Idle);
} break;
case FP_EntityPortalMonkeyState_Idle: {
} break;
case FP_EntityPortalMonkeyState_BeingCarried: {
} break;
case FP_EntityPortalMonkeyState_DisablingPortal: {
} break;
}
} break;
case FP_EntityType_Smoochie: {
FP_EntitySmoochieState *state = DQN_CAST(FP_EntitySmoochieState *) & action->state;
switch (*state) {
case FP_EntitySmoochieState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Idle);
} break;
case FP_EntitySmoochieState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -886,10 +855,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_Clinger: {
FP_EntityClingerState *state = DQN_CAST(FP_EntityClingerState *)&action->state;
switch (*state) {
case FP_EntityClingerState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityClingerState_Idle);
} break;
case FP_EntityClingerState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -960,10 +925,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_MerchantTerry: {
FP_EntityMerchantTerryState *state = DQN_CAST(FP_EntityMerchantTerryState *)&action->state;
switch (*state) {
case FP_EntityMerchantTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMerchantTerryState_Idle);
} break;
case FP_EntityMerchantTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -977,10 +938,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_MerchantPhoneCompany: {
FP_EntityMerchantPhoneCompanyState *state = DQN_CAST(FP_EntityMerchantPhoneCompanyState *)&action->state;
switch (*state) {
case FP_EntityMerchantPhoneCompanyState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMerchantPhoneCompanyState_Idle);
} break;
case FP_EntityMerchantPhoneCompanyState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -993,10 +950,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_MerchantGym: {
FP_EntityMerchantGymState *state = DQN_CAST(FP_EntityMerchantGymState *)&action->state;
switch (*state) {
case FP_EntityMerchantGymState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMerchantGymState_Idle);
} break;
case FP_EntityMerchantGymState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1010,10 +963,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_MerchantGraveyard: {
FP_EntityMerchantGraveyardState *state = DQN_CAST(FP_EntityMerchantGraveyardState *)&action->state;
switch (*state) {
case FP_EntityMerchantGraveyardState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMerchantGraveyardState_Idle);
} break;
case FP_EntityMerchantGraveyardState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1027,10 +976,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_ClubTerry: {
FP_EntityClubTerryState *state = DQN_CAST(FP_EntityClubTerryState *)&action->state;
switch (*state) {
case FP_EntityClubTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityClubTerryState_Idle);
} break;
case FP_EntityClubTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1061,10 +1006,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_Map: {
FP_EntityMapState *state = DQN_CAST(FP_EntityMapState *) & action->state;
switch (*state) {
case FP_EntityMapState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMapState_Idle);
} break;
case FP_EntityMapState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1078,10 +1019,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_Heart: {
FP_EntityHeartState *state = DQN_CAST(FP_EntityHeartState *) & action->state;
switch (*state) {
case FP_EntityHeartState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityHeartState_Idle);
} break;
case FP_EntityHeartState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1094,10 +1031,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_AirportTerry: {
FP_EntityAirportTerryState *state = DQN_CAST(FP_EntityAirportTerryState *)&action->state;
switch (*state) {
case FP_EntityAirportTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryState_Idle);
} break;
case FP_EntityAirportTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1143,10 +1076,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_AirportTerryPlane: {
FP_EntityAirportTerryPlaneState *state = DQN_CAST(FP_EntityAirportTerryPlaneState *)&action->state;
switch (*state) {
case FP_EntityAirportTerryPlaneState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryPlaneState_Idle);
} break;
case FP_EntityAirportTerryPlaneState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1172,10 +1101,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_Catfish: {
FP_EntityCatfishState *state = DQN_CAST(FP_EntityCatfishState *) & action->state;
switch (*state) {
case FP_EntityCatfishState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityCatfishState_Idle);
} break;
case FP_EntityCatfishState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1245,10 +1170,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_ChurchTerry: {
FP_EntityChurchTerryState *state = DQN_CAST(FP_EntityChurchTerryState *)&action->state;
switch (*state) {
case FP_EntityChurchTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityChurchTerryState_Idle);
} break;
case FP_EntityChurchTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1280,10 +1201,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_KennelTerry: {
FP_EntityKennelTerryState *state = DQN_CAST(FP_EntityKennelTerryState *)&action->state;
switch (*state) {
case FP_EntityKennelTerryState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityKennelTerryState_Idle);
} break;
case FP_EntityKennelTerryState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1301,10 +1218,6 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_MobSpawner: {
FP_EntityMobSpawnerState *state = DQN_CAST(FP_EntityMobSpawnerState *)&action->state;
switch (*state) {
case FP_EntityMobSpawnerState_Nil: {
FP_Game_EntityTransitionState(game, entity, FP_EntityMobSpawnerState_Idle);
} break;
case FP_EntityMobSpawnerState_Idle: {
if (entering_new_state) {
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
@@ -1435,12 +1348,13 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
{
Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate);
if (TELY_Platform_InputKeyIsReleased(input->mouse_left))
game->clicked_entity = game->prev_active_entity;
game->update_counter++;
game->clock_ms = DQN_CAST(uint64_t)(platform->input.timer_s * 1000.f);
Dqn_ProfilerZone update_zone = Dqn_Profiler_BeginZoneWithIndex(DQN_STRING8("FP_Update: Entity loop"), FP_ProfileZone_FPUpdate_EntityLoop);
if (game->state == FP_GameState_Play) {
Dqn_V2 dir_vector = {};
if (TELY_Platform_InputKeyIsReleased(input->mouse_left))
game->clicked_entity = game->prev_active_entity;
// NOTE: Keyboard movement input
if (TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_W))
@@ -1503,8 +1417,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F1))
game->debug_ui = !game->debug_ui;
Dqn_ProfilerZone update_zone = Dqn_Profiler_BeginZoneWithIndex(DQN_STRING8("FP_Update: Entity loop"), FP_ProfileZone_FPUpdate_EntityLoop);
// NOTE: Handle input ==========================================================================
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
FP_GameEntity *entity = it.entity;
@@ -1886,9 +1798,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
}
if (game->clicked_entity == entity->handle) {
if (game->active_menu == FP_GameActiveMenu_Nil || game->active_menu == FP_GameActiveMenu_Build) {
if (game->in_game_menu == FP_GameInGameMenu_Nil || game->in_game_menu == FP_GameInGameMenu_Build) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_H))
game->active_menu = DQN_CAST(FP_GameActiveMenu)(DQN_CAST(uint32_t)game->active_menu ^ FP_GameActiveMenu_Build);
game->in_game_menu = DQN_CAST(FP_GameInGameMenu)(DQN_CAST(uint32_t)game->in_game_menu ^ FP_GameInGameMenu_Build);
}
if (entity->flags & FP_GameEntityFlag_CameraTracking)
@@ -1908,7 +1820,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
inventory_count = &entity->inventory.airports;
bool have_building_inventory = inventory_count && (*inventory_count) > 0;
if (have_building_inventory && game->active_menu == FP_GameActiveMenu_Build) {
if (have_building_inventory && game->in_game_menu == FP_GameInGameMenu_Build) {
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, placeable_building, entity->handle);
Dqn_V2 placement_pos = Dqn_Rect_Center(dest_rect);
@@ -1970,6 +1882,15 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
acceleration_meters_per_s *= 1.f; // TODO(doyle): Penalise the player
}
// NOTE: Left-shift lets us strafe in the same direction
if (!TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_LeftShift)) {
if (acceleration_meters_per_s.x)
entity->direction = acceleration_meters_per_s.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (acceleration_meters_per_s.y)
entity->direction = acceleration_meters_per_s.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
}
// NOTE: Tick the state machine
// NOTE: This can delete the entity! Take caution
FP_GameEntityHandle entity_handle = entity->handle;
@@ -1986,6 +1907,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
game->enemies_spawned_this_wave = 0;
game->current_wave++;
}
}
// NOTE: Update entity =========================================================================
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
@@ -2000,14 +1922,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
// NOTE: Recover mobile data
entity->terry_mobile_data_plan =
DQN_MIN(entity->terry_mobile_data_plan + DQN_CAST(Dqn_usize)(FP_TERRY_MOBILE_DATA_PER_RANGE_ATTACK * .25f * PHYSICS_STEP),
DQN_MIN(entity->terry_mobile_data_plan + DQN_CAST(Dqn_usize)(FP_TERRY_MOBILE_DATA_PER_RANGE_ATTACK * .125f * PHYSICS_STEP),
entity->terry_mobile_data_plan_cap);
// NOTE: Recover hp & stamina
entity->stamina = DQN_MIN(entity->stamina + 1, entity->stamina_cap);
entity->stamina = DQN_MIN(entity->stamina + 0.25f, entity->stamina_cap);
if (game->update_counter % 12 == 0) {
entity->hp = DQN_MIN(entity->hp + 1, entity->hp_cap);
entity->hp = DQN_MIN(entity->hp + 0.75f, entity->hp_cap);
}
// NOTE: Derive dynmamic bounding boxes ====================================================
@@ -2121,12 +2043,13 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
// NOTE: Do HP =========================================================================
defender->hp = defender->hp >= FP_DEFAULT_DAMAGE ? defender->hp - FP_DEFAULT_DAMAGE : 0;
if (defender->hp <= 0) {
defender->is_dying = true;
FP_GameEntity *coin_receiver = FP_Game_GetEntity(game, attacker->projectile_owner);
if (FP_Game_IsNilEntity(coin_receiver))
coin_receiver = attacker;
if (!defender->is_dying)
coin_receiver->coins += 1;
defender->is_dying = true;
}
// NOTE: Kickback ======================================================================
@@ -2165,7 +2088,18 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
{
Dqn_Profiler_ZoneScopeWithIndex("FP_Render", FP_ProfileZone_FPRender);
TELY_PlatformInput *input = &platform->input;
TELY_RFui *rfui = &game->rfui;
TELY_Assets *assets = &platform->assets;
TELY_Render_ClearColourV3(renderer, TELY_COLOUR_BLACK_MIDNIGHT_V4.rgb);
TELY_Render_PushFont(renderer, game->jetbrains_mono_font);
TELY_RFui_FrameSetup(rfui, &platform->frame_arena);
TELY_RFui_PushFont(rfui, game->jetbrains_mono_font);
TELY_RFui_PushLabelColourV4(rfui, TELY_COLOUR_BLACK_MIDNIGHT_V4);
Dqn_M2x3 model_view = FP_Game_CameraModelViewM2x3(game->camera, platform);
TELY_Render_PushTransform(renderer, model_view);
Dqn_V2 world_mouse_p = input->mouse_p + game->camera.world_pos;
// NOTE: Draw tiles ============================================================================
@@ -2354,7 +2288,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
}
}
if (game->active_menu == FP_GameActiveMenu_Build) {
if (game->in_game_menu == FP_GameInGameMenu_Build) {
if (entity->flags & FP_GameEntityFlag_BuildZone)
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_BLUE_CADET_V4, 0.5f));
}
@@ -2438,6 +2372,33 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
}
}
if (game->state == FP_GameState_IntroScreen) {
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
TELY_Render_RectColourV4(
renderer,
Dqn_Rect_InitNx4(0, 0, DQN_CAST(Dqn_f32)platform->core.window_size.x, DQN_CAST(Dqn_f32)platform->core.window_size.y),
TELY_RenderShapeMode_Fill,
TELY_Colour_V4Alpha(TELY_COLOUR_BLACK_V4, 0.8f));
Dqn_V2I inset = platform->core.window_size * .05f;
Dqn_f32 min_inset = DQN_CAST(Dqn_f32)DQN_MIN(inset.x, inset.y);
Dqn_V2 draw_p = Dqn_V2_InitNx2(min_inset, min_inset);
TELY_Render_PushColourV4(renderer, TELY_COLOUR_WHITE_V4);
TELY_Render_PushFont(renderer, game->inter_regular_font_large);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Feely Pona"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PushFont(renderer, game->inter_regular_font);
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, "Press enter to start"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
TELY_Render_PopFont(renderer);
TELY_Render_PopColourV4(renderer);
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Return))
game->state = FP_GameState_Play;
} else {
// NOTE: Render the merchant menus =========================================
FP_GameEntity *player = FP_Game_GetEntity(game, game->player);
Dqn_V2 player_pos = FP_Game_CalcEntityWorldPos(game, game->player);
@@ -2664,10 +2625,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
}
if (activated_merchant) {
game->active_menu = FP_GameActiveMenu_Merchant;
game->in_game_menu = FP_GameInGameMenu_Merchant;
} else {
if (game->active_menu == FP_GameActiveMenu_Merchant) {
game->active_menu = FP_GameActiveMenu_Nil;
if (game->in_game_menu == FP_GameInGameMenu_Merchant) {
game->in_game_menu = FP_GameInGameMenu_Nil;
}
}
}
@@ -2923,7 +2884,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
if (!FP_Game_IsNilEntityHandle(game, game->clicked_entity)) {
// NOTE: Render building blueprint =========================================================
if (game->active_menu == FP_GameActiveMenu_Build) {
if (game->in_game_menu == FP_GameInGameMenu_Build) {
FP_GameEntity *entity = FP_Game_GetEntity(game, game->clicked_entity);
FP_GamePlaceableBuilding placeable_building = PLACEABLE_BUILDINGS[game->build_mode_building_index];
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, placeable_building.type, placeable_building.state, entity->direction);
@@ -3003,82 +2964,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
Dqn_f32 scanline_gap = 4.0f;
Dqn_f32 scanline_thickness = 3.0f;
FP_GameRenderCameraFollowScanlines(renderer, screen_size, game->camera.world_pos, scanline_gap, scanline_thickness);
}
extern "C" __declspec(dllexport)
void TELY_DLL_FrameUpdate(void *user_data)
{
TELY_Platform *platform = DQN_CAST(TELY_Platform *) user_data;
TELY_PlatformInput *input = &platform->input;
TELY_Assets *assets = &platform->assets;
TELY_Renderer *renderer = &platform->renderer;
FP_Game *game = DQN_CAST(FP_Game *) platform->user_data;
TELY_RFui *rfui = &game->rfui;
TELY_Render_ClearColourV3(renderer, TELY_COLOUR_BLACK_MIDNIGHT_V4.rgb);
TELY_Render_PushFont(renderer, game->jetbrains_mono_font);
TELY_RFui_FrameSetup(rfui, &platform->frame_arena);
TELY_RFui_PushFont(rfui, game->jetbrains_mono_font);
TELY_RFui_PushLabelColourV4(rfui, TELY_COLOUR_BLACK_MIDNIGHT_V4);
// =============================================================================================
game->prev_clicked_entity = game->clicked_entity;
game->prev_hot_entity = game->hot_entity;
game->prev_active_entity = game->active_entity;
game->hot_entity = {};
game->active_entity = {};
Dqn_FArray_Clear(&game->parent_entity_stack);
Dqn_FArray_Add(&game->parent_entity_stack, game->root_entity->handle);
Dqn_M2x3 model_view = FP_Game_CameraModelViewM2x3(game->camera, platform);
TELY_Render_PushTransform(renderer, model_view);
Dqn_V2 world_mouse_p = input->mouse_p + game->camera.world_pos;
// =============================================================================================
TELY_Audio *audio = &platform->audio;
#if 0
if (audio->playback_size == 0) {
TELY_Audio_Play(audio, game->audio[FP_GameAudio_TestAudio], 1.f /*volume*/);
}
#endif
// =============================================================================================
if (TELY_Platform_InputKeyWasDown(input->mouse_left) && TELY_Platform_InputKeyIsDown(input->mouse_left)) {
if (game->prev_active_entity.id)
game->active_entity = game->prev_active_entity;
} else {
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->root_entity); ) {
FP_GameEntity *entity = it.entity;
if (entity->local_hit_box_size.x <= 0 || entity->local_hit_box_size.y <= 0)
continue;
if ((entity->flags & FP_GameEntityFlag_Clickable) == 0)
continue;
Dqn_Rect world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
if (!Dqn_Rect_ContainsPoint(world_hit_box, world_mouse_p))
continue;
game->hot_entity = entity->handle;
if (TELY_Platform_InputKeyIsPressed(input->mouse_left)) {
game->active_entity = entity->handle;
game->clicked_entity = entity->handle;
}
}
}
for (game->delta_s_accumulator += DQN_CAST(Dqn_f32)input->delta_s;
game->delta_s_accumulator > PHYSICS_STEP;
game->delta_s_accumulator -= PHYSICS_STEP) {
FP_Update(platform, game, input);
}
FP_Render(game, platform, renderer);
// NOTE: UI ====================================================================================
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
@@ -3161,6 +3047,74 @@ void TELY_DLL_FrameUpdate(void *user_data)
}
}
}
}
extern "C" __declspec(dllexport)
void TELY_DLL_FrameUpdate(void *user_data)
{
TELY_Platform *platform = DQN_CAST(TELY_Platform *) user_data;
TELY_PlatformInput *input = &platform->input;
TELY_Assets *assets = &platform->assets;
TELY_Renderer *renderer = &platform->renderer;
FP_Game *game = DQN_CAST(FP_Game *) platform->user_data;
TELY_RFui *rfui = &game->rfui;
// =============================================================================================
game->prev_clicked_entity = game->clicked_entity;
game->prev_hot_entity = game->hot_entity;
game->prev_active_entity = game->active_entity;
game->hot_entity = {};
game->active_entity = {};
Dqn_FArray_Clear(&game->parent_entity_stack);
Dqn_FArray_Add(&game->parent_entity_stack, game->root_entity->handle);
// =============================================================================================
TELY_Audio *audio = &platform->audio;
#if 0
if (audio->playback_size == 0) {
TELY_Audio_Play(audio, game->audio[FP_GameAudio_TestAudio], 1.f /*volume*/);
}
#endif
// =============================================================================================
if (game->state == FP_GameState_Play) {
if (TELY_Platform_InputKeyWasDown(input->mouse_left) && TELY_Platform_InputKeyIsDown(input->mouse_left)) {
if (game->prev_active_entity.id)
game->active_entity = game->prev_active_entity;
} else {
Dqn_V2 world_mouse_p = input->mouse_p + game->camera.world_pos;
for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->root_entity); ) {
FP_GameEntity *entity = it.entity;
if (entity->local_hit_box_size.x <= 0 || entity->local_hit_box_size.y <= 0)
continue;
if ((entity->flags & FP_GameEntityFlag_Clickable) == 0)
continue;
Dqn_Rect world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
if (!Dqn_Rect_ContainsPoint(world_hit_box, world_mouse_p))
continue;
game->hot_entity = entity->handle;
if (TELY_Platform_InputKeyIsPressed(input->mouse_left)) {
game->active_entity = entity->handle;
game->clicked_entity = entity->handle;
}
}
}
}
for (game->delta_s_accumulator += DQN_CAST(Dqn_f32)input->delta_s;
game->delta_s_accumulator > PHYSICS_STEP;
game->delta_s_accumulator -= PHYSICS_STEP) {
FP_Update(platform, game, input);
}
FP_Render(game, platform, renderer);
TELY_RFui_Flush(rfui, renderer, input, assets);
TELY_Audio_MixPlaybackSamples(audio, assets);
+1 -25
View File
@@ -29,7 +29,6 @@ enum FP_EntityType
enum FP_EntityTerryState
{
FP_EntityTerryState_Nil,
FP_EntityTerryState_Idle,
FP_EntityTerryState_Attack,
FP_EntityTerryState_RangeAttack,
@@ -39,14 +38,12 @@ enum FP_EntityTerryState
enum FP_EntityMobSpawnerState
{
FP_EntityMobSpawnerState_Nil,
FP_EntityMobSpawnerState_Idle,
FP_EntityMobSpawnerState_Shutdown,
};
enum FP_EntitySmoochieState
{
FP_EntitySmoochieState_Nil,
FP_EntitySmoochieState_Idle,
FP_EntitySmoochieState_Attack,
FP_EntitySmoochieState_HurtSide,
@@ -56,7 +53,6 @@ enum FP_EntitySmoochieState
enum FP_EntityCatfishState
{
FP_EntityCatfishState_Nil,
FP_EntityCatfishState_Idle,
FP_EntityCatfishState_Attack,
FP_EntityCatfishState_Death,
@@ -65,7 +61,6 @@ enum FP_EntityCatfishState
enum FP_EntityClingerState
{
FP_EntityClingerState_Nil,
FP_EntityClingerState_Idle,
FP_EntityClingerState_Attack,
FP_EntityClingerState_Death,
@@ -74,82 +69,63 @@ enum FP_EntityClingerState
enum FP_EntityMerchantTerryState
{
FP_EntityMerchantTerryState_Nil,
FP_EntityMerchantTerryState_Idle,
};
enum FP_EntityMerchantGymState
{
FP_EntityMerchantGymState_Nil,
FP_EntityMerchantGymState_Idle,
};
enum FP_EntityMerchantPhoneCompanyState
{
FP_EntityMerchantPhoneCompanyState_Nil,
FP_EntityMerchantPhoneCompanyState_Idle,
};
enum FP_EntityMerchantGraveyardState
{
FP_EntityMerchantGraveyardState_Nil,
FP_EntityMerchantGraveyardState_Idle,
};
enum FP_EntityClubTerryState
{
FP_EntityClubTerryState_Nil,
FP_EntityClubTerryState_Idle,
FP_EntityClubTerryState_PartyTime,
};
enum FP_EntityAirportTerryState
{
FP_EntityAirportTerryState_Nil,
FP_EntityAirportTerryState_Idle,
FP_EntityAirportTerryState_FlyPassenger,
};
enum FP_EntityAirportTerryPlaneState
{
FP_EntityAirportTerryPlaneState_Nil,
FP_EntityAirportTerryPlaneState_Idle,
FP_EntityAirportTerryPlaneState_FlyPassenger,
};
enum FP_EntityChurchTerryState
{
FP_EntityChurchTerryState_Nil,
FP_EntityChurchTerryState_Idle,
FP_EntityChurchTerryState_ConvertPatron,
};
enum FP_EntityKennelTerryState
{
FP_EntityKennelTerryState_Nil,
FP_EntityKennelTerryState_Idle,
};
enum FP_EntityMapState
{
FP_EntityMapState_Nil,
FP_EntityMapState_Idle,
};
enum FP_EntityHeartState
{
FP_EntityHeartState_Nil,
FP_EntityHeartState_Idle,
};
enum FP_EntityPortalMonkeyState
{
FP_EntityPortalMonkeyState_Nil,
FP_EntityPortalMonkeyState_Idle,
FP_EntityPortalMonkeyState_BeingCarried,
FP_EntityPortalMonkeyState_DisablingPortal,
};
struct FP_EntityRenderData
{
FP_Meters height;
@@ -161,6 +137,6 @@ struct FP_EntityRenderData
TELY_AssetAnimatedSprite sprite;
};
Dqn_usize const FP_TERRY_MOBILE_DATA_PER_RANGE_ATTACK = DQN_KILOBYTES(1);
Dqn_usize const FP_TERRY_MOBILE_DATA_PER_RANGE_ATTACK = DQN_KILOBYTES(5);
uint16_t const FP_TERRY_DASH_STAMINA_COST = 33;
uint16_t const FP_DEFAULT_DAMAGE = 30;
+98 -44
View File
@@ -35,7 +35,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 1.8f;
FP_EntityTerryState state = DQN_CAST(FP_EntityTerryState)raw_state;
switch (state) {
case FP_EntityTerryState_Nil: break;
case FP_EntityTerryState_Idle: result.anim_name = g_anim_names.terry_walk_idle; break;
case FP_EntityTerryState_Attack: {
@@ -84,7 +83,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 1.6f;
FP_EntitySmoochieState state = DQN_CAST(FP_EntitySmoochieState)raw_state;
switch (state) {
case FP_EntitySmoochieState_Nil: break;
case FP_EntitySmoochieState_Idle: result.anim_name = g_anim_names.smoochie_walk_down; break;
case FP_EntitySmoochieState_Attack: result.anim_name = g_anim_names.smoochie_attack_down; break;
case FP_EntitySmoochieState_HurtSide: result.anim_name = g_anim_names.smoochie_hurt_side; result.flip = direction == FP_GameDirection_Right ? TELY_AssetFlip_X : TELY_AssetFlip_No; break;
@@ -105,7 +103,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 3.66f;
FP_EntityMerchantTerryState state = DQN_CAST(FP_EntityMerchantTerryState)raw_state;
switch (state) {
case FP_EntityMerchantTerryState_Nil: break;
case FP_EntityMerchantTerryState_Idle: result.anim_name = g_anim_names.merchant_terry; break;
}
} break;
@@ -114,7 +111,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 3.66f;
FP_EntityMerchantGraveyardState state = DQN_CAST(FP_EntityMerchantGraveyardState)raw_state;
switch (state) {
case FP_EntityMerchantGraveyardState_Nil: break;
case FP_EntityMerchantGraveyardState_Idle: result.anim_name = g_anim_names.merchant_graveyard; break;
}
} break;
@@ -124,7 +120,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.anim_name = g_anim_names.merchant_gym;
FP_EntityMerchantGymState state = DQN_CAST(FP_EntityMerchantGymState)raw_state;
switch (state) {
case FP_EntityMerchantGymState_Nil: break;
case FP_EntityMerchantGymState_Idle: result.anim_name = g_anim_names.merchant_gym; break;
}
} break;
@@ -133,7 +128,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 3.66f;
FP_EntityMerchantPhoneCompanyState state = DQN_CAST(FP_EntityMerchantPhoneCompanyState)raw_state;
switch (state) {
case FP_EntityMerchantPhoneCompanyState_Nil: break;
case FP_EntityMerchantPhoneCompanyState_Idle: result.anim_name = g_anim_names.merchant_phone_company; break;
}
} break;
@@ -142,7 +136,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 4.f;
FP_EntityClubTerryState state = DQN_CAST(FP_EntityClubTerryState)raw_state;
switch (state) {
case FP_EntityClubTerryState_Nil: break;
case FP_EntityClubTerryState_Idle: result.anim_name = g_anim_names.club_terry_dark; break;
case FP_EntityClubTerryState_PartyTime: result.anim_name = g_anim_names.club_terry_alive; break;
}
@@ -152,7 +145,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 1.6f;
FP_EntityClingerState state = DQN_CAST(FP_EntityClingerState)raw_state;
switch (state) {
case FP_EntityClingerState_Nil: break;
case FP_EntityClingerState_Idle: result.anim_name = g_anim_names.clinger_walk_down; break;
case FP_EntityClingerState_Attack: {
@@ -183,7 +175,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 4.f;
FP_EntityHeartState state = DQN_CAST(FP_EntityHeartState)raw_state;
switch (state) {
case FP_EntityHeartState_Nil: break;
case FP_EntityHeartState_Idle: result.anim_name = g_anim_names.heart; break;
}
} break;
@@ -192,7 +183,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 4.f;
FP_EntityAirportTerryState state = DQN_CAST(FP_EntityAirportTerryState)raw_state;
switch (state) {
case FP_EntityAirportTerryState_Nil: break;
case FP_EntityAirportTerryState_Idle: result.anim_name = g_anim_names.airport_terry; break;
case FP_EntityAirportTerryState_FlyPassenger: result.anim_name = g_anim_names.airport_terry; break;
}
@@ -202,7 +192,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 1.6f;
FP_EntityCatfishState state = DQN_CAST(FP_EntityCatfishState)raw_state;
switch (state) {
case FP_EntityCatfishState_Nil:
case FP_EntityCatfishState_Idle: result.anim_name = g_anim_names.catfish_walk_down; break;
case FP_EntityCatfishState_Attack: {
switch (direction) {
@@ -230,7 +219,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 4.f;
FP_EntityChurchTerryState state = DQN_CAST(FP_EntityChurchTerryState)raw_state;
switch (state) {
case FP_EntityChurchTerryState_Nil: break;
case FP_EntityChurchTerryState_Idle: result.anim_name = g_anim_names.church_terry_dark; break;
case FP_EntityChurchTerryState_ConvertPatron: result.anim_name = g_anim_names.church_terry_alive; break;
}
@@ -240,7 +228,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 3.f;
FP_EntityKennelTerryState state = DQN_CAST(FP_EntityKennelTerryState)raw_state;
switch (state) {
case FP_EntityKennelTerryState_Nil: break;
case FP_EntityKennelTerryState_Idle: result.anim_name = g_anim_names.kennel_terry; break;
}
} break;
@@ -259,7 +246,6 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u
result.height.meters = 3.f;
FP_EntityMobSpawnerState state = DQN_CAST(FP_EntityMobSpawnerState)raw_state;
switch (state) {
case FP_EntityMobSpawnerState_Nil: break;
case FP_EntityMobSpawnerState_Idle: result.anim_name = g_anim_names.portal; break;
case FP_EntityMobSpawnerState_Shutdown: {
result.anim_name = g_anim_names.portal_break;
@@ -326,7 +312,9 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
entity->is_dying = false;
entity->base_acceleration_per_s.meters = 8.f;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
entity->attack_cooldown_ms = 1000;
entity->faction = FP_GameEntityFaction_Foe;
@@ -334,6 +322,9 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
return result;
}
@@ -349,13 +340,19 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
entity->base_acceleration_per_s.meters = 8.f;
entity->is_dying = false;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
entity->attack_cooldown_ms = 1000;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.7f, entity->sprite_height.meters * .6f);
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
entity->faction = FP_GameEntityFaction_Foe;
return result;
}
@@ -371,7 +368,12 @@ static FP_GameEntityHandle FP_Entity_CreateCatfish(FP_Game *game, Dqn_V2 pos, DQ
entity->base_acceleration_per_s.meters = 8.f;
entity->is_dying = false;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->attack_cooldown_ms = 1000;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.7f, entity->sprite_height.meters * .6f);
FP_Entity_AddDebugEditorFlags(game, entity->handle);
@@ -424,9 +426,13 @@ static FP_GameEntityHandle FP_Entity_CreateMobSpawner(FP_Game *game, Dqn_V2 pos,
entity->type = FP_EntityType_MobSpawner;
entity->local_pos = pos;
entity->local_hit_box_size = Dqn_V2_InitNx1(32);
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_Entity_AddDebugEditorFlags(game, result);
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->spawn_cap = spawn_cap;
entity->spawn_list = FP_SentinelList_Init<FP_GameEntityHandle>(game->chunk_pool);
return result;
@@ -443,12 +449,17 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
entity->type = FP_EntityType_Terry;
entity->local_pos = pos;
entity->base_acceleration_per_s.meters = 16.f;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->attack_cooldown_ms = 500;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters * .6f);
entity->hp_cap = FP_DEFAULT_DAMAGE * 3;
entity->hp = entity->hp_cap;
entity->coins = 1'000'000;
entity->coins = 0;//1'000'000;
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable;
@@ -469,7 +480,12 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantTerry(FP_Game *game, Dqn_V2 p
entity->type = FP_EntityType_MerchantTerry;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -493,7 +509,12 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantGraveyard(FP_Game *game, Dqn_
entity->type = FP_EntityType_MerchantGraveyard;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -517,7 +538,12 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantGym(FP_Game *game, Dqn_V2 pos
entity->type = FP_EntityType_MerchantGym;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -541,7 +567,12 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantPhoneCompany(FP_Game *game, D
entity->type = FP_EntityType_MerchantPhoneCompany;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -565,7 +596,12 @@ static FP_GameEntityHandle FP_Entity_CreateClubTerry(FP_Game *game, Dqn_V2 pos,
entity->type = FP_EntityType_ClubTerry;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -589,7 +625,12 @@ static FP_GameEntityHandle FP_Entity_CreateHeart(FP_Game *game, Dqn_V2 pos, DQN_
entity->type = FP_EntityType_Heart;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -613,7 +654,12 @@ static FP_GameEntityHandle FP_Entity_CreateChurchTerry(FP_Game *game, Dqn_V2 pos
entity->type = FP_EntityType_ChurchTerry;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -637,7 +683,12 @@ static FP_GameEntityHandle FP_Entity_CreateKennelTerry(FP_Game *game, Dqn_V2 pos
entity->type = FP_EntityType_KennelTerry;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -661,7 +712,12 @@ static FP_GameEntityHandle FP_Entity_CreateAirportTerry(FP_Game *game, Dqn_V2 po
entity->type = FP_EntityType_AirportTerry;
entity->local_pos = pos;
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable;
@@ -684,11 +740,15 @@ static FP_GameEntityHandle FP_Entity_CreatePhoneMessageProjectile(FP_Game *game,
va_end(args);
entity->type = FP_EntityType_PhoneMessageProjectile;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->constant_acceleration_per_s = velocity;
entity->local_pos = pos;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_TTL;
@@ -699,10 +759,6 @@ static FP_GameEntityHandle FP_Entity_CreatePhoneMessageProjectile(FP_Game *game,
entity->ttl_end_timestamp = game->clock_ms + 1000;
entity->projectile_owner = owner;
entity->faction = FP_GameEntityFaction_Friendly;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
return result;
}
@@ -715,18 +771,18 @@ static FP_GameEntityHandle FP_Entity_CreatePortalMonkey(FP_Game *game, Dqn_V2 po
va_end(args);
entity->type = FP_EntityType_PortalMonkey;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->local_pos = pos;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
FP_Entity_AddDebugEditorFlags(game, result);
entity->local_hit_box_offset = Dqn_V2_InitNx2(0, render_data.render_size.h * .1f);
entity->local_hit_box_size = Dqn_V2_InitNx2(render_data.render_size.w, render_data.render_size.h - (render_data.render_size.h * .4f));
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
return result;
}
@@ -740,18 +796,16 @@ static FP_GameEntityHandle FP_Entity_CreateAirportTerryPlane(FP_Game *game, Dqn_
entity->type = FP_EntityType_AirportTerryPlane;
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, 0, FP_GameDirection_Down);
entity->sprite_height = render_data.height;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
entity->local_pos = pos;
entity->sprite_height = render_data.height;
entity->flags |= FP_GameEntityFlag_NoClip;
FP_Entity_AddDebugEditorFlags(game, result);
entity->local_hit_box_offset = Dqn_V2_InitNx2(0, render_data.render_size.h * .1f);
entity->local_hit_box_size = Dqn_V2_InitNx2(render_data.render_size.w, render_data.render_size.h - (render_data.render_size.h * .4f));
entity->base_acceleration_per_s.meters = 32.f;
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, result, duration_ms, render_data.sprite);
return result;
}
+8 -8
View File
@@ -229,15 +229,15 @@ static FP_GameEntity *FP_Game_MakeEntityPointerFV(FP_Game *game, DQN_FMT_STRING_
result->hp_cap = FP_DEFAULT_DAMAGE;
result->hp = result->hp_cap;
result->inventory.airports_base_price = 4;
result->inventory.churchs_base_price = 2;
result->inventory.kennels_base_price = 2;
result->inventory.clubs_base_price = 2;
result->inventory.airports_base_price = 100;
result->inventory.churchs_base_price = 50;
result->inventory.kennels_base_price = 50;
result->inventory.clubs_base_price = 50;
result->inventory.stamina_base_price = 2;
result->inventory.health_base_price = 2;
result->inventory.mobile_plan_base_price = 2;
result->inventory.attack_base_price = 2;
result->inventory.stamina_base_price = 10;
result->inventory.health_base_price = 10;
result->inventory.mobile_plan_base_price = 10;
result->inventory.attack_base_price = 10;
// NOTE: Attach entity as a child to the parent
+16 -7
View File
@@ -223,9 +223,9 @@ struct FP_GameEntity
Dqn_usize coins;
FP_GameInventory inventory;
uint16_t hp;
Dqn_f32 hp;
uint16_t hp_cap;
uint16_t stamina;
Dqn_f32 stamina;
uint16_t stamina_cap;
bool converted_faction;
@@ -263,11 +263,17 @@ enum FP_GameAudio
FP_GameAudio_Count,
};
enum FP_GameActiveMenu
enum FP_GameInGameMenu
{
FP_GameActiveMenu_Nil,
FP_GameActiveMenu_Build,
FP_GameActiveMenu_Merchant,
FP_GameInGameMenu_Nil,
FP_GameInGameMenu_Build,
FP_GameInGameMenu_Merchant,
};
enum FP_GameState
{
FP_GameState_IntroScreen,
FP_GameState_Play,
};
struct FP_Game
@@ -275,6 +281,7 @@ struct FP_Game
Dqn_f32 delta_s_accumulator;
uint16_t tile_size;
TELY_ChunkPool *chunk_pool;
TELY_AssetFontHandle inter_regular_font_large;
TELY_AssetFontHandle inter_regular_font;
TELY_AssetFontHandle inter_italic_font;
TELY_AssetFontHandle jetbrains_mono_font;
@@ -319,7 +326,7 @@ struct FP_Game
Dqn_PCG32 rng;
bool debug_ui;
FP_GameActiveMenu active_menu;
FP_GameInGameMenu in_game_menu;
bool build_mode_can_place_building;
Dqn_usize build_mode_building_index;
@@ -330,6 +337,8 @@ struct FP_Game
uint32_t enemies_per_wave;
uint32_t enemies_spawned_this_wave;
uint64_t wave_cooldown_timestamp_ms;
FP_GameState state;
};
struct FP_GameAStarNode