Hi all,
New to Godot here, so apologies for anything obvious I'm missing here.
I'm creating a movement system for a 2.5D RPG, similar to Paper Mario. Currently, I have a system set up that uses acceleration and deceleration when moving, along with a sprint mechanic, and a "skidding" mechanic. The skidding occurs when the player attempts to take a sharp turn, locking them into their current direction, whilst decelerating until they've completely stopped, then allowing them to move again. This system was working as intended before implementing gravity and vertical movement - however, now if the player takes turns in certain directions, or skids whilst sprinting, they will continue to skid indefinitely, with their speed never reaching zero.
Here's the code:
extends KinematicBody
#Variable Declarations
var walkSpeed = 6.0
var sprintSpeed = 11.0
var maxSpeed
var acceleration = 20.0
var deceleration = 30.0
var velocity = Vector3()
var direction = Vector2()
var input_direction = Vector2()
var state = "walking"
var turnSpeed = 10.0
var fallSpeed = 30.0
var jumpSpeed = 10.0
func _physics_process(delta):
var currentSpeed = velocity.length()
#jumping
if Input.is_action_just_pressed("jump"):
velocity.y = jumpSpeed
#Movement
maxSpeed = walkSpeed
if state == "walking":
if Input.is_action_pressed("sprint"):
maxSpeed = sprintSpeed
#Get input direction
input_direction.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
input_direction.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
input_direction = input_direction.normalized()
#Instantly set direction if player is not moving (no turning)
if currentSpeed == 0:
direction = input_direction
direction = (direction.linear_interpolate(input_direction, turnSpeed * delta)).normalized()
#Detect if player takes a sharp turn, and skid if so
if abs(direction.angle_to(input_direction)) > PI/2:
state = "skid"
if currentSpeed > walkSpeed:
state = "sprintskid"
#Stop if no input
if input_direction.length() > 0:
currentSpeed += acceleration * delta
else:
currentSpeed -= deceleration * delta
#Skidding
if state == "skid":
currentSpeed -= deceleration * delta * 2
if currentSpeed <= deceleration * delta * 2:
#When speed reaches zero, return to normal state
currentSpeed = 0
state = "walking"
#Sprint Skidding
if state == "sprintskid":
currentSpeed -= deceleration * delta * 0.35
if currentSpeed <= deceleration * delta * 0.35:
#When speed reaches zero, return to normal state
currentSpeed = 0
state = "walking"
currentSpeed = clamp(currentSpeed, 0, maxSpeed)
velocity.x = direction.x * currentSpeed
velocity.z = direction.y * currentSpeed
move_and_slide(velocity, Vector3.UP)
#Jump sound
if Input.is_action_just_pressed("jump"):
$AudioStreamPlayer2D.play()
#sprite code
if currentSpeed > 0:
if velocity.x < 0.1:
$Spriteholder/AnimatedSprite3D.play("run")
$Spriteholder/AnimatedSprite3D.scale.x = -1
if velocity.x > -0.1:
$Spriteholder/AnimatedSprite3D.play("run")
$Spriteholder/AnimatedSprite3D.scale.x = 1
else:
$Spriteholder/AnimatedSprite3D.play("stand")
if state == "skid" or state == "sprintskid":
$Spriteholder/AnimatedSprite3D.play("skid")
if is_on_floor():
velocity.y = 0
else:
velocity.y -= fallSpeed * delta
Here's some footage.
Thanks in advance.