Controller Issue in Menu

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Chain
:warning: Old Version Published before Godot 3 was released.

Greetings!

I am going to keep it short: I have a menu which can be controlled by the left stick of a gamepad and via keyboard. Keyboard works fine, directional pad on controller too, but the left stick just creates bugs/straight up doesn’t work.

Gif to show my problem:

Thanks in advance!

I need to test if is a bug but try to get only the initial “event” from _input_event and ignore the next ones until is released.

eons | 2017-08-30 02:57

@eons Your suggestion works. If you just set a bool to ignore all is_action_pressed("ui_up") after the first one, until you get a is_action_released("ui_up"), this fixes the problem. Waaayy less code than the proposed answer (a couple extra lines to existing input code).

I would say this is a bug since is_action_pressed etc. should already have this built in for analogue inputs.

Domarius | 2019-01-20 02:36

:bust_in_silhouette: Reply From: quijipixel

Game sticks are troublesome and there are several ways to get around them. I’ll show you the way it worked for me:

const JOY_DEADZONE = 0.3

func _process(delta):
	var axis1_x_value = Input.get_joy_axis(0, JOY_ANALOG_0_X)
	var axis1_y_value = Input.get_joy_axis(0, JOY_ANALOG_0_Y)
	if axis1_y_value < -JOY_DEADZONE:
		up_pressed = true
	axis1_y_value > JOY_DEADZONE:
		down_pressed = true
	axis1_x_value > JOY_DEADZONE:
		right_pressed = true
	axis1_x_value < -JOY_DEADZONE:
		left_pressed = true

Every process call you have to poll the sticks current value. If you print the variables axis1_x_value and axis1_y_value you will notice that they range between -1 and 1. And that when the stick is released, it is probably not going back to 0. So using a constant (in this case JOY_DEADZONE) to check if it is pressed or not is a safer way to go.

Thank you for your reply. Your solution doesn’t quite help tough. The Menu is as glitchy as it was before. JOY_DEADZONE with a value of 0.99925 is the closest thing to a usable menu.
Is my controller just so broken?

Chain | 2017-08-29 12:53

Wow, thats just too much. Have you tested it with other games? A value of 0.3 worked for me pretty well but 0.9 its just too much. You can try the Godots controller demo, there you can see how your controller is behaving.

quijipixel | 2017-08-29 13:01

I started Dishonored 2 a couple of times. Everything is behaving like it should. But in Godot it doesn’t really work.

Chain | 2017-08-29 14:33

That might be a bug then. Place a post on github with the device, Godot version and computer specs.

quijipixel | 2017-08-29 16:55

it’s not a bug!
You just have to make sure that you only move the focus once and then wait until the joystick has been released once.

var pressed = false

func _process(delta):
    if (!pressed && down_pressed):
        do_something()
        pressed = true
    elif (pressed && !down_pressed):
        pressed = false

timoschwarzer | 2017-08-30 09:47

Posted the final solution above. Thanks man :slight_smile:

Chain | 2017-08-31 10:16

:bust_in_silhouette: Reply From: Chain

Thank you soooo much quijipixel!!! I would not have been able to do this without you!!

With your help I managed to create code which works and does the job exactly as I wanted. Here it is:

Variables:


const JOY_DEADZONE = 0.3
var axis1_x_value = 0
var axis1_y_value = 0

var pressed = false
var pressed2 = false

btns = [Array which contains all my Menu Buttons that I want to navigate through ]

Refreshing Axis:


func _fixed_process(delta):
axis1_x_value = Input.get_joy_axis(0, JOY_ANALOG_0_X)
axis1_y_value = Input.get_joy_axis(0, JOY_ANALOG_0_Y)

Listening to Input:


func _input(event):

# Down

btns[select_pos].grab_focus()

if btns[select_pos] == btns[btns.size() - 1] and axis1_y_value > JOY_DEADZONE and !pressed:
	select_pos = -1
	btns[select_pos].grab_focus()

if !pressed:
	if axis1_y_value > JOY_DEADZONE:
		select_pos += 1
		pressed = true
elif pressed:
	if not  axis1_y_value > JOY_DEADZONE:
		pressed = false
			
# Up

if btns[select_pos] == btns[-1] and axis1_y_value < -JOY_DEADZONE and !pressed2:
	select_pos = btns.size()-1
	btns[select_pos].grab_focus()
	
if !pressed2:
	if axis1_y_value < -JOY_DEADZONE:
		select_pos -= 1
		pressed2 = true
elif pressed2:
	if not axis1_y_value < -JOY_DEADZONE:
		pressed2 = false

It is not a very clean, effective or well thought out code. But it works.

Thank you :slight_smile: