using Godot; namespace Gmtk24 { public partial class Player : CharacterBody3D { [Export] public float MovementSpeed = 7; [Export] public float SprintMultiplier = 1.5f; [Export] public float JumpVelocity = 10; [Export] public float JumpBufferLengthSeconds = 0.2f; [Export] public float Gravity = 20; [Export] public Node3D Eye; [ExportCategory("Noises")] [Export] public AudioStreamPlayer HeightBasedWindPlayer; [Export] public float MinVolumeWindHeight = 0; [Export] public float MaxVolumeWindHeight = 0; [Export] public AudioStreamPlayer3D FootstepPlayer; [Export] public float FootstepNoiseInterval = 0.25f; private float CurrentYaw = 0; private float CurrentPitch = 0; private float JumpBufferTime = 0; private float FootstepCooldown = 0; public override void _UnhandledInput(InputEvent @event) { if (@event is InputEventMouseMotion mouseMotion && Input.MouseMode == Input.MouseModeEnum.Captured) { var cameraSensitivity = UserSettings.Singleton.GetCameraSpeedMultipliers(); var mouseMultiplier = 0.0003f; CurrentYaw -= mouseMotion.ScreenRelative.X * mouseMultiplier * cameraSensitivity.X; CurrentPitch -= mouseMotion.ScreenRelative.Y * mouseMultiplier * cameraSensitivity.Y; GetViewport().SetInputAsHandled(); } if (@event.IsActionPressed("jump")) { JumpBufferTime = JumpBufferLengthSeconds; } } public override void _Process(double delta) { var yawInput = Input.GetActionStrength("look_left") - Input.GetActionStrength("look_right"); var pitchInput = Input.GetActionStrength("look_up") - Input.GetActionStrength("look_down"); var cameraSensitivity = UserSettings.Singleton.GetCameraSpeedMultipliers(); CurrentYaw += yawInput * cameraSensitivity.X * (float)delta; if (Eye != null) { CurrentPitch += pitchInput * cameraSensitivity.Y * (float)delta; CurrentPitch = Mathf.Clamp(CurrentPitch, -Mathf.Pi * 0.49f, Mathf.Pi * 0.49f); } Eye.Quaternion = new Quaternion(Vector3.Up, CurrentYaw) * new Quaternion(Vector3.Right, CurrentPitch); if (JumpBufferTime > 0) { JumpBufferTime -= (float)delta; } float windRange = MaxVolumeWindHeight - MinVolumeWindHeight; float windVol = windRange == 0 ? 1 : Mathf.Clamp((Position.Y - MinVolumeWindHeight) / windRange, 0, 1); if (windVol != 0 && !HeightBasedWindPlayer.Playing) { HeightBasedWindPlayer.Play(); } HeightBasedWindPlayer.VolumeDb = Mathf.LinearToDb(windVol); if (IsOnFloor() && Velocity.Length() > 1) { FootstepCooldown -= (float)delta * Velocity.Length(); if (IsInstanceValid(FootstepPlayer) && FootstepCooldown < 0) { FootstepPlayer.GlobalPosition = GlobalPosition; FootstepPlayer.Play(); FootstepCooldown += FootstepNoiseInterval; } } else { FootstepCooldown = 0; } } public override void _PhysicsProcess(double delta) { Vector3 moveInput = new Vector3( Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"), 0, Input.GetActionStrength("move_backward") - Input.GetActionStrength("move_forward") ); Vector3 move = Eye.Basis * moveInput; move.Y = 0; move = move.Normalized() * Mathf.Min(1, moveInput.Length()) * MovementSpeed; if (Input.IsActionPressed("sprint")) { move *= SprintMultiplier; } Vector3 vel = Velocity; vel.X = move.X; vel.Z = move.Z; vel += Vector3.Down * Gravity * (float)delta; bool tooLow = Position.Y < 0; bool askedToJump = (IsOnFloor() || tooLow) && JumpBufferTime > 0; if (askedToJump) { JumpBufferTime = 0; vel += Vector3.Up * JumpVelocity; } if (tooLow && vel.Y < 0) { vel.Y = 0; } Velocity = vel; MoveAndSlide(); } } }