Eight way movement problems. Hitting A and D at the same time

Godot Version

Godot.4.4.1

Question

I’ve been having a small problem with the movement in my game. It’s set up with the eight way movement script but whenever i press A and D at the same time, the player stops moving. I’ve been looking all over the internet for a good solution for this and have no idea what to do (i’m still fairly new to coding). I’m trying to make it so that when you hit the A key first, you keep moving in that direction, even if you hit the D key, like in most videogames. I’m sorry if this isn’t very clear but i’ve been struggling with this for a while now. Here’s my code if you need it:

extends CharacterBody2D

const speed = 400
const accel = 1800
const friction = 1200

var input = Vector2.ZERO
var direction : Vector2 = Vector2.ZERO

func _physics_process(delta):
direction = Input.get_vector(“left”, “right”, “up”, “down”).normalized()

if direction != Vector2.ZERO:
	var target_velocity = direction * speed
	velocity = velocity.move_toward(target_velocity, accel * delta)
else:
	velocity = velocity.move_toward(Vector2.ZERO, friction * delta)

move_and_slide()
1 Like

get_vector returns - as you might expect - a Vector2D. If you press D, the x-value of that vector is positive. If you press A, the x-value of that vector is negative. If you press both at the same time, the x-value will be zero. However, if you don’t press either button, the x-value will also be zero. Figuring out which button was pressed first using get_vector is clearly quite difficult.

One way to get the behavior you want is to look at which input commands were given instead. You can define your own inputs via the project settings (for instance, pressing A could be bound to the left input action.) You can now determine input like this:

func _physics_process(delta : float)->void:
    if Input.is_action_just_pressed("left"):
        # Left button press was detected here.

You could then use a variable to store what the input was last time _physics_process was called and compare it to current input. For instance, if on the previous call to the function only A was pressed and now both A and D are pressed, you know that you should continue moving left.

(Is the behavior you describe actually the default in many games? I guess I don’t actively think about that when playing games, but I feel as if that isn’t quite as universal as you say.)

1 Like

So it is behaving exactly as you have coded it at the moment. When you press A and D, the direction is Vector2(1,0) + Vector2(-1,0) which is Vector2.ZERO. In your next if statement you say if this is the case, do nothing.

You need to use the inputs to set an active_direction which is then used for movement. Something like this:

# Only allow new direction if no other active direction is set
if Input.is_action_just_pressed("left") and active_direction == "":
    active_direction = "left"
elif Input.is_action_just_pressed("right") and active_direction == "":
    active_direction = "right"

# Only cancel active direction if it is the currently active direction
if Input.is_action_just_released("left") and active_direction == "left":
    active_direction = ""
elif Input.is_action_just_released("right") and active_direction == "right":
    active_direction = ""

# Use the active direction for movement
if active_direction == "left":
    move_left()
elif active_direction == "right":
    move_right()

Hope that example helps. You would do the same for up and down as well if you wanted.

EDIT Sorry @TokyoFunkScene we crossed in our replies.

1 Like

Thanks, i didn’t know you could have empty quotes like that so i decided to add them into my script. I also got super literal with determining the direction thing and that seemed to really help me out a lot.

1 Like