How to Prioritize the most recent Direction with Movement?

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

I’m new to Godot and programming in general and have been working on simple 4- Direction Topdown 2D movement. I have gotten the movement to a point I like but have encountered a problem. For the current code certain movement takes priority over another.

For example if I am holding Left and then press Right, the player will move Right, but if I am holding Right and press Left the player will keep moving Right.

I want the player to be able to continue to press a key, then a press a new key and the movement will change to it, but if the second key is released the movement will return to the first.

ie - Holding Up and go Up, but if you press Right you will go Right, then if you release Right, while still holding Up, you will return to going Up.

Im sure this is a simple problem but I’ve yet to find a solution that works and also keeps 4-Direction movement (I don’t want 8 directions).
Anyways here is the code:

extends KinematicBody2D

const TOPDOWN = Vector2(0, 0)
const SPEED = 150

var motion = Vector2()

func _physics_process(delta):
	_controls_loop()
	_movement_loop()	

func _movement_loop():
	motion = move_and_slide(motion, TOPDOWN)

func _controls_loop():
	var right = Input.is_action_pressed("ui_right")
	var left = Input.is_action_pressed("ui_left")
	var up = Input.is_action_pressed("ui_up")
	var down = Input.is_action_pressed("ui_down")

	if right:
		motion.x = SPEED
		motion.y = 0
	elif left:
		motion.x = -SPEED
		motion.y = 0
	elif up:
		motion.x = 0
		motion.y = -SPEED
	elif down:
		motion.x = 0
		motion.y = SPEED
	else:
		motion.x = 0
		motion.y = 0

If anyone could help me or point me in the right direction I would greatly appreciate it

:bust_in_silhouette: Reply From: Eric Ellingson

Not sure if this is the best way, but it seems to work.

extends KinematicBody2D

const TOPDOWN = Vector2(0, 0)
const SPEED = 150

const MOVEMENTS = {
	'ui_up': Vector2.UP,
	'ui_left': Vector2.LEFT,
	'ui_right': Vector2.RIGHT,
	'ui_down': Vector2.DOWN,
}

# hold an ordered list of the currently pressed keys
var direction_history = []
var motion = Vector2()

func _physics_process(delta):
	_controls_loop()
    _movement_loop()

func _movement_loop():
    motion = move_and_slide(motion * SPEED, TOPDOWN)

func _controls_loop():
    # reset motion to zero, so that if no keys are pressed there 
    # will be no movement
	motion = Vector2()

    # loop through all the directions ('ui_up', ui_left', etc),
    # check to see if a key has been released, and if so, we
    # want to remove it from the array holding all the pressed keys
	for direction in MOVEMENTS.keys():
		if Input.is_action_just_released(direction):
			var index = direction_history.find(direction)
			if index != -1:
				direction_history.remove(index)
		if Input.is_action_just_pressed(direction):
			direction_history.append(direction)

	if direction_history.size():
		var direction = direction_history[direction_history.size() - 1]
		motion = MOVEMENTS[direction]

Thank you! This is working perfectly and I think I understand it. Essentially we are just storing inputs in our array and removing them once they are released, this way the newest input takes priority. I was thinking this was how you had to do it but was not sure how to go about it. Thank you for showing it in a way that makes sense, your comments helped me to understand. :slight_smile:

Jinnom | 2019-10-26 17:54