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