0 votes

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:

http://imgur.com/a/Gehbu

Thanks in advance!

in Engine by (71 points)

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 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.

2 Answers

0 votes
Best answer

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 :)

by (71 points)
+1 vote

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.

by (689 points)

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?

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.

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

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

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

Posted the final solution above. Thanks man :)

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.