Move a 2D character by x distance taking x time on button press

Godot Version

`4.4

Question

I am able to move my 2D character on button press using move_local_x but how do i do so taking a specific time to complete? The character moves too fast with this animation

1 Like

Hiiiii :smiling_face:. If I understand correctly, I think you could use Tweens for that :open_mouth:. There is a cool video explaining them :grin:.

I cant seem to get it to work. If I want to say move the character to the right by 100 pixels over the course of 5 seconds when pressing a specific button what would the code look like?

my current attempt:

func _physics_process(delta: float) → void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta

# basic attack test
if Input.is_action_just_pressed("Test_attack_1"):
	animated_sprite.play("attack")
	get_tree().create_tween().tween_property(animated_sprite.play("attack"), move_local_x(100 * delta), 5)

Error=Cannot get return value of call to “move_local_x()” because it returns “void”.

If you want precise control over distance and time, your button press should init variables, and the movement should take place in _physics_process:

const MOVE_TIME := 5.0
const MOVE_DIST := 100.0

var move_time_left := 0.0

# on button press trigger
move_time_left = MOVE_TIME

# in _physics_process
if move_time_left > 0.0:
    move_time_left -= delta
    velocity.x = MOVE_DIST / MOVE_TIME # also account for gravity, etc.
else:
    # stop the motion here

Tweens can be convenient, but not really appropriate where more control is desired. Think of the button press as starting an action that you want to control for a duration, which means setting variable to process that action over the course of the duration.

I’d suggest something more like:

# Untested!

const MOVE_TIME  =   5.0
const MOVE_DIST  = 100.0
const MOVE_SPEED = MOVE_DIST / MOVE_TIME

var cur_time = 0.0
var moving = false

# Kick off a movement.

func start_moving():
    moving = true
    cur_time = 0.0

# Update func.

func _physics_process(delta: float):
    # If we're not moving, don't do any movement math.
    if moving:
        if cur_time < MOVE_TIME: # Not done yet?
            # If delta is higher than the time left, we could
            # overshoot, so we check for that.
            var remain = MOVE_TIME - cur_time
            if remain >= delta: # This update won't overshoot the end.
                cur_time += delta
                velocity.x += (MOVE_SPEED * delta) # Scale speed by delta.
            else: # This update would have overshot.
                cur_time = MOVE_TIME
                velocity.x += (MOVE_SPEED * remain)
                moving = false
        else: # Done.
            moving = false

I think part of the problem is that you aren’t scaling your speed by delta, so the speed you move will vary depending on the update rate. Remember, the update is getting called many times per second…