Coding player movement for a 2D game that needs to have both left and right arrow keys pressed down at the same time

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Wysti

The problem is that when the player moves right, he can not “turn” left when the left arrow key is pressed when the right arrow key is already pressed down. You can see in the gif below that the player runs against the right wall when this happens (I am pressing the left arrow at this point).

On the other hand, the player can “turn” right when he is already moving left, as illustrated below.

The relevant code is below, I have tried to fit in if Input.is_action_just_pressed and is_action_just_released, whatever they are called, and also to make the line 54 elif statement if instead and indented with the line 46 statement, but I can’t get the movement to work ( make the player run left while he is running right already).


enter image description here

I don’t understand. What do you want to have happen when left and right are both pressed?

japhib | 2022-04-26 23:14

:bust_in_silhouette: Reply From: joeyq

This is because the right key will always override the left key.
If the if statement (move right) is true , the elif block (move left) and else block (idle) will be skipped over.
In stead of using Input.is_action_pressed(), a better way is to use Input.get_axis() which is shorthand for writing Input.get_action_strength(“positive_action”) - Input.get_action_strength(“negative_action”), which gives a float between -1 and 1.
If right and left are pressed on the keyboard at the same time you will get 0 (idle), if you have a joystick and use d-pad left or right you get -1 and 1, if you also mapped a joypad and slightly press right or left you get between -1 and 1 so you can get the player to walk slower or faster.
Here’s some example code based on godot 4 template of CharacterBody2D.

extends KinematicBody2D
## player speed and jump
const SPEED:float = 300.0
const JUMP_VELOCITY:float = -400.0

## Get the gravity from the project settings to be synced with RigidDynamicBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
## velocity of player
var velocity: Vector2 =Vector2()
## direction of player, 0 = idle, -1 is left, 1 is right
var direction: float = 0.0

## I assume you have a  sprite named "Sprite" for player
onready var sprite: Sprite = $"Sprite"
## I added a label as a sibling to this node named "Label" to show direction wchich is a float between -1 and 1
onready var label: Label = $"../Label"

func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta

	# Handle Jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	direction = Input.get_axis("ui_left", "ui_right")
	if direction:
		if sign(direction) == 1:
			sprite.flip_h = false
		if sign(direction) == -1:
			sprite.flip_h = true
		velocity.x = direction * SPEED
		velocity.x = move_toward(velocity.x, 0, SPEED)

	velocity = move_and_slide(velocity, Vector2.UP)
	## debug stuff
	label.text = str(direction)
	label.text += '\n' + str(is_on_floor())
	label.text += '\n' + str(velocity)

I am doing a left/right moving game and am using an implementation similar to above. Would recommend.

SnapCracklins | 2022-04-26 19:46