Fluid object movement with gamepad stick [problem]
gamedevmike

Hello.
I'm creating a simple fighter game with Allegro 5. One of my basic establishments was the possibility to use gamepads (they feel more comfortable in fighters, don't they).

The problem I encountered is that I somehow cannot make my character move (right, left) fluently when the left stick is held (position 1.0 or -1.0 on axis 0, stick 0).

Here's how I'm trying to achieve it:

#SelectExpand
1if( event.type == ALLEGRO_EVENT_TIMER ) 2{ 3 al_get_joystick_state( joy1, &gamepadstate ) 4 if( gamepadstate.stick[0].axis[0] && event.joystick.pos == 1.0 ) position += movespeed; 5 if( gamepadstate.stick[0].axis[0] && event.joystick.pos == -1.0 ) position -= movespeed; 6}

This is based on keyboard movement procedure, which looks like this:

#SelectExpand
1if( event.type == ALLEGRO_EVENT_TIMER ) 2{ 3 if( al_key_down( &keystate, ALLEGRO_KEY_RIGHT ) ) position += movespeed; 4 if( al_key_down( &keystate, ALLEGRO_KEY_LEFT ) ) position -= movespeed; 5}

Unfortunately, such an approach does not work.
if(gamepadstate.stick[0].axis[0]) cout << event.joystick.pos; shows some float number from 0.2 to 0.7 (approximately, hardly ever reaches 1) when I move the stick. The number is always non-negative, no matter if I flick my stick left or right.

Position output is valid under
if( event.type == ALLEGRO_EVENT_JOYSTICK_AXIS )
but there's no fluid move either. One object (character) position change on one flick, nothing more when held (which is completely expected ofc).

And finally some questions.
Is there anything I missed?
Is my approach any good?
What don't I understand here?
Could I get any advice on how to move my character with gamepad stick?

Thanks in advance. Sorry if I'm unclear anywhere.

Edgar Reynaldo

Simple answer - don't use polling, use events and keep track of the state yourself. You may find the events have correct data where the joystick state does not.

beoran

An analog stick may not report an axis at a full 1.0 or - 1.0. This is normal for analog sticks since they can sense how much you are tilting the stick. In stead of comparing with 1, set a threshold for motion >0.1 or so.

gamedevmike

Thanks for answers.
I wondered if there's a ready resolution to use.

@beoran Tried this. It's not the case.

Audric

The error is that for ALLEGRO_EVENT_TIMER event, you are allowed to read event.timer, but not event.joystick - the latter will read as "garbage" data.

You can use something like this:

#SelectExpand
1if( event.type == ALLEGRO_EVENT_TIMER ) 2{ 3 bool controler_left = 0; 4 bool controler_right = 0; 5 // poll keyboard 6 ALLEGRO_KEYBOARD_STATE keystate; 7 al_get_keyboard_state(&keystate); 8 if( al_key_down( &keystate, ALLEGRO_KEY_RIGHT ) ) controler_right = 1; 9 if( al_key_down( &keystate, ALLEGRO_KEY_LEFT ) ) controler_left = 1 ; 10 11 // poll joystick 12 al_get_joystick_state( joy1, &gamepadstate ); 13 float axis_x = gamepadstate.stick[0].axis[0]; 14 if( axis_x > 0.3) controler_right = 1; 15 if( axis_x < -0.3) controler_left = 1; 16 17 // logic 18 if (controler_right && !controler_left) position += movespeed; 19 if (controler_left && !controler_right) position -= movespeed; 20 21}

The alternative is skip the part where you poll the entire keyboard/joystick, and instead react to the events, for example :

if( event.type == ALLEGRO_EVENT_JOYSTICK )
{
   // A movement of the horizontal axis on first joystick
   if (event.joystick.stick == 0 && event.joystick.axis == 0)
   {
      float axis_x = event.joystick.pos;
      if( axis_x > 0.3) controler_right = 1;
      if( axis_x < -0.3) controler_left = 1;
   }
}

Thread #617033. Printed from Allegro.cc