304 lines
9.8 KiB
C#
304 lines
9.8 KiB
C#
using System.Collections.Generic;
|
|
using FlaxEngine;
|
|
using Cabrito;
|
|
using System.Diagnostics;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Game
|
|
{
|
|
public class PlayerMovement : Script
|
|
{
|
|
[Limit(0, 9000), Tooltip("Base Movement speed")]
|
|
public float MoveSpeed { get; set; } = 320;
|
|
|
|
private float viewPitch;
|
|
private float viewYaw;
|
|
private float viewRoll;
|
|
|
|
private InputEvent onExit = new InputEvent("Exit");
|
|
|
|
Actor rootActor;
|
|
public override void OnAwake()
|
|
{
|
|
base.OnAwake();
|
|
|
|
onExit.Triggered += () =>
|
|
{
|
|
if (Console.IsSafeToQuit)
|
|
Engine.RequestExit();
|
|
};
|
|
|
|
rootActor = Actor.GetChild(0);
|
|
}
|
|
|
|
public override void OnDestroy()
|
|
{
|
|
base.OnDestroy();
|
|
|
|
onExit.Dispose();
|
|
}
|
|
|
|
public override void OnStart()
|
|
{
|
|
var initialEulerAngles = Actor.Orientation.EulerAngles;
|
|
viewPitch = initialEulerAngles.X;
|
|
viewYaw = initialEulerAngles.Y;
|
|
viewRoll = initialEulerAngles.Z;
|
|
}
|
|
|
|
private RayCastHit[] TracePlayer(Vector3 start, Vector3 end)
|
|
{
|
|
bool collided;
|
|
RayCastHit[] hitInfos;
|
|
|
|
var capsuleCollider = Actor.GetChild<CapsuleCollider>();
|
|
var boxCollider = Actor.GetChild<BoxCollider>();
|
|
PhysicsColliderActor collider = null;
|
|
Vector3 delta = end - start;
|
|
|
|
if (capsuleCollider && capsuleCollider.IsActive)
|
|
{
|
|
collider = capsuleCollider;
|
|
|
|
//start.Y -= capsuleCollider.Height / 2;
|
|
//start.Y -= capsuleCollider.Radius / 2;
|
|
|
|
/*collided = Physics.BoxCastAll(start,
|
|
new Vector3(capsuleCollider.Radius,
|
|
(capsuleCollider.Height + capsuleCollider.Radius) / 2,
|
|
capsuleCollider.Radius),
|
|
delta.Normalized, out hitInfos, Quaternion.Identity, delta.Length, uint.MaxValue,
|
|
false);*/
|
|
|
|
collided = Physics.CapsuleCastAll(start,
|
|
capsuleCollider.Radius, capsuleCollider.Height,
|
|
delta.Normalized, out hitInfos, capsuleCollider.Orientation, delta.Length, uint.MaxValue,
|
|
false);
|
|
}
|
|
else if (boxCollider && boxCollider.IsActive)
|
|
{
|
|
collider = boxCollider;
|
|
|
|
//start.Y += boxCollider.Size.Y / 2;
|
|
|
|
collided = Physics.BoxCastAll(start,
|
|
boxCollider.OrientedBox.Extents,
|
|
delta.Normalized, out hitInfos, boxCollider.Orientation, delta.Length, uint.MaxValue,
|
|
false);
|
|
}
|
|
else
|
|
return new RayCastHit[0];
|
|
|
|
if (collided)
|
|
{
|
|
List<RayCastHit> hitInfosFiltered = new List<RayCastHit>();
|
|
foreach (var hitInfo in hitInfos)
|
|
{
|
|
if (hitInfo.Collider == collider)
|
|
continue;
|
|
|
|
hitInfosFiltered.Add(hitInfo);
|
|
}
|
|
|
|
hitInfos = hitInfosFiltered.ToArray();
|
|
}
|
|
|
|
return hitInfos;
|
|
}
|
|
|
|
private bool SlideMove(Vector3 start, ref Vector3 velocity)
|
|
{
|
|
// PM_SlideMove
|
|
/*
|
|
|
|
endpos = pos + velocity
|
|
|
|
for i=0, i<4, i++
|
|
trace(pos, endpos)
|
|
|
|
if trace.dist >= 1
|
|
break;
|
|
|
|
blocked =
|
|
blocked_floor => trace.plane.normal[2] >= MIN_STEP_NORMAL
|
|
blocked_step => trace.plane.normal[2] == 0
|
|
blocked_other => .
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Vector3 startPos = start;
|
|
Vector3 endPos = startPos + (velocity * Time.DeltaTime);
|
|
Vector3 delta = endPos - startPos;
|
|
bool blocked = false;
|
|
|
|
|
|
RayCastHit[] hitInfos = TracePlayer(startPos, endPos);
|
|
bool collided = hitInfos.Length > 0;
|
|
|
|
float distance = 1.0f;
|
|
|
|
Vector3 normal = Vector3.Zero;
|
|
Vector3 point;
|
|
if (collided)
|
|
{
|
|
collided = false;
|
|
foreach (var hitInfo in hitInfos)
|
|
{
|
|
//if (hitInfo.Distance < minDistanceFromFloor)
|
|
// continue;
|
|
|
|
float fraction = hitInfo.Distance / delta.Length;
|
|
|
|
collided = true;
|
|
if (fraction <= distance)
|
|
{
|
|
normal = hitInfo.Normal;
|
|
point = hitInfo.Point;
|
|
distance = fraction;
|
|
}
|
|
|
|
break;
|
|
|
|
//Console.Print("collided " + hitInfo.Distance.ToString());
|
|
//break;
|
|
}
|
|
}
|
|
if (collided)
|
|
velocity = Vector3.ProjectOnPlane(velocity, normal);
|
|
|
|
blocked = collided;
|
|
|
|
return blocked;
|
|
}
|
|
|
|
//Vector3 wishVelocity = Vector3.Zero;
|
|
Vector3 gravityVelocity = Vector3.Zero;
|
|
Vector3 currentVelocity = Vector3.Zero;
|
|
private bool onGround = false;
|
|
|
|
private const float friction = 4f;
|
|
private const float stopspeed = 100f;
|
|
private const float accelerationGround = 10f;
|
|
private const float jumpVelocity = 270f;
|
|
private bool jumped = false;
|
|
|
|
public override void OnFixedUpdate()
|
|
{
|
|
var rigidBody = Actor.As<RigidBody>();
|
|
var rootTrans = rootActor.Transform;
|
|
|
|
var inputDirection = new Vector3(InputManager.GetAxis("Horizontal"), 0.0f, InputManager.GetAxis("Vertical"));
|
|
var moveDirection = rootTrans.TransformDirection(inputDirection);
|
|
|
|
Vector3 wishVelocity = Vector3.Zero;
|
|
if (!Console.IsOpen && !inputDirection.IsZero)
|
|
{
|
|
//move = moveDirection.Normalized * MoveSpeed * Time.DeltaTime / (1.0f/Time.PhysicsFPS);
|
|
inputDirection = moveDirection.Normalized * MoveSpeed;
|
|
wishVelocity = inputDirection;
|
|
}
|
|
|
|
// onGround checks
|
|
RayCastHit[] hitInfosGround = TracePlayer(rigidBody.Position, rigidBody.Position + (Vector3.Down * 1f));
|
|
onGround = false;
|
|
foreach (var hitInfo in hitInfosGround)
|
|
{
|
|
var dot = Vector3.Dot(Vector3.Down, hitInfo.Normal);
|
|
if (dot < -0.7) //~45deg
|
|
{
|
|
onGround = true;
|
|
Vector3 newPos = rigidBody.Position;
|
|
newPos += Vector3.Down * (hitInfo.Distance - 0.01f);
|
|
//newPos.Y = hitInfo.Point.Y + 0.0001f;
|
|
//rigidBody.Position = newPos;
|
|
//currentVelocity.Y = 0.0f;
|
|
}
|
|
}
|
|
|
|
// jump
|
|
if (onGround)
|
|
{
|
|
if (!jumped && InputManager.GetAction("Jump"))
|
|
{
|
|
//jumped = true;
|
|
|
|
currentVelocity += Vector3.Up * jumpVelocity;
|
|
}
|
|
else if (jumped) // jump released
|
|
jumped = false;
|
|
}
|
|
|
|
|
|
// ground friction
|
|
if (onGround)
|
|
{
|
|
float currentSpeed = currentVelocity.Length;
|
|
|
|
float control = currentSpeed < stopspeed ? stopspeed : currentSpeed;
|
|
var drop = control * friction * Time.DeltaTime;
|
|
|
|
float newspeed = currentSpeed - drop;
|
|
if (newspeed < 0)
|
|
newspeed = 0;
|
|
|
|
if (currentSpeed < 0.0001f)
|
|
currentVelocity *= 0;
|
|
else
|
|
currentVelocity *= newspeed / currentSpeed;
|
|
}
|
|
|
|
// ground acceleration
|
|
{
|
|
float currentSpeed = Vector3.Dot(currentVelocity, wishVelocity.Normalized);
|
|
float addSpeed = wishVelocity.Length - currentSpeed;
|
|
|
|
if (addSpeed > 0)
|
|
{
|
|
float accelSpeed = 12f * wishVelocity.Length * Time.DeltaTime;
|
|
if (accelSpeed > addSpeed)
|
|
accelSpeed = addSpeed;
|
|
|
|
currentVelocity += accelSpeed * wishVelocity.Normalized;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!onGround)
|
|
currentVelocity += Physics.Gravity * Time.DeltaTime;
|
|
|
|
bool blocked2 = SlideMove(rigidBody.Position, ref currentVelocity);
|
|
if (currentVelocity.Length > 0.0f)
|
|
rigidBody.Position += currentVelocity * Time.DeltaTime;
|
|
}
|
|
|
|
public override void OnUpdate()
|
|
{
|
|
float xAxis = InputManager.GetAxis("Mouse X");
|
|
float yAxis = InputManager.GetAxis("Mouse Y");
|
|
if (xAxis != 0.0f || yAxis != 0.0f)
|
|
{
|
|
var camera = rootActor.GetChild<Camera>();
|
|
var camTrans = camera.Transform;
|
|
var rootTrans = rootActor.Transform;
|
|
|
|
viewPitch += yAxis;
|
|
viewYaw += xAxis;
|
|
|
|
viewPitch = Mathf.Clamp(viewPitch, -90.0f, 90.0f);
|
|
|
|
camTrans.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
|
|
rootTrans.Orientation = Quaternion.Euler(0, viewYaw, 0);
|
|
|
|
camera.Transform = camTrans;
|
|
rootActor.Transform = rootTrans;
|
|
}
|
|
}
|
|
}
|
|
}
|