Disabling diagonal movement

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

So in my game, I want the player to be able to walk left, right, backwards and forwards only, and not diagonally. How should I modify my code to achieve this? The current code is:

func _physics_process(delta):
	var input_vector = Vector2.ZERO
	
	input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
	input_vector = input_vector.normalized()
	
	if input_vector != Vector2.ZERO:
		animationTree.set("parameters/Idle/blend_position", input_vector)
		animationTree.set("parameters/Run/blend_position", input_vector)
		animationState.travel("Run")
		velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION*delta)
	else:
		animationState.travel("Idle")
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
	
	velocity = move_and_slide(velocity)

do you want:

  • up/down or left/right prioritized
  • keep direction, if additional keys are pushed
  • going in the last pushed direction
    ?

whiteshampoo | 2020-06-23 12:43

:bust_in_silhouette: Reply From: Czselu349

This solution doesn’t keep the direction if additional keys are pushed and it prioratizes left/right, but here you go:

export(int) var acceleration = 240
export(int) var max_speed = 840
export(int) var friction = 420

var velocity = Vector2(0,0)
var move_dir = Vector2(0,0)

func _physics_process(delta):
	if Input.is_action_pressed("ui_right") || Input.is_action_pressed("ui_left"):
		move_dir.x = int(Input.is_action_pressed("ui_right")) - 
int(Input.is_action_pressed("ui_left"))
	elif Input.is_action_pressed("ui_down") || Input.is_action_pressed("ui_up"):
		move_dir.y = int(Input.is_action_pressed("ui_down")) - 
int(Input.is_action_pressed("ui_up"))
	else:
		move_dir = Vector2(0,0)

	move_dir = move_dir.normalized()

	if move_dir != Vector2(0,0):
		# Animation stuff
		velocity += acceleration * move_dir
		velocity = velocity.clamped(max_speed)
	else:
		# Animation stuff
	velocity = velocity.move_toward(Vector2(0,0), friction)

velocity = move_and_slide(velocity)
:bust_in_silhouette: Reply From: artemis flintlock

Necro this question to add to it. I wanted to implement something along the same line. I took a simplified approach using absolute value and tracking the x,y velocity in variables.

extends KinematicBody2D


var velocity = Vector2.ZERO
var vx = 0
var vy = 0

func _physics_process(delta):
var input_vector = Vector2.ZERO

if abs(vy) == 0:
	input_vector.x = Input.get_action_strength("ui_right") -     Input.get_action_strength("ui_left") 
if abs(vx) == 0:
	input_vector.y = Input.get_action_strength("ui_down") -     Input.get_action_strength("ui_up")

vx = input_vector.x
vy = input_vector.y

if input_vector != Vector2.ZERO:
	velocity = input_vector
else:
	velocity = Vector2.ZERO
	
move_and_collide(velocity)

Here is my solution:

############################################################
#
#	Main player movement script
#
#	By: rt-2
#	Created: 2024-06-09
#	Last update: 2024-06-09
#
############################################################

extends CharacterBody2D

#
#	Vars
# 
# Constants
@export var PLAYER_SPEED : float = 100
const KEY_NONE : int = -1
const KEY_RIGHT : int = 0
const KEY_LEFT : int = 1
const KEY_UP : int = 2
const KEY_DOWN : int = 3
# Vars
var player_last_directionAccepted : int = KEY_NONE
var player_last_inputs : Array = [null, null, null, null]

#
# Main Process
#
func _physics_process(_delta) :

	# Vars
	#inputs
	var inputs : Array = [null, null, null, null]
	inputs[KEY_RIGHT] = int(Input.get_action_strength("right"))
	inputs[KEY_LEFT] = int(Input.get_action_strength("left"))
	inputs[KEY_UP] = int(Input.get_action_strength("up"))
	inputs[KEY_DOWN] = int(Input.get_action_strength("down"))

	# save last state
	var tmp_player_last_inputs : Array = [null, null, null, null]
	var n : int = 0
	for v in inputs :
		tmp_player_last_inputs[n] = v
		n += 1
	
	# Prevent player from going diagonal
	if inputs[player_last_directionAccepted] == 0 : player_last_directionAccepted = KEY_NONE
	var i : int = 0
	#loop through all inputs
	while i < player_last_inputs.size() :
		if inputs[i] == 1 and i != player_last_directionAccepted and player_last_inputs[i] != 1:
			#found one pressed that wasnt the last pressed
			player_last_directionAccepted = i
			break
		i += 1
	
	#remove all others from inputing except new one
	var j : int = 0
	while j < inputs.size() :
		if player_last_directionAccepted != KEY_NONE and j != player_last_directionAccepted :
			#if not the new button, remove
			inputs[j] = 0
		j += 1
	
	# save last state
	player_last_inputs = tmp_player_last_inputs
	
	# Get inputs
	var input_direction = Vector2(
		inputs[KEY_RIGHT] - inputs[KEY_LEFT],
		inputs[KEY_DOWN] - inputs[KEY_UP]
	)
		
	# Get Velocity
	velocity = input_direction * PLAYER_SPEED		
		
	# Apply movement
	move_and_slide()