refactor playermovement
This commit is contained in:
@@ -134,6 +134,7 @@ namespace Game
|
||||
public void SetPosition(Float3 newPosition)
|
||||
{
|
||||
Position = newPosition;
|
||||
playerMovement.movementState.position = newPosition;
|
||||
}
|
||||
|
||||
public void SetRotation(Float3 eulerAngles)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user