How can I avoid two "event.is_action_released"

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

I have a 2D project where I have a main character who is moved by W, A, S and D keys, and I’m trouble with the key releasing. When any of that keys is released when another is going to be pressed, the animation freezes on the first key stand animation. For example, if you press W and then press A when are releasing W, it freezes on the W stand animation and don’t changes for the walking A animation. Here is the code:

extends KinematicBody2D

var character_name = "carlton"
var dir = Vector2(0,0)
var speed = 200

var char_up
var char_down
var char_left
var char_right
var rel_up
var rel_down
var rel_left
var rel_right

func _ready():
	$sprite.scale = Vector2(0.1,0.1)
	set_physics_process(true)
	set_process_input(true)

func _physics_process(delta):
	move_and_collide(dir * speed * delta)

func _input(event):
	char_up = event.is_action_pressed("character_up")
	char_down = event.is_action_pressed("character_down")
	char_left = event.is_action_pressed("character_left")
	char_right = event.is_action_pressed("character_right")
	rel_up = event.is_action_released("character_up")
	rel_down = event.is_action_released("character_down")
	rel_left = event.is_action_released("character_left")
	rel_right = event.is_action_released("character_right")
	_update()

func _update():
	if char_up:
		dir.y = -1
		$sprite.animation = "walk_up"
	elif char_down:
		dir.y = 1
		$sprite.animation = "walk_down"
	elif char_left:
		dir.x = -1
		$sprite.animation = "walk_right"
		$sprite.scale.x = -0.1
	elif char_right:
		dir.x = 1
		$sprite.animation = "walk_right"
		$sprite.scale.x = 0.1
	elif rel_up:
		dir.y = 0
		$sprite.animation = "up"
	elif rel_down:
		dir.y = 0
		$sprite.animation = "down"
	elif rel_left:
		dir.x = 0
		$sprite.animation = "right"
	elif rel_right:
		dir.x = 0
		$sprite.animation = "right"

Hi, Have you tried running update in _process instead than in input? because input is called once when an input is detected. So it will be updated with the last event that was triggered i think, and never be updated again untill you start another. For example, if W key released is detected by engine after A key pressed, the last update you will see is W key released and it will keep that animation until you press or release another thing.

p7f | 2018-12-06 15:59

Great for you! Can you post it as an answer so everybody can see its solved?

p7f | 2018-12-06 20:30

:bust_in_silhouette: Reply From: JulioYagami

I tried lots of times until I found a solution that really works.

I created a timer node that automatically updates the player animation based on the dir Vector.

extends KinematicBody2D

var character_name = "carlton"
var dir = Vector2(0,0)
var speed = 200

var timer

func _ready():
	timer = Timer.new()
	timer.wait_time = 0.5
	timer.autostart = true
	timer.one_shot = false
	add_child(timer)
	timer.connect("timeout",self,"_on_timer_timeout")
	
	$sprite.scale = Vector2(0.1,0.1)
	set_process_input(true)
	set_process(true)

func _process(delta):
	translate(dir * speed * delta)

func _input(event):
	if event.is_action_pressed("character_up"):
		$sprite.animation = "walk_up"
		dir.y = -1
	elif event.is_action_pressed("character_down"):
		$sprite.animation = "walk_down"
		dir.y = 1
	elif event.is_action_pressed("character_left"):
		$sprite.animation = "walk_right"
		$sprite.scale.x = -0.1
		dir.x = -1
	elif event.is_action_pressed("character_right"):
		$sprite.animation = "walk_right"
		$sprite.scale.x = 0.1
		dir.x = 1
	elif event.is_action_released("character_up"):
		$sprite.animation = "up"
		dir.y = 0
	elif event.is_action_released("character_down"):
		$sprite.animation = "down"
		dir.y = 0
	elif event.is_action_released("character_left"):
		$sprite.animation = "right"
		$sprite.scale.x = -0.1
		dir.x = 0
	elif event.is_action_released("character_right"):
		$sprite.animation = "right"
		$sprite.scale.x = 0.1
		dir.x = 0

func _on_timer_timeout():
	match dir:
		Vector2(0,-1):
			$sprite.animation = "walk_up"
		Vector2(0,1):
			$sprite.animation = "walk_down"
		Vector2(-1,0):
			$sprite.animation = "walk_right"
			$sprite.scale.x = -0.1
		Vector2(1,0):
			$sprite.animation = "walk_right"
			$sprite.scale.x = 0.1