85 lines
3.0 KiB
C#
85 lines
3.0 KiB
C#
using System.Collections.Generic;
|
|
using Game.Features.Players.Contracts;
|
|
using Game.Features.Players.Domain;
|
|
using Game.Features.Players.Domain.Movement;
|
|
using Game.Godot;
|
|
using Game.Godot.Extensions;
|
|
using Game.Godot.Mappings;
|
|
using Godot;
|
|
|
|
namespace Game.Features.Players.Godot;
|
|
|
|
public partial class PlayerController : Node3D, IMovementModeSwitcher
|
|
{
|
|
[Export] public CharacterBody3D Body;
|
|
[Export] public CollisionShape3D Collision;
|
|
[Export] public Camera3D Camera;
|
|
|
|
[Export] public float MoveSpeed = 4.0f;
|
|
[Export] public float JumpVelocity = 4.5f;
|
|
[Export] public float NoclipFlySpeed = 8.0f;
|
|
[Export] public float MouseSensitivity = 0.003f;
|
|
[Export] public float MaxLookAngleDegrees = 89.0f;
|
|
|
|
private Dictionary<MovementMode, IMovementStrategy> _movementStrategies;
|
|
private IMovementStrategy _currentMovementStrategy;
|
|
private PlayerLook _look;
|
|
|
|
public MovementMode ActiveMovementMode { get; private set; } = MovementMode.Ground;
|
|
|
|
public void SetMovementMode(MovementMode movementMode)
|
|
{
|
|
ActiveMovementMode = movementMode;
|
|
_currentMovementStrategy = _movementStrategies[movementMode];
|
|
Collision.Disabled = movementMode == MovementMode.Noclip;
|
|
}
|
|
|
|
public override void _Ready()
|
|
{
|
|
this.AssertRequiredExports();
|
|
|
|
_look = new PlayerLook(MouseSensitivity, MaxLookAngleDegrees);
|
|
|
|
float gravity = (float)ProjectSettings.GetSetting(ProjectSetting.Gravity.SettingPath());
|
|
_movementStrategies = new Dictionary<MovementMode, IMovementStrategy>
|
|
{
|
|
[MovementMode.Ground] = new GroundMovement(MoveSpeed, JumpVelocity, gravity),
|
|
[MovementMode.Noclip] = new NoclipMovement(NoclipFlySpeed)
|
|
};
|
|
_currentMovementStrategy = _movementStrategies[ActiveMovementMode];
|
|
}
|
|
|
|
public override void _UnhandledInput(InputEvent @event)
|
|
{
|
|
if (@event is not InputEventMouseMotion mouseMotion || !MouseCapture.IsCaptured) return;
|
|
|
|
Body.RotateY(_look.CalculateYawDelta(mouseMotion.Relative.X));
|
|
_look.UpdatePitch(mouseMotion.Relative.Y);
|
|
Camera.Rotation = new Vector3(_look.Pitch, 0f, 0f);
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
Vector2 inputDirection = Input.GetVector(
|
|
InputAction.MoveLeft.ActionName(),
|
|
InputAction.MoveRight.ActionName(),
|
|
InputAction.MoveForward.ActionName(),
|
|
InputAction.MoveBack.ActionName()
|
|
);
|
|
|
|
MovementInput input = new(
|
|
Right: Body.Transform.Basis.X,
|
|
Back: Body.Transform.Basis.Z,
|
|
Direction: inputDirection,
|
|
IsOnFloor: Body.IsOnFloor(),
|
|
JumpPressed: Input.IsActionJustPressed(InputAction.Jump.ActionName()),
|
|
AscendPressed: Input.IsActionPressed(InputAction.Jump.ActionName()),
|
|
DescendPressed: Input.IsActionPressed(InputAction.MoveDown.ActionName()),
|
|
Delta: (float)delta
|
|
);
|
|
|
|
Body.Velocity = _currentMovementStrategy.CalculateVelocity(Body.Velocity, input);
|
|
Body.MoveAndSlide();
|
|
}
|
|
}
|