parent
3ac59f082e
commit
f4708975d7
1 changed files with 0 additions and 158 deletions
@ -1,158 +0,0 @@ |
|||||||
using Godot; |
|
||||||
using System; |
|
||||||
|
|
||||||
public partial class Player : CharacterBody3D |
|
||||||
{ |
|
||||||
public float MouseSensitivity { get; set; } = 0.2F; |
|
||||||
|
|
||||||
/// <summary> Time after pressing the jump button a jump may occur late. </summary> |
|
||||||
public TimeSpan JumpEarlyTime { get; set; } = TimeSpan.FromSeconds(0.2); |
|
||||||
|
|
||||||
/// <summary> Time after leaving a jumpable surface when a jump may still occur. </summary> |
|
||||||
public TimeSpan JumpCoyoteTime { get; set; } = TimeSpan.FromSeconds(0.2); |
|
||||||
|
|
||||||
public Vector3 Gravity { get; set; } = new(0, -12.0F, 0); |
|
||||||
public float JumpVelocity { get; set; } = 5.0F; |
|
||||||
public float MoveAccel { get; set; } = 6.0F; |
|
||||||
public float MaxMoveSpeed { get; set; } = 4.0F; |
|
||||||
public float FrictionFloor { get; set; } = 12.0F; |
|
||||||
public float FrictionAir { get; set; } = 2.0F; |
|
||||||
|
|
||||||
public enum MovementMode { Default, Flying, NoClip } |
|
||||||
public MovementMode Movement { get; set; } = MovementMode.Default; |
|
||||||
|
|
||||||
|
|
||||||
private Node3D _neckBone = null!; |
|
||||||
private Node3D _headBone = null!; |
|
||||||
private Camera3D _camera = null!; |
|
||||||
|
|
||||||
private DateTime? _jumpPressed = null; |
|
||||||
private DateTime? _lastOnFloor = null; |
|
||||||
|
|
||||||
public bool IsSprinting { get; private set; } |
|
||||||
|
|
||||||
|
|
||||||
public override void _Ready() |
|
||||||
{ |
|
||||||
_neckBone = GetNode<Node3D>("Neck"); |
|
||||||
_headBone = GetNode<Node3D>("Neck/Head"); |
|
||||||
_camera = GetNode<Camera3D>("Neck/Head/Camera"); |
|
||||||
} |
|
||||||
|
|
||||||
public override void _Input(InputEvent ev) |
|
||||||
{ |
|
||||||
// Inputs that are valid when the game is focused. |
|
||||||
// =============================================== |
|
||||||
|
|
||||||
if (ev.IsAction("move_sprint")) |
|
||||||
{ |
|
||||||
IsSprinting = ev.IsPressed(); |
|
||||||
GetViewport().SetInputAsHandled(); |
|
||||||
} |
|
||||||
|
|
||||||
if (ev.IsActionPressed("move_jump")) |
|
||||||
{ |
|
||||||
_jumpPressed = DateTime.Now; |
|
||||||
GetViewport().SetInputAsHandled(); |
|
||||||
} |
|
||||||
|
|
||||||
// Cycle movement mode between default, flying and flying+noclip. |
|
||||||
if (ev.IsActionPressed("cycle_movement_mode")) |
|
||||||
{ |
|
||||||
if (++Movement > MovementMode.NoClip) |
|
||||||
Movement = MovementMode.Default; |
|
||||||
GetViewport().SetInputAsHandled(); |
|
||||||
} |
|
||||||
|
|
||||||
// Inputs that are valid only when the mouse is captured. |
|
||||||
// ====================================================== |
|
||||||
if (Input.MouseMode == Input.MouseModeEnum.Captured) { |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override void _UnhandledInput(InputEvent ev) |
|
||||||
{ |
|
||||||
var isMouseCaptured = Input.MouseMode == Input.MouseModeEnum.Captured; |
|
||||||
// When pressing escape and mouse is currently captured, release it. |
|
||||||
if (ev.IsActionPressed("ui_cancel") && isMouseCaptured) |
|
||||||
Input.MouseMode = Input.MouseModeEnum.Visible; |
|
||||||
|
|
||||||
// Grab the mouse when pressing the primary mouse button. |
|
||||||
// TODO: Make "primary mouse button" configurable. |
|
||||||
if (ev is InputEventMouseButton button && button.ButtonIndex == MouseButton.Left) |
|
||||||
Input.MouseMode = Input.MouseModeEnum.Captured; |
|
||||||
|
|
||||||
if (ev is InputEventMouseMotion motion && isMouseCaptured) |
|
||||||
{ |
|
||||||
_neckBone.RotateX(Mathf.DegToRad(motion.Relative.Y * -MouseSensitivity)); |
|
||||||
_headBone.RotateY(Mathf.DegToRad(motion.Relative.X * -MouseSensitivity)); |
|
||||||
|
|
||||||
var rotation = _neckBone.RotationDegrees; |
|
||||||
rotation.X = Mathf.Clamp(rotation.X, -80, 80); |
|
||||||
_neckBone.RotationDegrees = rotation; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override void _PhysicsProcess(double delta) |
|
||||||
{ |
|
||||||
var movementVector = new Vector3( |
|
||||||
Input.GetActionStrength("move_strafe_right") - Input.GetActionStrength("move_strafe_left"), |
|
||||||
Input.GetActionStrength("move_upward") - Input.GetActionStrength("move_downward"), |
|
||||||
Input.GetActionStrength("move_backward") - Input.GetActionStrength("move_forward")); |
|
||||||
|
|
||||||
if (Movement == MovementMode.Default) |
|
||||||
{ |
|
||||||
Velocity += Gravity * (float)delta; |
|
||||||
|
|
||||||
var dir = Vector3.Zero; |
|
||||||
var camTransform = _camera.GlobalTransform; |
|
||||||
dir += camTransform.Basis.Z.Normalized() * movementVector.Z; |
|
||||||
dir += camTransform.Basis.X.Normalized() * movementVector.X; |
|
||||||
dir.Y = 0; |
|
||||||
dir = dir.Normalized() * movementVector.Length(); |
|
||||||
|
|
||||||
var hvel = Velocity; |
|
||||||
hvel.Y = 0; |
|
||||||
|
|
||||||
var target = dir * MaxMoveSpeed; |
|
||||||
var friction = IsOnFloor() ? FrictionFloor : FrictionAir; |
|
||||||
var accel = (dir.Dot(hvel) > 0) ? MoveAccel : friction; |
|
||||||
|
|
||||||
if (IsSprinting) { target *= 5; accel *= 5; } |
|
||||||
hvel = hvel.Lerp(target, accel * (float)delta); |
|
||||||
|
|
||||||
Velocity = new(hvel.X, Velocity.Y, hvel.Z); |
|
||||||
|
|
||||||
// Sometimes, when pushing into a wall, jumping wasn't working. |
|
||||||
// Possibly due to `IsOnFloor` returning `false` for some reason. |
|
||||||
// The `JumpEarlyTime` feature seems to avoid this issue, thankfully. |
|
||||||
|
|
||||||
if (IsOnFloor()) _lastOnFloor = DateTime.Now; |
|
||||||
|
|
||||||
if (((DateTime.Now - _jumpPressed) <= JumpEarlyTime) |
|
||||||
&& ((DateTime.Now - _lastOnFloor) <= JumpCoyoteTime)) |
|
||||||
{ |
|
||||||
Velocity = new(Velocity.X, JumpVelocity, Velocity.Z); |
|
||||||
_jumpPressed = null; |
|
||||||
_lastOnFloor = null; |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Velocity *= 1 - FrictionAir * (float)delta; |
|
||||||
|
|
||||||
var cameraRot = _headBone.GlobalTransform.Basis.GetRotationQuaternion(); |
|
||||||
var dir = cameraRot * movementVector; |
|
||||||
var target = dir * MaxMoveSpeed; |
|
||||||
var accel = (dir.Dot(Velocity) > 0) ? MoveAccel : FrictionAir; |
|
||||||
target *= 4; accel *= 4; |
|
||||||
|
|
||||||
if (IsSprinting) { target *= 5; accel *= 5; } |
|
||||||
Velocity = Velocity.Lerp(target, accel * (float)delta); |
|
||||||
} |
|
||||||
|
|
||||||
if (Movement == MovementMode.NoClip) |
|
||||||
Translate(Velocity * (float)delta); |
|
||||||
else MoveAndSlide(); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue