fp: Integrate perry assets

This commit is contained in:
2023-10-21 16:30:15 +11:00
parent 253d2826c9
commit 5d37c49f51
68 changed files with 359 additions and 80 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -10,4 +10,4 @@ if not exist "%sprite_packer%" (
exit /B 1
)
%sprite_packer% 5100x5100 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\atlas || exit /b 1
%sprite_packer% 5200x5200 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\atlas || exit /b 1
+85 -66
View File
@@ -91,17 +91,16 @@ static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform,
static void FP_SetDefaultGamepadBindings(FP_GameControls *controls)
{
controls->up.gamepad_key = TELY_PlatformInputGamepadKey_DUp;
controls->down.gamepad_key = TELY_PlatformInputGamepadKey_DDown;
controls->left.gamepad_key = TELY_PlatformInputGamepadKey_DLeft;
controls->right.gamepad_key = TELY_PlatformInputGamepadKey_DRight;
controls->attack.gamepad_key = TELY_PlatformInputGamepadKey_X;
controls->range_attack.gamepad_key = TELY_PlatformInputGamepadKey_Y;
controls->build_mode.gamepad_key = TELY_PlatformInputGamepadKey_L3;
controls->strafe.gamepad_key = TELY_PlatformInputGamepadKey_B;
controls->dash.gamepad_key = TELY_PlatformInputGamepadKey_A;
controls->buy_building.gamepad_key = TELY_PlatformInputGamepadKey_LeftBumper;
controls->buy_upgrade.gamepad_key = TELY_PlatformInputGamepadKey_RightBumper;
// NOTE: Note up/down/left/right uses analog sticks, non-negotiable.
controls->attack.gamepad_key = TELY_PlatformInputGamepadKey_X;
controls->range_attack.gamepad_key = TELY_PlatformInputGamepadKey_Y;
controls->build_mode.gamepad_key = TELY_PlatformInputGamepadKey_L3;
controls->strafe.gamepad_key = TELY_PlatformInputGamepadKey_B;
controls->dash.gamepad_key = TELY_PlatformInputGamepadKey_A;
controls->buy_building.gamepad_key = TELY_PlatformInputGamepadKey_LeftBumper;
controls->buy_upgrade.gamepad_key = TELY_PlatformInputGamepadKey_RightBumper;
controls->move_building_ui_cursor_left.gamepad_key = TELY_PlatformInputGamepadKey_DLeft;
controls->move_building_ui_cursor_right.gamepad_key = TELY_PlatformInputGamepadKey_DRight;
}
static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
@@ -123,7 +122,14 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
bool gamepad_pressed = TELY_Platform_InputGamepadKeyIsPressed(input, gamepad_index, TELY_PlatformInputGamepadKey_Start);
if (keyboard_pressed || gamepad_pressed) {
FP_GameEntityHandle terry_handle = FP_Entity_CreateTerry(game, Dqn_V2_InitNx2(1380, 11), "Terry");
FP_GameEntityHandle terry_handle = {};
if (play->players.size) {
FP_GameEntityHandle player = play->players.data[play->players.size - 1];
Dqn_V2 player_pos = FP_Game_CalcEntityWorldPos(game, player);
terry_handle = FP_Entity_CreatePerry(game, player_pos, "Perry");
} else {
terry_handle = FP_Entity_CreateTerry(game, Dqn_V2_InitNx2(1380, 11), "Perry");
}
Dqn_FArray_Add(&play->players, terry_handle);
FP_GameEntity *terry = FP_Game_GetEntity(game, terry_handle);
@@ -131,29 +137,33 @@ static bool FP_ListenForNewPlayer(TELY_PlatformInput *input, FP_Game *game)
if (keyboard_pressed) {
controls->mode = FP_GameControlMode_Keyboard;
if (play->players.size == 1) {
controls->up.scan_code = TELY_PlatformInputScanCode_W;
controls->down.scan_code = TELY_PlatformInputScanCode_S;
controls->left.scan_code = TELY_PlatformInputScanCode_A;
controls->right.scan_code = TELY_PlatformInputScanCode_D;
controls->attack.scan_code = TELY_PlatformInputScanCode_G;
controls->range_attack.scan_code = TELY_PlatformInputScanCode_H;
controls->build_mode.scan_code = TELY_PlatformInputScanCode_F;
controls->strafe.scan_code = TELY_PlatformInputScanCode_J;
controls->dash.scan_code = TELY_PlatformInputScanCode_V;
controls->buy_building.scan_code = TELY_PlatformInputScanCode_T;
controls->buy_upgrade.scan_code = TELY_PlatformInputScanCode_Y;
controls->up.scan_code = TELY_PlatformInputScanCode_W;
controls->down.scan_code = TELY_PlatformInputScanCode_S;
controls->left.scan_code = TELY_PlatformInputScanCode_A;
controls->right.scan_code = TELY_PlatformInputScanCode_D;
controls->attack.scan_code = TELY_PlatformInputScanCode_G;
controls->range_attack.scan_code = TELY_PlatformInputScanCode_H;
controls->build_mode.scan_code = TELY_PlatformInputScanCode_F;
controls->strafe.scan_code = TELY_PlatformInputScanCode_J;
controls->dash.scan_code = TELY_PlatformInputScanCode_V;
controls->buy_building.scan_code = TELY_PlatformInputScanCode_T;
controls->buy_upgrade.scan_code = TELY_PlatformInputScanCode_Y;
controls->move_building_ui_cursor_left.scan_code = TELY_PlatformInputScanCode_Q;
controls->move_building_ui_cursor_right.scan_code = TELY_PlatformInputScanCode_E;
} else {
controls->up.scan_code = TELY_PlatformInputScanCode_O;
controls->down.scan_code = TELY_PlatformInputScanCode_L;
controls->left.scan_code = TELY_PlatformInputScanCode_K;
controls->right.scan_code = TELY_PlatformInputScanCode_Semicolon;
controls->attack.scan_code = TELY_PlatformInputScanCode_Right;
controls->range_attack.scan_code = TELY_PlatformInputScanCode_Left;
controls->build_mode.scan_code = TELY_PlatformInputScanCode_Up;
controls->strafe.scan_code = TELY_PlatformInputScanCode_N;
controls->dash.scan_code = TELY_PlatformInputScanCode_Down;
controls->buy_building.scan_code = TELY_PlatformInputScanCode_Backslash;
controls->buy_upgrade.scan_code = TELY_PlatformInputScanCode_Apostrophe;
controls->up.scan_code = TELY_PlatformInputScanCode_O;
controls->down.scan_code = TELY_PlatformInputScanCode_L;
controls->left.scan_code = TELY_PlatformInputScanCode_K;
controls->right.scan_code = TELY_PlatformInputScanCode_Semicolon;
controls->attack.scan_code = TELY_PlatformInputScanCode_Right;
controls->range_attack.scan_code = TELY_PlatformInputScanCode_Left;
controls->build_mode.scan_code = TELY_PlatformInputScanCode_Up;
controls->strafe.scan_code = TELY_PlatformInputScanCode_N;
controls->dash.scan_code = TELY_PlatformInputScanCode_Down;
controls->buy_building.scan_code = TELY_PlatformInputScanCode_Backslash;
controls->buy_upgrade.scan_code = TELY_PlatformInputScanCode_Apostrophe;
controls->move_building_ui_cursor_left.scan_code = TELY_PlatformInputScanCode_I;
controls->move_building_ui_cursor_right.scan_code = TELY_PlatformInputScanCode_P;
}
} else {
controls->mode = FP_GameControlMode_Gamepad;
@@ -506,9 +516,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, entity->action.state, entity->direction);
switch (entity->type) {
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Terry: {
FP_EntityTerryState *state = DQN_CAST(FP_EntityTerryState *) & action->state;
{
FP_GameEntity *portal_monkey = FP_Game_GetEntity(game, entity->carried_monkey);
if (!FP_Game_IsNilEntity(portal_monkey)) {
@@ -537,7 +547,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
// NOTE: Check if we are nearby a monkey and picking it up
FP_GetClosestPortalMonkeyResult closest_monkey = FP_GetClosestPortalMonkey(game, entity->handle);
if (closest_monkey.dist < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game->play, 2.f))) {
if (TELY_Platform_InputScanCodeIsPressed(input, controls->attack.scan_code)) {
if (FP_Game_KeyBindIsPressed(input, controls, controls->attack)) {
entity->carried_monkey = closest_monkey.entity;
picked_up_monkey_this_frame = true;
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Monkey], 1.f);
@@ -552,7 +562,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_RangeAttack);
}
} else {
if (!picked_up_monkey_this_frame && TELY_Platform_InputScanCodeIsPressed(input, controls->attack.scan_code)) {
if (!picked_up_monkey_this_frame && FP_Game_KeyBindIsPressed(input, controls, controls->attack)) {
FP_GameEntity *portal_monkey = FP_Game_GetEntity(game, entity->carried_monkey);
portal_monkey->local_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
entity->carried_monkey = {};
@@ -600,7 +610,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
// NOTE: Check if we are nearby a monkey and picking it up
FP_GetClosestPortalMonkeyResult closest_monkey = FP_GetClosestPortalMonkey(game, entity->handle);
if (closest_monkey.dist < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game->play, 2.f))) {
if (TELY_Platform_InputScanCodeIsPressed(input, controls->attack.scan_code)) {
if (FP_Game_KeyBindIsPressed(input, controls, controls->attack)) {
entity->carried_monkey = closest_monkey.entity;
picked_up_monkey_this_frame = true;
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Monkey], 1.f);
@@ -1207,6 +1217,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
case FP_EntityType_Count: break;
case FP_EntityType_Terry: /*FALLTHRU*/
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Catfish: /*FALLTHRU*/
case FP_EntityType_Clinger: /*FALLTHRU*/
case FP_EntityType_Smoochie: {
@@ -1220,7 +1231,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
} else if (entity->type == FP_EntityType_Smoochie) {
is_attacking = entity->action.state == FP_EntitySmoochieState_Attack;
} else {
DQN_ASSERT(entity->type == FP_EntityType_Terry);
DQN_ASSERT(entity->type == FP_EntityType_Terry || entity->type == FP_EntityType_Perry);
is_range_attack = entity->action.state == FP_EntityTerryState_RangeAttack;
is_attacking = is_range_attack || entity->action.state == FP_EntityTerryState_Attack;
}
@@ -1286,16 +1297,20 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
game->play.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->play.state == FP_GameState_Play) {
if (TELY_Platform_InputKeyIsReleased(input->mouse_left))
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'
if (FP_DEVELOPER_MODE && TELY_Platform_InputKeyIsReleased(input->mouse_left))
game->play.clicked_entity = game->play.prev_active_entity;
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Escape))
game->play.state = FP_GameState_Pause;
if (game->play.clicked_entity.id) {
if (FP_DEVELOPER_MODE && game->play.clicked_entity.id) {
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Delete))
FP_Game_DeleteEntity(game, game->play.clicked_entity);
}
DQN_MSVC_WARNING_POP
// NOTE: Handle input ==========================================================================
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->play.root_entity); ) {
@@ -1319,12 +1334,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
dir_vector.x = +1.f;
// NOTE: Gamepad movement input
// NOTE: button_codes 0 should be the first gamepad connected, we can
// get this working with other gamepads later
uint32_t gamepad = 0;
if (input->button_codes[gamepad]) {
dir_vector.x += input->left_stick[gamepad].x;
dir_vector.y += input->left_stick[gamepad].y;
if (controls->mode == FP_GameControlMode_Gamepad) {
dir_vector.x += input->left_stick[controls->gamepad_index].x;
dir_vector.y += input->left_stick[controls->gamepad_index].y;
}
// TODO(doyle): Some bug, diagonal is still faster
@@ -1339,6 +1351,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
if (entity->flags & (FP_GameEntityFlag_MoveByKeyboard | FP_GameEntityFlag_MoveByGamepad)) {
bool move_entity = true;
switch (entity->type) {
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Terry: {
auto *state = DQN_CAST(FP_EntityTerryState *)&entity->action.state;
move_entity = *state == FP_EntityTerryState_Run || *state == FP_EntityTerryState_Idle;
@@ -1376,22 +1389,20 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
case FP_EntityType_ChurchTerry: break;
case FP_EntityType_KennelTerry: break;
case FP_EntityType_PhoneMessageProjectile: break;
case FP_EntityType_AirportTerryPlane: break;
case FP_EntityType_MobSpawner:
case FP_EntityType_PortalMonkey: break;
case FP_EntityType_Billboard: break;
case FP_EntityType_AirportTerryPlane: break;
case FP_EntityType_MobSpawner: break;
case FP_EntityType_PortalMonkey: break;
case FP_EntityType_Billboard: break;
}
if (move_entity)
acceleration_meters_per_s = dir_vector * entity->base_acceleration_per_s.meters;
acceleration_meters_per_s += dir_vector * entity->base_acceleration_per_s.meters;
}
if (dir_vector == Dqn_V2_Zero) {
if (entity->velocity.x)
entity->direction = entity->velocity.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (entity->velocity.y)
entity->direction = entity->velocity.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
}
if (entity->velocity.x)
entity->direction = entity->velocity.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (entity->velocity.y)
entity->direction = entity->velocity.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
// NOTE: Determine AI movement =============================================================
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
@@ -1425,7 +1436,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
if (dist_to_defender > (aggro_dist_threshold * 1.5f)) {
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate<FP_GameWaypoint>(&entity->waypoints, &link); ) {
FP_GameEntity *maybe_terry = FP_Game_GetEntity(game, link->data.entity);
if (maybe_terry->type == FP_EntityType_Terry) {
if (maybe_terry->type == FP_EntityType_Terry || maybe_terry->type == FP_EntityType_Perry) {
link = FP_SentinelList_Erase(&entity->waypoints, link, game->play.chunk_pool);
}
}
@@ -1621,7 +1632,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
acceleration_meters_per_s = entity_to_waypoint_norm * (entity->base_acceleration_per_s.meters * 0.25f);
if (entity->type == FP_EntityType_Smoochie) {
if (waypoint_entity->type == FP_EntityType_Terry) {
if (waypoint_entity->type == FP_EntityType_Terry || waypoint_entity->type == FP_EntityType_Perry) {
if (dist_to_waypoint_sq < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game->play, 2.f)) &&
!entity->smoochie_has_teleported) {
@@ -1731,13 +1742,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
if (can_attack) {
switch (entity->type) {
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Terry: /*FALLTHRU*/
case FP_EntityType_Smoochie: /*FALLTHRU*/
case FP_EntityType_Catfish: /*FALLTHRU*/
case FP_EntityType_Clinger: {
// TODO(doyle): We should check if it's valid to enter this new state
// from the entity's current state
if (entity->type == FP_EntityType_Terry) {
if (entity->type == FP_EntityType_Terry || entity->type == FP_EntityType_Perry) {
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Attack);
} else if (entity->type == FP_EntityType_Smoochie) {
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Attack);
@@ -1803,7 +1815,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
// NOTE: Building selector =========================================================
Dqn_usize const last_building_index = DQN_ARRAY_UCOUNT(PLACEABLE_BUILDINGS) - 1;
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_Q)) {
if (FP_Game_KeyBindIsPressed(input, controls, controls->move_building_ui_cursor_left)) {
if (entity->build_mode_building_index <= 0) {
entity->build_mode_building_index = last_building_index;
} else {
@@ -1811,7 +1823,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
}
}
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_E)) {
if (FP_Game_KeyBindIsPressed(input, controls, controls->move_building_ui_cursor_left)) {
if (entity->build_mode_building_index >= last_building_index) {
entity->build_mode_building_index = 0;
} else {
@@ -3084,7 +3096,7 @@ 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); };
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, FP_EntityType_Terry, FP_EntityTerryState_Idle, FP_GameDirection_Down);
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, player->type, 0 /*state, usually 0 is idle*/, FP_GameDirection_Down);
player_avatar_rect.size = render_data.render_size;
TELY_Render_TextureColourV4(renderer,
@@ -3623,7 +3635,11 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
}
// NOTE: Debug UI ==============================================================================
if (game->play.debug_ui) {
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'
if (FP_DEVELOPER_MODE && game->play.debug_ui) {
DQN_MSVC_WARNING_POP
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
@@ -3755,7 +3771,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
TELY_RFui_Flush(rfui, renderer, input, assets);
}
if (game->play.state == FP_GameState_Play) {
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE'
if (FP_DEVELOPER_MODE && game->play.state == FP_GameState_Play) {
DQN_MSVC_WARNING_POP
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
DQN_DEFER { TELY_Render_PopTransform(renderer); };
+20
View File
@@ -127,6 +127,26 @@ struct FP_GlobalAnimations
Dqn_String8 terry_walk_down = DQN_STRING8("terry_walk_down");
Dqn_String8 terry_walk_left = DQN_STRING8("terry_walk_left");
Dqn_String8 terry_walk_right = DQN_STRING8("terry_walk_right");
Dqn_String8 perry_attack_up = DQN_STRING8("perry_attack_up");
Dqn_String8 perry_attack_side = DQN_STRING8("perry_attack_side");
Dqn_String8 perry_attack_down = DQN_STRING8("perry_attack_down");
Dqn_String8 perry_attack_phone_up = DQN_STRING8("perry_attack_phone_up");
Dqn_String8 perry_attack_phone_side = DQN_STRING8("perry_attack_phone_side");
Dqn_String8 perry_attack_phone_down = DQN_STRING8("perry_attack_phone_down");
Dqn_String8 perry_death = DQN_STRING8("perry_death");
Dqn_String8 perry_pat_dog = DQN_STRING8("perry_pat_dog");
Dqn_String8 perry_ghost = DQN_STRING8("perry_ghost");
Dqn_String8 perry_walk_idle = DQN_STRING8("perry_walk_idle");
Dqn_String8 perry_walk_up = DQN_STRING8("perry_walk_up");
Dqn_String8 perry_walk_down = DQN_STRING8("perry_walk_down");
Dqn_String8 perry_walk_right = DQN_STRING8("perry_walk_right");
}
g_anim_names;
#if defined(DQN_PLATFORM_EMSCRIPTEN)
#define FP_DEVELOPER_MODE 0
#else
#define FP_DEVELOPER_MODE 0
#endif
+54
View File
@@ -83,6 +83,60 @@ static FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType
}
} break;
case FP_EntityType_Perry: {
result.height.meters = 1.72f;
FP_EntityPerryState state = DQN_CAST(FP_EntityPerryState)raw_state;
switch (state) {
case FP_EntityTerryState_Idle: {
result.anim_name = g_anim_names.perry_walk_idle;
} break;
case FP_EntityTerryState_Attack: {
switch (direction) {
case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_attack_up; result.height.meters *= 1.5f; break;
case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_attack_down; result.height.meters *= 1.6f; break;
case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_attack_side; result.height.meters *= 1.5f; break;
case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_attack_side; result.height.meters *= 1.5f; result.flip = TELY_AssetFlip_X; break;
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
}
} break;
case FP_EntityTerryState_RangeAttack: {
switch (direction) {
case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_attack_phone_up; result.height.meters *= 1.35f; break;
case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_attack_phone_down; result.height.meters *= 1.35f; break;
case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_attack_phone_side; result.height.meters *= 1.35f; result.flip = TELY_AssetFlip_X; break;
case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_attack_phone_side; result.height.meters *= 1.35f; break;
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
}
} break;
case FP_EntityTerryState_Dash: {
switch (direction) {
case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_ghost; break;
case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_ghost; break;
case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_ghost; break;
case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_ghost; result.flip = TELY_AssetFlip_X; break;
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
}
} break;
case FP_EntityTerryState_Run: {
switch (direction) {
case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_walk_up; break;
case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_walk_down; break;
case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_walk_right; result.flip = TELY_AssetFlip_X; break;
case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_walk_right; break;
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
}
} break;
case FP_EntityTerryState_DeadGhost: {
result.anim_name = g_anim_names.perry_death; break;
} break;
}
} break;
case FP_EntityType_Smoochie: {
result.height.meters = 1.6f;
FP_EntitySmoochieState state = DQN_CAST(FP_EntitySmoochieState)raw_state;
+2
View File
@@ -23,6 +23,7 @@ enum FP_EntityType
FP_EntityType_PortalMonkey,
FP_EntityType_Smoochie,
FP_EntityType_Terry,
FP_EntityType_Perry,
FP_EntityType_PhoneMessageProjectile,
FP_EntityType_Billboard,
FP_EntityType_Count,
@@ -37,6 +38,7 @@ enum FP_EntityTerryState
FP_EntityTerryState_Dash,
FP_EntityTerryState_DeadGhost,
};
typedef FP_EntityTerryState FP_EntityPerryState;
enum FP_EntityMobSpawnerState
{
+20 -5
View File
@@ -167,15 +167,12 @@ static FP_GameEntityHandle FP_Entity_CreateMobSpawner(FP_Game *game, Dqn_V2 pos,
return result;
}
static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
static FP_GameEntityHandle FP_Entity_CreateTerryInternal(FP_Game *game, Dqn_V2 pos, bool is_perry, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args)
{
va_list args;
va_start(args, fmt);
FP_GameEntity *entity = FP_Game_MakeEntityPointerFV(game, fmt, args);
FP_GameEntityHandle result = entity->handle;
va_end(args);
entity->type = FP_EntityType_Terry;
entity->type = is_perry ? FP_EntityType_Perry : FP_EntityType_Terry;
entity->local_pos = pos;
entity->base_acceleration_per_s.meters = 16.f;
@@ -199,6 +196,24 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
return result;
}
static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
FP_GameEntityHandle result = FP_Entity_CreateTerryInternal(game, pos, false /*is_perry*/, fmt, args);
va_end(args);
return result;
}
static FP_GameEntityHandle FP_Entity_CreatePerry(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
FP_GameEntityHandle result = FP_Entity_CreateTerryInternal(game, pos, true /*is_perry*/, fmt, args);
va_end(args);
return result;
}
static FP_GameEntityHandle FP_Entity_CreateMerchantTerry(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
{
va_list args;
+2
View File
@@ -825,6 +825,7 @@ static bool FP_Game_CanEntityAttack(FP_GameEntity *entity, uint64_t current_time
static void FP_Game_EntityTransitionState(FP_Game *game, FP_GameEntity *entity, uint32_t desired_state)
{
switch (entity->type) {
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Terry: {
if (desired_state == FP_EntityTerryState_Attack ||
desired_state == FP_EntityTerryState_RangeAttack) {
@@ -979,6 +980,7 @@ static FP_GameCanMoveToPositionResult FP_Game_CanEntityMoveToPosition(FP_Game *g
}
} break;
case FP_EntityType_Perry: /*FALLTHRU*/
case FP_EntityType_Terry: {
// NOTE: Don't collide with mobs when dashing (e.g. phase through)
FP_EntityTerryState state = *DQN_CAST(FP_EntityTerryState *)&entity->action.state;
+2
View File
@@ -188,6 +188,8 @@ struct FP_GameControls
FP_GameKeyBind attack;
FP_GameKeyBind buy_building;
FP_GameKeyBind buy_upgrade;
FP_GameKeyBind move_building_ui_cursor_left;
FP_GameKeyBind move_building_ui_cursor_right;
FP_GameKeyBind range_attack;
FP_GameKeyBind build_mode;
FP_GameKeyBind strafe;
BIN
View File
Binary file not shown.