fp: Integrate perry assets
This commit is contained in:
parent
253d2826c9
commit
5d37c49f51
BIN
Data/Textures/atlas.png (Stored with Git LFS)
BIN
Data/Textures/atlas.png (Stored with Git LFS)
Binary file not shown.
BIN
Data/Textures/atlas.txt (Stored with Git LFS)
BIN
Data/Textures/atlas.txt (Stored with Git LFS)
Binary file not shown.
BIN
Data/Textures/atlas/end_screen.png (Stored with Git LFS)
BIN
Data/Textures/atlas/end_screen.png (Stored with Git LFS)
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.
BIN
Data/Textures/sprite_spec.txt (Stored with Git LFS)
BIN
Data/Textures/sprite_spec.txt (Stored with Git LFS)
Binary file not shown.
|
@ -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
|
||||
|
|
151
feely_pona.cpp
151
feely_pona.cpp
|
@ -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
feely_pona.h
20
feely_pona.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue