refactor playermovement

This commit is contained in:
2023-05-01 19:43:58 +03:00
parent f5f0af31a2
commit 14b4426d04
5 changed files with 252 additions and 212 deletions

View File

@@ -21,7 +21,7 @@ namespace Game
playerMovement = playerActor.GetScript<PlayerMovement>();
viewModelHolder = playerActor.GetChild("ViewModelHolder");
lastGround = playerMovement.onGround;
lastGround = playerMovement.OnGround;
targetOffset = Actor.LocalPosition;
}
@@ -36,7 +36,7 @@ namespace Game
Float3 position = Actor.Parent.Position + targetOffset;
Float3 targetPosition = position;
if (playerMovement.onGround)
if (playerMovement.OnGround)
{
float deltaY = position.Y - lastPosition.Y;
//if (Mathf.Abs(deltaY) < 10f)
@@ -69,7 +69,7 @@ namespace Game
}
lastPosition = position;
lastGround = playerMovement.onGround;
lastGround = playerMovement.OnGround;
}
}
}

View File

@@ -17,11 +17,19 @@ namespace Game
#endif
}
private readonly InputEvent onExit = new InputEvent("Exit");
public override void Initialize()
{
//FlaxEngine.Debug.Log("ConsolePlugin initialized");
Console.Init();
onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};
//AssetManager.Init(); // TODO: move these elsewhere
#if !FLAX_EDITOR
Level.SceneLoading += OnSceneLoading;
@@ -31,6 +39,7 @@ namespace Game
public override void Deinitialize()
{
onExit.Dispose();
#if !FLAX_EDITOR
Level.SceneLoading -= OnSceneLoading;
Level.SceneLoaded -= OnSceneLoaded;
@@ -86,11 +95,19 @@ namespace Game
_description = DescriptionInternal;
}
//private readonly InputEvent onExit = new InputEvent("Exit");
public override void Initialize()
{
//FlaxEngine.Debug.Log("ConsolePlugin initialized");
Console.Init();
/*onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};*/
//AssetManager.Init();
Level.SceneLoading += OnSceneLoading;
@@ -112,6 +129,8 @@ namespace Game
FlaxEditor.Editor.Instance.PlayModeEnd -= OnPlayModeEnd;
}*/
private void OnPlayModeBegin()
{
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
@@ -124,12 +143,14 @@ namespace Game
private void OnPlayModeEnd()
{
//onExit.Dispose();
//GameMode.StopServer();
NetworkManager.Cleanup();
}
public override void Deinitialize()
{
//onExit.Dispose();
//Level.SceneLoaded -= OnSceneLoaded;
Level.SceneLoading -= OnSceneLoading;
if (FlaxEditor.Editor.Instance != null)

View File

@@ -428,10 +428,10 @@ namespace Game
if (!NetworkManager.IsLocalClient && playerInput is PlayerInputNetwork)
{
playerActor.Position = actorState.position;
playerActor.GetScript<PlayerMovement>().currentVelocity = actorState.velocity;
playerActor.GetScript<PlayerMovement>().lastJumped = actorState.lastJumpTime;
playerActor.GetScript<PlayerMovement>().numJumps = actorState.numJumps;
playerActor.GetScript<PlayerMovement>().jumped = actorState.jumped;
playerActor.GetScript<PlayerMovement>().movementState.currentVelocity = actorState.velocity;
playerActor.GetScript<PlayerMovement>().movementState.lastJumped = actorState.lastJumpTime;
playerActor.GetScript<PlayerMovement>().movementState.numJumps = actorState.numJumps;
playerActor.GetScript<PlayerMovement>().movementState.jumped = actorState.jumped;
playerActor.GetScript<PlayerMovement>().SetCameraEulerAngles(actorState.viewAngles, true);
}
//playerActor.SetPosition(reportedPosition);
@@ -468,12 +468,13 @@ namespace Game
playerActor.GetScript<PlayerMovement>().input.SetState(serverWorldState.frame, new PlayerInputState(), new PlayerActorState()
{
position = playerActor.Position,
velocity = playerActor.GetScript<PlayerMovement>().currentVelocity,
velocity = playerActor.GetScript<PlayerMovement>().movementState.currentVelocity,
orientation = playerActor.GetScript<PlayerMovement>().rootActor.Orientation,
viewAngles = playerActor.GetScript<PlayerMovement>().viewAngles,
lastJumpTime = playerActor.GetScript<PlayerMovement>().lastJumped,
numJumps = playerActor.GetScript<PlayerMovement>().numJumps,
jumped = playerActor.GetScript<PlayerMovement>().jumped,
lastJumpTime = playerActor.GetScript<PlayerMovement>().movementState.lastJumped,
numJumps = playerActor.GetScript<PlayerMovement>().movementState.numJumps,
jumped = playerActor.GetScript<PlayerMovement>().movementState.jumped,
//onGround = playerActor.GetScript<PlayerMovement>().movementState.onGround,
});
}
NetworkManager.ServerEndSendMessage(ref message, connection);
@@ -594,12 +595,13 @@ namespace Game
playerMovement.input.SetState(frame, lastInputState, new PlayerActorState()
{
position = playerActor.Position,
velocity = playerMovement.currentVelocity,
velocity = playerMovement.movementState.currentVelocity,
orientation = playerMovement.rootActor.Orientation,
viewAngles = playerMovement.viewAngles,
lastJumpTime = playerMovement.lastJumped,
numJumps = playerMovement.numJumps,
jumped = playerMovement.jumped,
lastJumpTime = playerMovement.movementState.lastJumped,
numJumps = playerMovement.movementState.numJumps,
jumped = playerMovement.movementState.jumped,
//onGround = playerMovement.movementState.onGround,
});
simframs++;

View File

@@ -134,6 +134,7 @@ namespace Game
public void SetPosition(Float3 newPosition)
{
Position = newPosition;
playerMovement.movementState.position = newPosition;
}
public void SetRotation(Float3 eulerAngles)

View File

@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using FlaxEngine;
using FlaxEngine.Assertions;
@@ -8,6 +11,76 @@ using Console = Game.Console;
namespace Game
{
public class PlayerMovementParameters
{
// FIXME, should be much smaller but needed to avoid issues with box collider edges against brush edges diagonally
public float collisionMargin { get; } = 0.031f * 1.666f * 1.85f;
public float slopeNormal { get; } = 0.7f;
public float moveSpeed { get; } = 320f;
public Float3 gravity { get; } = new Float3(0, -800.0f, 0f);
/*
// QW
public float friction = 4f;
public float stopspeed = 100f;
public float accelerationGround = 10f;
public float jumpVelocity = 270f;
public float maxAirSpeed = 320f;
public float maxAirStrafeSpeed = 30f; //Q2+
public float airAcceleration = 0f; //Q2+
public float airStopAcceleration = 0f; //Q2+
public float airStrafeAcceleration = 0f; //CPM?
public float strafeAcceleration = 10f; //QW
public float airControl = 0f; //CPM
public float stepSize = 16f;
public float autoJumpTime = 0.4f;
public int airStep = 0;
*/
// GOA
public float friction { get; } = 6f;
public float stopspeed { get; } = 100f;
public float accelerationGround { get; } = 12f;
public float jumpVelocity { get; } = 270f;
public float jumpBoostTime { get; } = 0.5f;
public float jumpBoostVelocity { get; } = 100f;
public int jumpBoostMaxJumps { get; } = 2;
public bool jumpStairBehavior { get; } = true;
public bool jumpAdditive { get; } = true;
public float maxAirSpeed { get; } = 320f;
public float maxAirStrafeSpeed { get; } = 30f;
public float airAcceleration { get; } = 0.4f;
public float airStopAcceleration { get; } = 2.5f;
public float airStrafeAcceleration { get; } = 0f;
public float strafeAcceleration { get; } = 10f;
public float airControl { get; } = 0f;
public float stepHeight { get; } = 16f;
public float autoJumpTime { get; } = 0.4f;
public int airStep { get; } = 2;
}
public struct PlayerMovementState
{
public Float3 position;
public Float3 currentVelocity;
//public Quaternion orientation;
public Float3 viewAngles; // yaw, pitch, roll
public float lastJumped = -1f;
public float lastLanded = -1f;
public int numJumps;
public bool jumped;
public bool onGround;
public PlayerMovementState()
{
}
}
public struct TraceInfo
{
public RayCastHit[] hitInfos;
@@ -25,60 +98,15 @@ namespace Game
//public Float3 maxEndPosition;
}
//[Networked]
public class PlayerMovement : Script
{
// FIXME, should be much smaller but needed to avoid issues with box collider edges against brush edges diagonally
private const float collisionMargin = 0.031f * 1.666f * 1.85f;
private const float slopeNormal = 0.7f;
private PlayerMovementParameters movementParameters = new PlayerMovementParameters();
public PlayerMovementState movementState = new PlayerMovementState();
/*
// QW
private const float friction = 4f;
private const float stopspeed = 100f;
private const float accelerationGround = 10f;
private const float jumpVelocity = 270f;
private const float maxAirSpeed = 320f;
private const float maxAirStrafeSpeed = 30f; //Q2+
private const float airAcceleration = 0f; //Q2+
private const float airStopAcceleration = 0f; //Q2+
private const float airStrafeAcceleration = 0f; //CPM?
private const float strafeAcceleration = 10f; //QW
private const float airControl = 0f; //CPM
private const float stepSize = 16f;
private const float autoJumpTime = 0.4f;
private const int airStep = 0;
*/
// GOA
private const float friction = 6f;
private const float stopspeed = 100f;
private const float accelerationGround = 12f;
private const float jumpVelocity = 270f;
private const float jumpBoostTime = 0.5f;
private const float jumpBoostVelocity = 100f;
private const int jumpBoostMaxJumps = 2;
private const bool jumpStairBehavior = true;
private const bool jumpAdditive = true;
private const float maxAirSpeed = 320f;
private const float maxAirStrafeSpeed = 30f;
private const float airAcceleration = 0.4f;
private const float airStopAcceleration = 2.5f;
private const float airStrafeAcceleration = 0f;
private const float strafeAcceleration = 10f;
private const float airControl = 0f;
private const float stepHeight = 16f;
private const float autoJumpTime = 0.4f;
private const int airStep = 2;
private readonly bool demoDeltasCorrect = true;
private readonly bool demoDeltasVerify = true;
private readonly InputEvent onExit = new InputEvent("Exit");
private bool predicting = false;
@@ -86,20 +114,18 @@ namespace Game
//public int currentInputFrame;
//private int currentInputFrame2;
public Float3 currentVelocity;
public PlayerInput input;
//private bool physicsInteractions = false;
public bool jumped;
public bool OnGround => movementState.onGround;
//private int lastInputFrame;
public float lastJumped = -1f;
private float lastLanded = -1f;
public int numJumps;
private float simulationTime = 0f;
[ReadOnly] public bool onGround;
private RigidBody rigidBody;
private Actor cameraHolder;
@@ -109,21 +135,13 @@ namespace Game
public Float3 viewAngles;
private Float3 viewAnglesLastFrame;
[Limit(0, 9000)]
[Tooltip("Base Movement speed")]
public float MoveSpeed { get; set; } = 320;
private static Float3 Gravity { get; } = new Float3(0, -800.0f, 0f);
//private Float3 safePosition;444 rg
[NetworkReplicated]
public uint PlayerId = 0;
[ReadOnly]
public float CurrentVelocity
{
get => currentVelocity.Length;
get => movementState.currentVelocity.Length;
set { }
}
@@ -132,7 +150,7 @@ namespace Game
{
get
{
Float3 horizontalSpeed = currentVelocity;
Float3 horizontalSpeed = movementState.currentVelocity;
horizontalSpeed.Y = 0f;
return horizontalSpeed.Length;
}
@@ -143,13 +161,6 @@ namespace Game
{
base.OnAwake();
onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};
Console.Print("player awake, playerid: " + PlayerId);
rootActor = Actor.GetChild("RootActor");
rigidBody = Actor.As<RigidBody>();
@@ -190,12 +201,13 @@ namespace Game
{
input = new PlayerInputDemo(demoFile);
/*Actor.Position = input.GetCurrentActorState().position;
/*movementState.position = input.GetCurrentActorState().position;
currentVelocity = input.GetCurrentActorState().velocity; f
SetCameraEulerAngles(input.GetCurrentActorState().viewAngles);*/
Actor.Position = input.GetCurrentInputState().verificationPosition;
movementState.position = input.GetCurrentInputState().verificationPosition;
Actor.Position = movementState.position;
//rootActor.Orientation = input.GetCurrentInputState().verificationOrientation;
currentVelocity = input.GetCurrentInputState().verificationVelocity;
movementState.currentVelocity = input.GetCurrentInputState().verificationVelocity;
SetCameraEulerAngles(input.GetCurrentInputState().verificationViewAngles);
}
@@ -239,8 +251,6 @@ namespace Game
public override void OnDestroy()
{
base.OnDestroy();
onExit.Dispose();
}
public override void OnStart()
@@ -269,7 +279,7 @@ namespace Game
/*if (input.frame > 0)
{
PlayerActorState actorState = input.GetCurrentActorState();
Actor.Position = actorState.position;
movementState.position = actorState.position;
currentVelocity = actorState.velocity;
viewYaw = actorState.viewYaw;
viewPitch = actorState.viewPitch;
@@ -291,20 +301,20 @@ namespace Game
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
position = movementState.position,
velocity = movementState.currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
lastJumpTime = movementState.lastJumped,
numJumps = movementState.numJumps,
jumped = movementState.jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
}
/*input.RecordCurrentActorState(new PlayerActorState()
{
position = Actor.Position,
position = movementState.position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewYaw = viewYaw,
@@ -314,7 +324,6 @@ namespace Game
//currentInputFrame2++;
}
private ulong lastPredictedFrame = 0;
public override void OnFixedUpdate()
{
PlayerInputDemo demoInput = input as PlayerInputDemo;
@@ -350,11 +359,11 @@ namespace Game
if (demoDeltasVerify)
{
// verify
float positionDelta = (Actor.Position - inputState.verificationPosition).Length;
float positionDelta = (movementState.position - inputState.verificationPosition).Length;
if (positionDelta > 0.00001)
Console.Print("Demo verification failed, position delta: " + positionDelta);
float velocityDelta = (currentVelocity - inputState.verificationVelocity).Length;
float velocityDelta = (movementState.currentVelocity - inputState.verificationVelocity).Length;
if (velocityDelta > 0.00001)
Console.Print("Demo verification failed, velocity delta: " + velocityDelta);
@@ -371,7 +380,7 @@ namespace Game
//if (currentInputFrame == 0)
/*{
//Console.Print("repos: " + inputState.verificationPosition);
Actor.Position = inputState.verificationPosition;
movementState.position = inputState.verificationPosition;
currentVelocity = inputState.verificationVelocity;
rootActor.Orientation = inputState.verificationOrientation;
}*/
@@ -417,14 +426,14 @@ namespace Game
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
movementState.position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
SetCameraEulerAngles(pastActorState.viewAngles, true);
if (Actor.Position.Length < 0.1)
if (movementState.position.Length < 0.1)
jumped = jumped;
continue;
@@ -445,7 +454,7 @@ namespace Game
break;
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
/*if ((movementState.position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
@@ -479,8 +488,8 @@ namespace Game
}
else
{
if (Actor.Position.Length < 0.1)
jumped = jumped;
if (movementState.position.Length < 0.1)
movementState.jumped = movementState.jumped;
//viewAngles = viewAnglesLastFrame;
//ApplyInputToCamera(inputState);
@@ -506,8 +515,8 @@ namespace Game
if (canpredict)
{
var oldAngles = viewAngles;
var oldPos = Actor.Position;
var oldVel = currentVelocity;
var oldPos = movementState.position;
var oldVel = movementState.currentVelocity;
@@ -522,15 +531,16 @@ namespace Game
}
if (currentFrame == inputState.frame)
jumped = jumped;
movementState.jumped = movementState.jumped;
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
movementState.position = pastActorState.position;
movementState.currentVelocity = pastActorState.velocity;
movementState.lastJumped = pastActorState.lastJumpTime;
movementState.numJumps = pastActorState.numJumps;
movementState.jumped = pastActorState.jumped;
Actor.Position = movementState.position;
SetCameraEulerAngles(pastActorState.viewAngles, true);
//cameraHolder.Orientation = Quaternion.Euler(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
//ApplyInputToCamera(pastInputState, true);
@@ -538,8 +548,8 @@ namespace Game
//if (pastActorState.viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved server frame: {currentFrame}, {pastActorState.viewAngles}");
if (Actor.Position.Length < 0.1)
jumped = jumped;
if (movementState.position.Length < 0.1)
movementState.jumped = movementState.jumped;
continue;
//rootActor.Orientation = pastActorState.orientation;
@@ -557,7 +567,7 @@ namespace Game
// ApplyInputToCamera(pastInputState, true);
SimulatePlayerMovement(pastInputState);
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
/*if ((movementState.position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
@@ -569,15 +579,15 @@ namespace Game
predicting = false;
if ((Actor.Position - oldPos).Length > 0.001)
if ((movementState.position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
if ((movementState.currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");
//if (input is not PlayerInputNetwork)
{
/*if ((Actor.Position - oldPos).Length > 0.001)
/*if ((movementState.position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
@@ -612,15 +622,15 @@ namespace Game
SimulatePlayerMovement(inputState);
}
if (Actor.Position.Length < 0.1)
jumped = jumped;
if (movementState.position.Length < 0.1)
movementState.jumped = movementState.jumped;
//if (currentVelocity.Length > 0)
// Console.Print($"velocity at frame {GameModeManager.ClientFrame}");
/*if (input.GetState(GameModeManager.ClientFrame - 1, out var pastInputState2, out var pastActorState2))
{
Actor.Position = pastActorState2.position;
movementState.position = pastActorState2.position;
currentVelocity = pastActorState2.velocity;
rootActor.Orientation = pastActorState2.orientation;
viewAngles = new Float3(pastActorState2.viewAngles.Y, pastActorState2.viewAngles.X, pastActorState2.viewAngles.Z);
@@ -638,13 +648,13 @@ namespace Game
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
position = movementState.position,
velocity = movementState.currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
lastJumpTime = movementState.lastJumped,
numJumps = movementState.numJumps,
jumped = movementState.jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
@@ -652,11 +662,11 @@ namespace Game
input.OnEndFrame();
}
if (Actor.Position.Length < 0.1)
jumped = jumped;
if (movementState.position.Length < 0.1)
movementState.jumped = movementState.jumped;
if (input is PlayerInputNetwork)
jumped = jumped;
movementState.jumped = movementState.jumped;
@@ -668,7 +678,7 @@ namespace Game
/*if (input.GetState(GameModeManager.ServerFrame, out var pastInputState2, out var pastActorState2))
{
Actor.Position = pastActorState2.position;
movementState.position = pastActorState2.position;
currentVelocity = pastActorState2.velocity;
SetCameraEulerAngles(pastActorState2.viewAngles, true);
}*/
@@ -964,24 +974,24 @@ namespace Game
}
#endif
private static SlideMoveHit StepSlideMove(PlayerActor actor, ref Vector3 position, ref Vector3 velocity,
private static SlideMoveHit StepSlideMove(PlayerActor actor, PlayerMovementParameters movementParameters, ref Vector3 position, ref Vector3 velocity,
bool onGround)
{
if (velocity.IsZero)
return SlideMoveHit.Nothing;
Vector3 gravityDirection = Gravity.Normalized;
Vector3 gravityDirection = movementParameters.gravity.Normalized;
Vector3 originalPosition = position;
Vector3 originalVelocity = velocity;
SlideMoveHit slideMoveHit = SlideMove(actor, ref position, ref velocity);
SlideMoveHit slideMoveHit = SlideMove(actor, movementParameters, ref position, ref velocity);
if (slideMoveHit == SlideMoveHit.Nothing)
// TODO: step down here
return slideMoveHit;
// hit something, try to step up
float effectiveStepHeight = stepHeight;
float effectiveStepHeight = movementParameters.stepHeight;
if (!onGround)
{
// TODO: implement clipping here
@@ -995,7 +1005,7 @@ namespace Game
if (!slideMoveHit.HasFlag(SlideMoveHit.Step))
return slideMoveHit;
if (airStep < 2)
if (movementParameters.airStep < 2)
{
//effectiveStepHeight = ?
}
@@ -1016,12 +1026,12 @@ namespace Game
position = traceUp.endPosition;
// try moving from step up position
SlideMoveHit slideMoveStepHit = SlideMove(actor, ref position, ref velocity);
SlideMoveHit slideMoveStepHit = SlideMove(actor, movementParameters, ref position, ref velocity);
// step down
Vector3 stepDown = position - stepDelta;
TraceInfo traceDown = TracePlayer(actor, position, stepDown);
if (traceDown.fraction < 1f && -Float3.Dot(gravityDirection, traceDown.hitNormal) < slopeNormal)
if (traceDown.fraction < 1f && -Float3.Dot(gravityDirection, traceDown.hitNormal) < movementParameters.slopeNormal)
{
// can't step down, slide move like normally
Console.Print("no stepping 1, frac: " + traceDown.fraction + ", dot: " +
@@ -1037,7 +1047,7 @@ namespace Game
// add some margin from the ground in order to avoid getting stuck after stepping up
if (traceDown.fraction < 1f)
position.Y += collisionMargin;
position.Y += movementParameters.collisionMargin;
// ??
float d1 = -Float3.Dot(gravityDirection, position);
@@ -1053,7 +1063,7 @@ namespace Game
Vector3 slidePosition2 = slidePosition; //down
Vector3 stepPosition2 = position; //up
// FIXME, negate gravity
// FIXME, negate movementParameters.gravity
slidePosition2.Y = 0f;
stepPosition2.Y = 0f;
@@ -1071,7 +1081,7 @@ namespace Game
return slideMoveHit;
}
private static SlideMoveHit SlideMove(PlayerActor actor, ref Vector3 position, ref Vector3 velocity)
private static SlideMoveHit SlideMove(PlayerActor actor, PlayerMovementParameters movementParameters, ref Vector3 position, ref Vector3 velocity)
{
if (velocity.IsZero)
return SlideMoveHit.Nothing;
@@ -1112,7 +1122,7 @@ namespace Game
timeleft *= 1.0f - fraction;
if (trace.hitNormal.Y > slopeNormal)
if (trace.hitNormal.Y > movementParameters.slopeNormal)
slideMoveHit |= SlideMoveHit.Floor;
else if (Math.Abs(trace.hitNormal.Y) < 0.0001f)
slideMoveHit |= SlideMoveHit.Step;
@@ -1166,7 +1176,7 @@ namespace Game
}
// push off slightly away from the walls to not get stuck
position += normalMargin.Normalized * collisionMargin;
position += normalMargin.Normalized * movementParameters.collisionMargin;
//Console.Print("pushin");
if (plane == hitNormals.Count)
@@ -1203,82 +1213,85 @@ namespace Game
Vector3 inputDirection =
new Float3(inputState.moveRight, 0.0f, inputState.moveForward);
Vector3 moveDirection = rootActor.Transform.TransformDirection(inputDirection);
Vector3 position = rigidBody.Position;
Vector3 velocity = currentVelocity; //rigidBody.LinearVelocity;
Vector3 wishVelocity = !inputDirection.IsZero ? moveDirection.Normalized * MoveSpeed : Vector3.Zero;
Vector3 position = movementState.position;
Vector3 velocity = movementState.currentVelocity; //rigidBody.LinearVelocity;
Vector3 wishVelocity = !inputDirection.IsZero ? moveDirection.Normalized * movementParameters.moveSpeed : Vector3.Zero;
if (position != rigidBody.Position)
Console.Print("PlayerMovement: rigidbody position does not match with movement state position");
// categorize position
bool lastGround = onGround;
Vector3 lastVelocity = velocity;
onGround = true;
movementState.onGround = true;
TraceInfo traceGround = CategorizePosition(position, ref velocity);
bool jumpAction = inputState.jumping;
if (jumped && !jumpAction)
jumped = false; // jump released
else if (jumped && simulationTime - lastJumped >= autoJumpTime)
jumped = false; // jump timeout
if (movementState.jumped && !jumpAction)
movementState.jumped = false; // jump released
else if (movementState.jumped && simulationTime - movementState.lastJumped >= movementParameters.autoJumpTime)
movementState.jumped = false; // jump timeout
// jump
if (onGround && jumpAction && !jumped)
if (movementState.onGround && jumpAction && !movementState.jumped)
if (OnJump(traceGround, ref position, ref velocity))
{
//Console.Print($"{inputState.frame} jumped " + ", predicting: " + predicting + ", vel: " + velocity.Y);
jumped = true;
lastJumped = simulationTime;
numJumps++;
movementState.jumped = true;
movementState.lastJumped = simulationTime;
movementState.numJumps++;
}
if (simulationTime - lastJumped > jumpBoostTime)
numJumps = 0;
if (simulationTime - movementState.lastJumped > movementParameters.jumpBoostTime)
movementState.numJumps = 0;
//if (/*onGround && */lastGround != onGround)
if (onGround)
if (movementState.onGround)
{
// ground friction
ApplyFriction(ref velocity);
ApplyFriction(movementParameters, ref velocity);
// ground acceleration
ApplyAcceleration(ref velocity, wishVelocity.Normalized, wishVelocity.Length, float.MaxValue,
accelerationGround);
movementParameters.accelerationGround);
}
else // air movement
{
ApplyAirAcceleration(ref velocity, wishVelocity);
ApplyAirAcceleration(movementParameters, ref velocity, wishVelocity);
}
StepSlideMove(Actor as PlayerActor, ref position, ref velocity, onGround);
StepSlideMove(Actor as PlayerActor, movementParameters, ref position, ref velocity, movementState.onGround);
TraceInfo traceGround2 = CategorizePosition(position, ref velocity);
movementState.position = position;
rigidBody.Position = position;
currentVelocity = velocity;
movementState.currentVelocity = velocity;
//rigidBody.LinearVelocity = velocity;
const float landingVelocityThreshold = 120f;
const float landingHardVelocityThreshold = 500f;
if (currentVelocity.Y - lastVelocity.Y > landingVelocityThreshold)
if (simulationTime - lastJumped > 0.01)
if (movementState.currentVelocity.Y - lastVelocity.Y > landingVelocityThreshold)
if (simulationTime - movementState.lastJumped > 0.01)
{
bool hardLanding = currentVelocity.Y - lastVelocity.Y > landingHardVelocityThreshold;
OnLanded(currentVelocity - lastVelocity, hardLanding);
lastLanded = simulationTime;
bool hardLanding = movementState.currentVelocity.Y - lastVelocity.Y > landingHardVelocityThreshold;
OnLanded(movementState.currentVelocity - lastVelocity, hardLanding);
movementState.lastLanded = simulationTime;
}
}
private TraceInfo CategorizePosition(Float3 position, ref Vector3 velocity)
{
Vector3 groundDelta = Gravity.Normalized; //Gravity.Normalized * (collisionMargin * 2);
Vector3 groundDelta = movementParameters.gravity.Normalized; //movementParameters.gravity.Normalized * (collisionMargin * 2);
//if (velocity.Y < 0f)
// groundDelta = Gravity.Normalized * velocity.Y * Time.DeltaTime;
// groundDelta = movementParameters.gravity.Normalized * velocity.Y * Time.DeltaTime;
TraceInfo traceGround = TracePlayer(Actor as PlayerActor, position, position + groundDelta);
//Console.PrintDebug(1, true, "startSolid: " + traceGround.startSolid);
if (!traceGround.startSolid && traceGround.fraction < 1f &&
-Float3.Dot(Gravity.Normalized, traceGround.hitNormal) < slopeNormal)
-Float3.Dot(movementParameters.gravity.Normalized, traceGround.hitNormal) < movementParameters.slopeNormal)
{
// clip velocity
@@ -1298,14 +1311,14 @@ namespace Game
}
if (!traceGround.startSolid && (traceGround.fraction >= 1f ||
-Float3.Dot(Gravity.Normalized, traceGround.hitNormal) < slopeNormal))
-Float3.Dot(movementParameters.gravity.Normalized, traceGround.hitNormal) < movementParameters.slopeNormal))
// falling or sliding down a slope
onGround = false;
movementState.onGround = false;
//Console.PrintDebug(1, true, "fall or slide");
else
//if (onGround != !traceGround.startSolid)
// Console.Print("slidefrac: " + traceGround.fraction);
onGround = !traceGround.startSolid;
movementState.onGround = !traceGround.startSolid;
//Console.PrintDebug(1, true, "issolid? :" + traceGround.startSolid);
//if (onGround && !slope)
@@ -1317,18 +1330,18 @@ namespace Game
private bool OnJump(TraceInfo traceGround, ref Vector3 position, ref Vector3 velocity)
{
float jumpVel = jumpVelocity;
if (simulationTime - lastJumped < jumpBoostTime)
jumpVel += jumpBoostVelocity;
float jumpVel = movementParameters.jumpVelocity;
if (simulationTime - movementState.lastJumped < movementParameters.jumpBoostTime)
jumpVel += movementParameters.jumpBoostVelocity;
// Reset velocity from gravity
if (-Float3.Dot(Gravity.Normalized, velocity) < 0 &&
// Reset velocity from movementParameters.gravity
if (-Float3.Dot(movementParameters.gravity.Normalized, velocity) < 0 &&
Float3.Dot(velocity, traceGround.hitNormal) < -0.1)
{
velocity = Float3.ProjectOnPlane(velocity, traceGround.hitNormal);
}
if (jumpAdditive)
if (movementParameters.jumpAdditive)
{
velocity += Float3.Up * jumpVel;
if (velocity.Y < jumpVel)
@@ -1337,30 +1350,30 @@ namespace Game
else
velocity = Float3.Up * jumpVel;
onGround = false;
movementState.onGround = false;
// Allow stairs to eat the first jump to allow easy stair jumps
if (jumpStairBehavior && jumpBoostMaxJumps >= 2 && numJumps == 0 &&
-Float3.Dot(Gravity.Normalized, traceGround.hitNormal) > 0.85)
if (movementParameters.jumpStairBehavior && movementParameters.jumpBoostMaxJumps >= 2 && movementState.numJumps == 0 &&
-Float3.Dot(movementParameters.gravity.Normalized, traceGround.hitNormal) > 0.85)
{
// Try stepping into stairs without vertical velocity
Vector3 stairCheckPosition = position;
Vector3 stairCheckVelocity = velocity.Normalized * (stepHeight / Time.DeltaTime);
Vector3 stairCheckVelocity = velocity.Normalized * (movementParameters.stepHeight / Time.DeltaTime);
stairCheckVelocity.Y = 0f;
SlideMoveHit blocked = StepSlideMove(Actor as PlayerActor, ref stairCheckPosition, ref stairCheckVelocity, true);
SlideMoveHit blocked = StepSlideMove(Actor as PlayerActor, movementParameters, ref stairCheckPosition, ref stairCheckVelocity, true);
float movedUp = stairCheckPosition.Y - position.Y;
if (movedUp > 0 && blocked.HasFlag(SlideMoveHit.Step))
{
velocity.Y = 0f;
onGround = true;
movementState.onGround = true;
}
}
if (!predicting)
// Avoid overlapping with recent landing sound
if (simulationTime - lastLanded > 0.3)
if (simulationTime - movementState.lastLanded > 0.3)
PlayJumpLandSound(false, false);
return true;
@@ -1375,7 +1388,7 @@ namespace Game
private void PlayJumpLandSound(bool landing, bool hardLanding)
{
if (!landing)
lastLanded = -1; // Reset so double jumps have double sounds
movementState.lastLanded = -1; // Reset so double jumps have double sounds
float volume1 = 0.8f;
float volume2 = volume1;
@@ -1389,16 +1402,18 @@ namespace Game
AudioManager.PlaySound("jumpland", Actor, 0, AudioFlags.None, rootActor.Position, volume1, pitchRange);
if (landing)
{
AudioManager.PlaySoundDelayed(secondStepDelayRange, "jumpland", Actor, 0, rootActor.Position, volume2,
pitchRange);
}
}
private static void ApplyFriction(ref Vector3 velocity)
private static void ApplyFriction(PlayerMovementParameters movementParameters, ref Vector3 velocity)
{
float currentSpeed = velocity.Length;
float control = currentSpeed < stopspeed ? stopspeed : currentSpeed;
float drop = control * friction * Time.DeltaTime;
float control = currentSpeed < movementParameters.stopspeed ? movementParameters.stopspeed : currentSpeed;
float drop = control * movementParameters.friction * Time.DeltaTime;
float newspeed = currentSpeed - drop;
if (newspeed < 0)
@@ -1410,51 +1425,52 @@ namespace Game
velocity *= newspeed / currentSpeed;
}
private static void ApplyAirAcceleration(ref Vector3 velocity, Vector3 wishVelocity)
private static void ApplyAirAcceleration(PlayerMovementParameters movementParameters, ref Vector3 velocity, Vector3 wishVelocity)
{
float wishspeed = wishVelocity.Length;
if (wishspeed > maxAirSpeed)
wishspeed = maxAirSpeed;
if (wishspeed > movementParameters.maxAirSpeed)
wishspeed = movementParameters.maxAirSpeed;
Vector3 wishDir = wishVelocity.Normalized;
float wishspeedAirControl = wishspeed;
if (airAcceleration != 0)
if (movementParameters.airAcceleration != 0)
{
// Q2+ air acceleration
float accel = airAcceleration;
float accel = movementParameters.airAcceleration;
if (Float3.Dot(velocity, wishDir) < 0)
accel = airStopAcceleration;
accel = movementParameters.airStopAcceleration;
if (airStrafeAcceleration != 0 && Mathf.Abs(wishVelocity.X) > 0 && wishVelocity.Y == 0)
if (movementParameters.airStrafeAcceleration != 0 && Mathf.Abs(wishVelocity.X) > 0 && wishVelocity.Y == 0)
{
// only strafe movement
if (wishspeed > maxAirStrafeSpeed)
wishspeed = maxAirStrafeSpeed;
if (wishspeed > movementParameters.maxAirStrafeSpeed)
wishspeed = movementParameters.maxAirStrafeSpeed;
accel = airStrafeAcceleration;
accel = movementParameters.airStrafeAcceleration;
}
ApplyAcceleration(ref velocity, wishDir, wishspeed, float.MaxValue, accel);
}
// QW air acceleration
if (strafeAcceleration != 0f)
ApplyAcceleration(ref velocity, wishDir, wishspeed, maxAirStrafeSpeed,
strafeAcceleration);
if (movementParameters.strafeAcceleration != 0f)
{
ApplyAcceleration(ref velocity, wishDir, wishspeed, movementParameters.maxAirStrafeSpeed,
movementParameters.strafeAcceleration);
}
// air control while holding forward/back buttons
//if (airControl != 0 && moveDirection.X == 0 && Mathf.Abs(moveDirection.Y) > 0)
// PM_Aircontrol(wishdir, wishspeedAirControl);
// apply gravity
velocity += Gravity * Time.DeltaTime;
// apply movementParameters.gravity
velocity += movementParameters.gravity * Time.DeltaTime;
//Console.Print(Time.DeltaTime.ToString());
}
private static void ApplyAcceleration(ref Vector3 velocity, Vector3 wishDir, float wishspeed,
float maxWishspeed,
float acceleration)
float maxWishspeed, float acceleration)
{
float wishspeedOrig = wishspeed;
if (wishspeed > maxWishspeed)
@@ -1481,4 +1497,4 @@ namespace Game
Other = 4
}
}
}
}