How to check the last pressed key

This should be the desired behavior for all diagonal directions, I really don’t know why it isn’t working for me :face_exhaling:

extends CharacterBody2D

@export var speed = 6000   
var dir := Vector2.ZERO

func _input(event):
	if event.is_action_pressed("left"):
		dir.x = -1
	if event.is_action_released("left"):
		dir.x = 1 if Input.is_action_pressed("right") else 0
	
	if event.is_action_pressed("right"):
		dir.x = 1
	if event.is_action_released("right"):
		dir.x = -1 if Input.is_action_pressed("left") else 0
	
	if event.is_action_pressed("up"):
		dir.y = -1
	if event.is_action_released("up"):
		dir.y = 1 if Input.is_action_pressed("down") else 0
	
	if event.is_action_pressed("down"):
		dir.y = 1
	if event.is_action_released("down"):
		dir.y = -1 if Input.is_action_pressed("up") else 0

func _physics_process(delta):
	if Input.is_action_pressed("left") and Input.is_action_pressed("right") and Input.is_action_pressed("up") and Input.is_action_pressed("down"):
		velocity = Vector2.ZERO
	else:
		var norm_dir : Vector2 = dir.normalized()
		velocity = Vector2(speed * norm_dir.x * delta, speed * norm_dir.y * delta)
	move_and_slide()

can you try directly using my code and see if it gives you the same issue please?

Yeah, that is odd. Honestly, if there’s nothing else in the script, no other outside elements/factors(other entities or effects). I’m not sure I can do much. Try putting the player in a fresh scene with nothing else and see if it still occurs.

My go-to when something like this happens is to restart Godot and your PC. Also, try making another player entirely. Don’t add anything but the essentials. Create a new CharacterBody2D scene, add the Godot Icon.svg as a sprite, add a script and only paste in your movement code. Add this temp player to a fresh scene as well and see if it’s still a problem.

I don’t know, I’ve modified my last reply, can you try please?

I’ve tried creating an entire new project and pasted the code, still the same issue:
it works just fine, but when I move diagonally I can’t adjust my Y direction unless I let go of the first Y input key.

It’s kinda annoying but maybe it’s a bug due to me using the “lightest” version of godot for programming, since I have an old ass pc, I don’t know.

Since there isn’t much more you can do here I’ll mark the thread as solved, thank you so much for your patience and help : )

And if you want, you can add me on discord, the tag is “cr1i”, I’ll be glad to chat with you about programming and learning from eachother (even though I will surely learn a lot more from you than you from me lol)

Damn… Sadly, it does work for me. I wish I had the answers but I really can’t find any issues. I had a very cheap keyboard in the past though that didn’t support more than 2 keypresses at once. Other than that I can’t think of anything.

Sure thing, I’ll add you. Though, I’m not active on discord a lot and am busy with work but I’ll answer you when I get a chance to. :wink:

FWIW I was trying to tackle the same issue and here’s the solution I came up with:

extends CharacterBody2D

@onready var _sprite = $AnimatedSprite2D

const ActionStates = {
	"IDLE": "idle",
	"WALK_LEFT": "left",
	"WALK_RIGHT": "right",
	"WALK_UP": "up",
	"WALK_DOWN": "down",
};

# Player controls as defined in Project Settings -> Input Map
const player_actions = [
	"left",
	"right",
	"up",
	"down"
];

# Small input buffer to keep track of what the last
# player control input was pressed
var recent_actions: Array = []

# Variable to keep track of the player state
var action_state: String = ActionStates.IDLE;

func _ready():
	# Set initial animation
	_sprite.play("walk_south")

func _input(event):
	for action in player_actions:
		# When the player pressed a player control key
		if Input.is_action_just_pressed(action):
			# Keep track of any pressed player control keys
			recent_actions.append(action)
			if recent_actions.size() > 2:
				recent_actions.pop_front()
			
			# Set the correct new player state
			action_state = action

		# When the player released a player control key
		elif Input.is_action_just_released(action):
			# Account that it's not being pressed anymore
			recent_actions.erase(action)

			# If we haven't tracked any previous keys, then idle
			if recent_actions.size() == 0:
				action_state = ActionStates.IDLE
			else:
				# Otherwise, iterate through recent actions to
				# check if there is an active key being pressed
				for i in range(recent_actions.size()):
					var previous_action = recent_actions[i]

					# If the player is still holding another control key
					if Input.is_action_pressed(previous_action):
						# Update the player state to reflect that
						action_state = previous_action
					else:
						# Otherwise we can set the player to idle
						action_state = ActionStates.IDLE

func _process(_delta):
	match action_state:
		ActionStates.WALK_LEFT:
			_sprite.flip_h = true
			_sprite.play("walk_side")
		ActionStates.WALK_RIGHT:
			_sprite.flip_h = false
			_sprite.play("walk_side")
		ActionStates.WALK_UP:
			_sprite.flip_h = false
			_sprite.play("walk_north")
		ActionStates.WALK_DOWN:
			_sprite.flip_h = false
			_sprite.play("walk_south")
		ActionStates.IDLE:
			_sprite.stop()

The general approach is that I’m keeping track of the last two (previous + current) actions pressed. And if the current action is released, then I check to see if the previous action is still pressed, and if it is, then proceed with that course of action. If it is not, then just idle.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.