diff --git a/.gitignore b/.gitignore index a663d15..4c18570 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ export_presets.cfg # Mono-specific ignores .mono/ data_*/ +/.vs diff --git a/Scripts/PlayerMovement.cs b/Scripts/PlayerMovement.cs index 675e62b..a190198 100644 --- a/Scripts/PlayerMovement.cs +++ b/Scripts/PlayerMovement.cs @@ -36,8 +36,10 @@ public partial class PlayerMovement : CharacterBody3D [Export] public float accelerationRate {private set; get;} = 1.0f; [Export] public float lerpSpeed {private set; get;} = 10.0f; // Gradually changes a value. (Adding smoothing to values) [Export] private float _airLerpSpeed = 3.0f; + [Export] private bool _enableJoyStick = true; + [Export] private bool _invertLook = false; - [ExportCategory("Jumping")] + [ExportCategory("Jumping")] [Export] private float _jumpVelocity = 4.5f; [Export] private float _coyoteTime = 0.5f; [Export] private int _jumps = 1; @@ -55,7 +57,13 @@ public partial class PlayerMovement : CharacterBody3D private float _rotationX = 0f; private float _rotationZ = 0f; - [ExportSubgroup("Z Tilt")] + // joystick inputs + private float _currentRotationY = 0.0f; // Store the current Y-axis rotation (horizontal) + private float _deadzoneThreshold = 0.1f; // Define a joystick deadzone threshold + private bool _isUsingJoystick = false; + private Vector2 _joyDir = Vector2.Zero; + + [ExportSubgroup("Z Tilt")] [Export] private float _zRotationLerp = 7f; [Export] private float _zClamp = 5f; @@ -123,9 +131,12 @@ public partial class PlayerMovement : CharacterBody3D [ExportSubgroup("Sensitivity")] [Export(PropertyHint.Range, "0, 1,")] public float mouseSensitivityX = 0.4f; [Export(PropertyHint.Range, "0, 1,")] public float mouseSensitivityY = 0.4f; + [Export(PropertyHint.Range, "0, 15,")] public int joystickSensitivityX = 5; + [Export(PropertyHint.Range, "0, 15,")] public int joystickSensitivityY = 5; + [Export(PropertyHint.Range, "0, 20,")] public int smoothingSpeed = 5; - [ExportSubgroup("Free Looking")] + [ExportSubgroup("Free Looking")] [Export] private float _freeLookTilt = 0.3f; [ExportSubgroup("Field of View")] @@ -216,7 +227,41 @@ public override void _Process(double delta) { HandleZRotation((float)delta); - if (Input.IsKeyPressed(Key.R) && _resetPosition != null) + if (_enableJoyStick) + { + float joystickX = Input.GetAxis("look_left", "look_right"); + float joystickY = Input.GetAxis("look_up", "look_down"); + + if (Mathf.Abs(joystickX) > _deadzoneThreshold || Mathf.Abs(joystickY) > _deadzoneThreshold) + { + Vector2 joyDir = new Vector2(joystickX, joystickY); + _joyDir = joyDir; + _isUsingJoystick = true; + switch (camState) + { + case CameraState.Freelooking: + if (FSM.CurrentState is PlayerSlide) + { + RotatePlayer(_joyDir.X, _joyDir.Y, true, delta); + } + else + { + FreeLookRotation(_joyDir.X, -120f, 120f); + } + break; + + case CameraState.Normal: + RotatePlayer(_joyDir.X, _joyDir.Y, true, delta); + break; + } + } + else + { + _isUsingJoystick = false; + } + } + + if (Input.IsKeyPressed(Key.R) && _resetPosition != null) GlobalPosition = _resetPosition.GlobalPosition; PhysicsInterpolation(); @@ -226,18 +271,34 @@ public override void _Process(double delta) HandleLabels(); } - private void RotatePlayer(float mouseX, float mouseY) - { - RotateY(Mathf.DegToRad(-mouseX * mouseSensitivityX)); + private void RotatePlayer(float inputX, float inputY, bool isJoystickInput = false, double delta = 0) + { + float sensitivityX = isJoystickInput ? joystickSensitivityX : mouseSensitivityX; + float sensitivityY = isJoystickInput ? joystickSensitivityY : mouseSensitivityY; - _rotationX += Mathf.DegToRad(-mouseY * mouseSensitivityY); - _rotationX = Mathf.Clamp(_rotationX, Mathf.DegToRad(-89f), Mathf.DegToRad(89f)); + if (_invertLook) + inputY = -inputY; - _rotationZ += Mathf.DegToRad(mouseX * mouseSensitivityX * inputDirection.Length()); - _rotationZ = Mathf.Clamp(_rotationZ, Mathf.DegToRad(-_zClamp), Mathf.DegToRad(_zClamp)); - } + if (isJoystickInput) + { + float rotationAmountY = inputX * sensitivityX * smoothingSpeed * (float)delta; + + // Accumulate the rotation over time for smooth horizontal rotation + _currentRotationY += rotationAmountY; + RotateY(Mathf.DegToRad(-inputX * sensitivityX)); + } + else + { + RotateY(Mathf.DegToRad(-inputX * sensitivityX)); + } + _rotationX += Mathf.DegToRad(-inputY * sensitivityY); + _rotationX = Mathf.Clamp(_rotationX, Mathf.DegToRad(-89f), Mathf.DegToRad(89f)); + + _rotationZ += Mathf.DegToRad(inputX * sensitivityX * inputDirection.Length()); + _rotationZ = Mathf.Clamp(_rotationZ, Mathf.DegToRad(-_zClamp), Mathf.DegToRad(_zClamp)); + } - public void RotatePlayerByConstraint(float mouseX, float mouseY, float leftDeg, float rightDeg) + public void RotatePlayerByConstraint(float mouseX, float mouseY, float leftDeg, float rightDeg) { float rotationY = Mathf.DegToRad(-mouseX * mouseSensitivityX); rotationY = Mathf.Clamp(rotationY, Mathf.DegToRad(leftDeg), Mathf.DegToRad(rightDeg)); diff --git a/project.godot b/project.godot index 14d8860..814656d 100644 --- a/project.godot +++ b/project.godot @@ -54,47 +54,76 @@ folder_colors={ forward={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) ] } backward={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) ] } left={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) ] } right={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) ] } sprint={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":7,"pressure":0.0,"pressed":true,"script":null) ] } crouch={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null) ] } free_look={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194328,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":8,"pressure":0.0,"pressed":true,"script":null) ] } jump={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) ] } screenShake={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":89,"key_label":0,"unicode":121,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":true,"script":null) +] +} +look_up={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null) +] +} +look_down={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null) +] +} +look_left={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null) +] +} +look_right={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null) ] }