using System; using Godot; using Playground.Common.CharacterMovement; namespace KarrotStarterTemplate.Common.CharacterMovement; [GlobalClass] public partial class CharacterMovementController : Node { [Export] public CharacterBody3D characterBody { get; set; } [Export] public CharacterMovementMode defaultMovementMode { get; set; } [Export] public AnimationMixer animationTree { get; set; } public CharacterMovementMode currentMovementMode { get; private set; } private Vector3 _temporaryMovementDirection = Vector3.Zero; public Vector2 blendspacePosition { get; private set; } public override void _Ready() { currentMovementMode = defaultMovementMode; characterBody ??= (CharacterBody3D)GetParent(); } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _PhysicsProcess(double delta) { Vector3 velocity = characterBody.Velocity; CharacterMovementMode v = currentMovementMode; if (v.gravityScale != 0 && !characterBody.IsOnFloor()) { velocity += characterBody.GetGravity() * (float)delta; } _temporaryMovementDirection = _temporaryMovementDirection.Normalized(); if (!_temporaryMovementDirection.IsZeroApprox()) { // velocity.X = _temporaryMovementDirection.X * v.speed; // velocity.Y += _temporaryMovementDirection.Y * v.speed; // velocity.Z = _temporaryMovementDirection.Z * v.speed; velocity = velocity.Lerp(_temporaryMovementDirection * v.speed, 3 * (float)delta); if (v.rotationRate > 0) { Vector3 c = characterBody.GlobalRotation; characterBody.GlobalRotation = new Vector3(0, Mathf.LerpAngle(c.Y, -Mathf.Atan2(velocity.X, -velocity.Z), Mathf.DegToRad(v.rotationRate) * (float)delta) , 0); // characterBody.LookAt(characterBody.GlobalPosition + velocity); } } else { if (velocity.Length() < .3) { velocity = velocity.MoveToward(new Vector3(0, velocity.Y, 0), 2 * (float)delta); } else { velocity = velocity.Lerp(new Vector3(0, velocity.Y, 0), 2 * (float)delta); } } _temporaryMovementDirection = Vector3.Zero; characterBody.Velocity = velocity; characterBody.MoveAndSlide(); } public override void _Process(double delta) { float x = characterBody.GlobalTransform.Basis.X.Dot(characterBody.Velocity); float z = characterBody.GlobalTransform.Basis.Z.Dot(characterBody.Velocity) * -1; blendspacePosition = blendspacePosition.MoveToward(new Vector2(x, z) , 4 * (float)delta * 1f); } public void SetMovementMode(CharacterMovementMode movementMode) { currentMovementMode = movementMode ?? defaultMovementMode; } public void AddMovementInput(Vector2 direction, float value) { AddMovementInput(new Vector3(direction.X, 0f, direction.Y), value); } public void AddMovementInput(Vector3 direction, float value) { if (currentMovementMode.ignoreUpDirection) { direction = new Vector3(direction.X, 0f, direction.Z); } _temporaryMovementDirection += direction * value; } }