0 votes

I'm trying to do what GDquest did in one of his videos: I'm trying to do grid-based movement. I've tried adapting his code, but I couldn't get that to work. Then I tried the code of airvikar, but I couldn't get that to work. Finally, I went to the official Discord channel and got the input of eons. He gave me some code and pointed me in a good direction, but I still can't get this code to function properly.

extends KinematicBody2D

const MOTION_SPEED = 160

func _physics_process(delta):
    var motion_vector = Vector2()
    var le_input = false
    var moving = false
    var direction = Vector2()
    var step_size = 0
    var motion_amount = 0

    # Let's do some moving
    if (Input.is_action_pressed("ui_up")):
        motion_vector += Vector2( 0, -1)
    if (Input.is_action_pressed("ui_down")):
        motion_vector += Vector2( 0, 1)
    if (Input.is_action_pressed("ui_left")):
        motion_vector += Vector2( -1, 0)
    if (Input.is_action_pressed("ui_right")):
        motion_vector += Vector2( 1, 0)

    if motion_vector != Vector2() and !moving:
        direction = motion_vector.normalized()
        step_size = MOTION_SPEED
        moving = true
    if step_size >= 0:
        motion_amount = step_size * delta
        move_and_collide(direction * motion_amount)
    elif moving:
        step_size = 0
        moving = false

This code is on a player scene which is added to the main scene. I'm not entirely certain where the code isn't properly moving the player sprite from tile to tile. The player sprite should just move from tile to tile, and not really have any intermediary movement (i.e. walking slowly in between tiles).

asked May 17 in Engine by Ertain (154 points)
edited May 17 by Ertain

1 Answer

0 votes
Best answer

I know the type of movement your talking about. And I believe I have a solution.

var moving = false

func _physics_process(delta):
    if !moving:
        var motion_vector = Vector2()
        if Input.is_action_pressed("ui_up"):
            motion_vector += Vector2( 0, -1)
        if Input.is_action_pressed("ui_down"):
            motion_vector += Vector2( 0, 1)
        if Input.is_action_pressed("ui_left"):
            motion_vector += Vector2( -1, 0)
        if Input.is_action_pressed("ui_right"):
            motion_vector += Vector2( 1, 0)

        if motion_vector != Vector2():
            #tile_size is the size of the tilemap in pixels.
            var new_position = position + motion_vector * tile_size
            #Yes. I'm assuming you have a Tween node as a child.
            $Tween.interpolate_property ( self, 'position', position, new_position, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
            #That last method's fifth property is how long it takes to go from one tile to the other in seconds.
            $Tween.start()
            moving = true

#This function is connected to the tween node's tween_completed signal.
func _on_Tween_tween_completed(object, key):
    moving = false
answered 6 days ago by SIsilicon (937 points)
selected 4 days ago by Ertain

Slow character?
Remember this line??

$Tween.interpolate_property ( self, 'position', position, new_position, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
#That last method's fifth property is how long it takes to go from one tile to the other in seconds.

The fifth property is your character's speed. Except the bigger it is, the longer it takes for them to go to the next tile.

So a value of 1 means it takes 1 second to go to the next tile.
And a value of zero means you travel instantly.

I eventually learned that. :P As for collisions, well, that's another monster.

I gotcha covered there.

Assuming your player is a kinematic body, you should have access to the method test_move(Transform2D from, Vector2 rel_vec). Returns true if a collision occurs.

Which mean you will change this-

        #tile_size is the size of the tilemap in pixels.
        var new_position = position + motion_vector * tile_size
        #Yes. I'm assuming you have a Tween node as a child.
        $Tween.interpolate_property ( self, 'position', position, new_position, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
        #That last method's fifth property is how long it takes to go from one tile to the other in seconds.
        $Tween.start()
        moving = true

To this.

        #tile_size is the size of the tilemap in pixels.
        motion_vector *= tile_size
        if not test_move(global_transform, motion_vector):
            #Yes. I'm assuming you have a Tween node as a child.
            $Tween.interpolate_property ( self, 'position', position, position+motion_vector, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
            #That last method's fifth property is how long it takes to go from one tile to the other in seconds.
            $Tween.start()
            moving = true

Notice that the new_position variable was omitted and in the Tween's function replaced with position+motion_vector.

Thank you for that fix, Sisilicon.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.