Remaking an equation in Godot

Godot Version

4.2.1

Question

When I started coding, I used, and still often use, scratch. I had a cool equation that I made in there that would allow a variable to gradually reach a maximum amount when a move key is pressed, and gradually reach 0 when a move key isn’t pressed.

const SPEED = 400
const FRICTION = 0.7

func _physics_process(delta)
-> var direction = Input.get_axis("ui_left", "ui_right")

-> velocity.x = (velocity.x + (((SPEED / FRICTION) - SPEED) * direction) * FRICTION)

However, when trying to move this into Godot, it rapidly increases, goes past the written max speed, and doesn’t gradually go back to 0.

((SPEED / FRICTION) - SPEED) As these are all constant we can reduce this to it’s value true value for debugging.

(velocity.x + (171.428 * direction) * 0.7)

I don’t see a reason why this would reach a maximum value so your player’s velocity will increase forever. Maybe in scratch your SPEED was a variable that you would apply to position?

A commonly used function in Godot is move_toward, this takes a value and a goal, and increases or decreases it by a speed towards that goal.

const SPEED = 400 # in pixels per second
const ACCELERATION = 1200 # in pixels per second, per second

func _physics_process(delta: float) -> void:
    var direction := Input.get_axis("ui_left", "ui_right")
    velocity.x = move_toward(velocity.x, SPEED * direction, ACCELERATION * delta)

Here velocity.x is the starting value, SPEED * direction is the goal, and ACCELERATION * delta is the increase or decrease in speed.

move_toward is built in, but here is an approximation of how the function works.

func move_toward(from, to, delta):
    if abs(to - from) < delta: # would over-shoot `to`
       return to
    else:
        var direction = sign(to - from)
        return from + delta * direction
2 Likes

This is complicated because it depends so much on your specific situation or requirements.

However I have found that using acceleration and max_speed as my defining traits, calculating new speed (new_speed = current_speed + acceleration * delta) and clamping it to max_speed, then using the calculated speed to calculate the new position for a sprite (new_position = current_position + current_speed * delta) makes everything super smooth. Especially when changing directions, I just change the acceleration and my ship slows to a stop and then accelerates away again in the new direction.

Especially as I then lerp to the new_position rather than just setting it. But I am not sure the lerping is strictly necessary.

Paul

PS I also set a deceleration rate seperately as I like having them set independently. So if the signs don’t match (acceleration and speed) you use deceleration value rather than the acceleration value. It is working beautifully although as I describe it here it sounds more complicated than it is.

Here is a link to lerping (I lerp everything).

1 Like