Making topdown movement work with acceleration and deceleration

Godot Version

Godot Engine v4.2.1.stable.official.b09f793f5

Question

Hey there everybody. I’m trying to make topdown movement work with acceleration and deceleration. Unfortunately I’m extremely new and even a simple mechanic for moving turned out to be a million lines long. My questions are:

  1. How can I write this information in a better, shorter way?

  2. Because of the way I set up the movement in the beginning, it makes the character stop instantly when I stop pressing the key. How do I get around that?

  3. I want the character to slide before stopping completely. How should I approach coding that?

Thanks in advance.

func _process(delta):
	position.x -= currentSPEED * delta
	position.x += currentSPEED * delta
	
	position.y -= currentSPEED * delta
	position.y += currentSPEED * delta
	
	if Input.is_action_pressed("ui_left"):
		if velocity.length() > 1:
			velocity.normalized()
		currentSPEED += Acceleration * delta
		position.x -= currentSPEED * delta
		
		if currentSPEED > maxSPEED:
			currentSPEED = maxSPEED
		
	elif Input.is_anything_pressed() == false :
		currentSPEED -= Deceleration * delta
		if currentSPEED < 0:
			currentSPEED = 0	
	
	if Input.is_action_pressed("ui_right"):
		if velocity.length() > 1:
			velocity.normalized()
		currentSPEED += Acceleration * delta
		position.x += currentSPEED * delta
		
		if currentSPEED > maxSPEED:
			currentSPEED = maxSPEED
		
	elif Input.is_anything_pressed() == false :
		currentSPEED -= Deceleration * delta
		if currentSPEED < 0:
			currentSPEED = 0	
			
	if Input.is_action_pressed("ui_up"):
		if velocity.length() > 1:
			velocity.normalized()
		currentSPEED += Acceleration * delta
		position.y -= currentSPEED * delta
		
		if currentSPEED > maxSPEED:
			currentSPEED = maxSPEED
		
	elif Input.is_anything_pressed() == false :
		currentSPEED -= Deceleration * delta
		if currentSPEED < 0:
			currentSPEED = 0	
	
	if Input.is_action_pressed("ui_down"):
		if velocity.length() > 1:
			velocity.normalized()
		currentSPEED += Acceleration * delta
		position.y += currentSPEED * delta
		
		if currentSPEED > maxSPEED:
			currentSPEED = maxSPEED
		
	elif Input.is_anything_pressed() == false :
		currentSPEED -= Deceleration * delta
		if currentSPEED < 0:
			currentSPEED = 0	

Are you using a CharacterBody2D? It’s recommended to use _physics_process for PhysicsBody2D nodes (like CharacterBody2D) for movement logic.

Analyzing your code I see some things that are wrong.

First, this four lines are redundant.

You are substracting and adding the same values to the same variables.

Second: your are normalizing velocity in every input check and currentSPEED is being limited after adding it to position.

Third: you are checking if there are no keys pressed before applying the deceleration. That means that if I press, just for example, the space bar, that code won’t execute.

I’ll give you two ways of writing this shorter, but I recommend you to watch some tutorials on YouTube and check the documentation regularly.

Assuming your script extends CharacterBody2D (which I recommend).

func _physics_process(delta):
	var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	
	if direction != Vector2.ZERO:
		velocity = velocity.move_toward(direction * maxSPEED, Acceleration * delta)
	else:
		velocity = velocity.move_toward(Vector2.ZERO, Deceleration * delta)
	
	move_and_slide()

If your script is extending Node2D.

func _process(delta):
	var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	
	if direction != Vector2.ZERO:
		velocity = velocity.move_toward(direction * maxSPEED, Acceleration * delta)
	else:
		velocity = velocity.move_toward(Vector2.ZERO, Deceleration * delta)
	
	position += velocity * delta

Have a nice day or night!

1 Like

Thanks a lot man. I’ll try to study it and check the documentation. Thank you so much for your time

1 Like