@@ -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 flo at collisionMargin = 0.031f * 1.666f * 1.85f ;
private const float slopeNormal = 0.7f ;
private PlayerMovementParameters movementParameters = new PlayerMovementParameters ( ) ;
public PlayerMovementSt ate 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 jumpe d;
public bool OnGround = > movementState . onGroun d;
//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.P osition = input.GetCurrentActorState().position;
/*movementState.p osition = input.GetCurrentActorState().position;
currentVelocity = input.GetCurrentActorState().velocity; f
SetCameraEulerAngles(input.GetCurrentActorState().viewAngles);*/
Actor . P osition = input . GetCurrentInputState ( ) . verificationPosition ;
movementState . p osition = 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.P osition = actorState.position;
movementState.p osition = actorState.position;
currentVelocity = actorState.velocity;
viewYaw = actorState.viewYaw;
viewPitch = actorState.viewPitch;
@@ -291,20 +301,20 @@ namespace Game
input . RecordCurrentActorState ( new PlayerActorState
{
position = Actor . P osition,
velocity = currentVelocity ,
position = movementState . p osition,
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.P osition,
position = movementState.p osition,
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 . P osition - inputState . verificationPosition ) . Length ;
float positionDelta = ( movementState . p osition - 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.P osition = inputState.verificationPosition;
movementState.p osition = inputState.verificationPosition;
currentVelocity = inputState.verificationVelocity;
rootActor.Orientation = inputState.verificationOrientation;
}*/
@@ -417,14 +426,14 @@ namespace Game
if ( currentFrame = = GameModeManager . ServerFrame )
{
Actor . P osition = pastActorState . position ;
movementState . p osition = pastActorState . position ;
currentVelocity = pastActorState . velocity ;
lastJumped = pastActorState . lastJumpTime ;
numJumps = pastActorState . numJumps ;
jumped = pastActorState . jumped ;
SetCameraEulerAngles ( pastActorState . viewAngles , true ) ;
if ( Actor . P osition. Length < 0.1 )
if ( movementState . p osition. Length < 0.1 )
jumped = jumped ;
continue ;
@@ -445,7 +454,7 @@ namespace Game
break ;
/*if ((Actor.P osition - pastActorState.position).Length > 0.001)
/*if ((movementState.p osition - 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 . P osition. Length < 0.1 )
jumped = jumped ;
if ( movementState . p osition. 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 . P osition;
var oldVel = currentVelocity ;
var oldPos = movementState . p osition;
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 . P osition = pastActorState . position ;
currentVelocity = pastActorState . velocity ;
lastJumped = pastActorState . lastJumpTime ;
numJumps = pastActorState . numJumps ;
jumped = pastActorState . jumped ;
movementState . p osition = 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 . P osition. Length < 0.1 )
jumped = jumped ;
if ( movementState . p osition. 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.P osition - pastActorState.position).Length > 0.001)
/*if ((movementState.p osition - 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 . P osition - oldPos ) . Length > 0.001 )
if ( ( movementState . p osition - 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.P osition - oldPos).Length > 0.001)
/*if ((movementState.p osition - 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 . P osition. Length < 0.1 )
jumped = jumped ;
if ( movementState . p osition. 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.P osition = pastActorState2.position;
movementState.p osition = 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 . P osition,
velocity = currentVelocity ,
position = movementState . p osition,
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 . P osition. Length < 0.1 )
jumped = jumped ;
if ( movementState . p osition. 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.P osition = pastActorState2.position;
movementState.p osition = 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 = G ravity. Normalized ;
Vector3 gravityDirection = movementParameters . g ravity. 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 . P osition;
Vector3 velocity = currentVelocity ; //rigidBody.LinearVelocity;
Vector3 wishVelocity = ! inputDirection . IsZero ? moveDirection . Normalized * M oveSpeed : Vector3 . Zero ;
Vector3 position = movementState . p osition;
Vector3 velocity = movementState . currentVelocity; //rigidBody.LinearVelocity;
Vector3 wishVelocity = ! inputDirection . IsZero ? moveDirection . Normalized * movementParameters . m oveSpeed : 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 = G ravity. Normalized ; //G ravity.Normalized * (collisionMargin * 2);
Vector3 groundDelta = movementParameters . g ravity. Normalized ; //movementParameters.g ravity.Normalized * (collisionMargin * 2);
//if (velocity.Y < 0f)
// groundDelta = G ravity.Normalized * velocity.Y * Time.DeltaTime;
// groundDelta = movementParameters.g ravity.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 ( G ravity. Normalized , traceGround . hitNormal ) < slopeNormal )
- Float3 . Dot ( movementParameters . g ravity. Normalized , traceGround . hitNormal ) < movementParameters . slopeNormal )
{
// clip velocity
@@ -1298,14 +1311,14 @@ namespace Game
}
if ( ! traceGround . startSolid & & ( traceGround . fraction > = 1f | |
- Float3 . Dot ( G ravity. Normalized , traceGround . hitNormal ) < slopeNormal ) )
- Float3 . Dot ( movementParameters . g ravity. 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 ( G ravity. Normalized , velocity ) < 0 & &
// Reset velocity from movementParameters. gravity
if ( - Float3 . Dot ( movementParameters . g ravity. 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 ( G ravity. Normalized , traceGround . hitNormal ) > 0.85 )
if ( movementParameters . jumpStairBehavior & & movementParameters . jumpBoostMaxJumps > = 2 & & movementState . numJumps = = 0 & &
- Float3 . Dot ( movementParameters . g ravity. 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 ,
strafe Acceleration ) ;
if ( movementParameters . strafeAcceleration ! = 0f )
{
Apply Acceleration( 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 + = G ravity * Time . DeltaTime ;
// apply movementParameters. gravity
velocity + = movementParameters . g ravity * 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
}
}
}
}