Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Input response times for controllers

Credits go to bamccaig and Eric Johnson for helping out!
This thread is locked; no one can reply to it. rss feed Print
Input response times for controllers
TripleG
Member #16,431
July 2016

The input response for

if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN)
{
printf("Button was pressed\n");
}
else if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_UP)
{
printf("Button was released\n");
}

is really bad. Sometimes it even skips that the button was released. It improved when I used al_wait_for_event(event_queue, &events);

but there are still skips when the buttons are pressed when I press the buttons too fast. Even when I press them at slow intervals it sometimes skips Button was released. I am using ALLEGRO_5.22 and have it installed using Microsoft visual studio 2015. Keyboard responses are immediate and analog response are immediate with controllers. It is just the buttons that are the issue

Eric Johnson
Member #14,841
January 2013
avatar

Please post a full program so we can better help you.

Here is a quick program I threw together to test joystick button inputs:

#SelectExpand
1#include <iostream> 2 3#include <allegro5/allegro.h> 4 5using std::cout; 6 7int main(void) { 8 9 if (!al_init()) { 10 11 cout << "Error: failed to initialize Allegro\n"; 12 13 return -1; 14 } 15 16 if (!al_install_joystick()) { 17 18 cout << "Error: failed to install joystick\n"; 19 20 return -1; 21 } 22 23 ALLEGRO_TIMER *timer; 24 ALLEGRO_EVENT_QUEUE *event_queue; 25 26 if (!(timer = al_create_timer(1.0 / 60.0))) { 27 28 cout << "Error: failed to create timer\n"; 29 30 return -1; 31 } 32 33 if (!(event_queue = al_create_event_queue())) { 34 35 cout << "Error: failed to create event_queue\n"; 36 37 return -1; 38 } 39 40 al_register_event_source(event_queue, al_get_joystick_event_source()); 41 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 42 43 al_start_timer(timer); 44 45 cout << "Notice: press joystick buttons now (program will shutdown in 20 seconds)\n\n"; 46 47 while (true) { 48 49 ALLEGRO_EVENT event; 50 51 al_wait_for_event(event_queue, &event); 52 53 if (event.type == ALLEGRO_EVENT_TIMER) { 54 55 static unsigned int ticks = 0; 56 57 ++ticks; 58 59 if (ticks > 60 * 20) { 60 61 break; 62 } 63 } 64 65 if (event.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN) { 66 67 cout << "Button pressed\n"; 68 } 69 else if (event.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_UP) { 70 71 cout << "Button released\n"; 72 } 73 } 74 75 al_destroy_timer(timer); 76 al_destroy_event_queue(event_queue); 77 78 cout << "\nGood bye!\n"; 79 80 return 0; 81}

I'm experiencing no latency from the above. I'm curious to know what you experience when you try out the above. It could be that your controller or the adapter used with it is bad.

TripleG
Member #16,431
July 2016

That sample code you posted does not have any delays at all! (Thank you for that) I'll look to see where I went wrong but I still can't find anything and I don't understand why this is still happening. Here is my code that I am using

#SelectExpand
1 2#include "allegro5\allegro.h" 3#include "allegro5\allegro_image.h" 4#include "allegro5\allegro_native_dialog.h" 5#include "allegro5\allegro_font.h" 6#include "allegro5\allegro_ttf.h" 7#include "allegro5\allegro_audio.h" 8#include "allegro5\allegro_acodec.h" 9#include "allegro5\allegro_native_dialog.h" 10#include "allegro5\display.h" 11#include "allegro5\timer.h" 12 13#include "Input.h" 14#include <stdlib.h> 15 16int main() 17{ 18 if (!al_init()) 19 { 20 exit(1); 21 } 22 // Initlizes the ability to use images 23 if (!al_init_image_addon()) 24 { 25 exit(1); 26 } 27 28 // Initialize the ability to use fonts 29 al_init_font_addon(); 30 31 // Initialize the ability to use true type fonts 32 if (!al_init_ttf_addon()) 33 { 34 exit(1); 35 } 36 37 al_install_audio(); 38 39 if (!al_is_audio_installed()) 40 { 41 exit(1); 42 } 43 44 // Allows the ability to load diffrent audio files 45 if (!al_init_acodec_addon()) 46 { 47 exit(1); 48 } 49 50 // How many sounds I am allowed to play (20) 51 if (!al_reserve_samples(20)) 52 { 53 exit(1); 54 //printf("Audio device was not installed correctly\n"); 55 } 56 57 // Allows the ability to use joysticks in the game. 58 if (!al_install_joystick()) 59 { 60 exit(1); 61 } 62 63 // Allows the aility to use keyboard in the game 64 if (!al_install_keyboard()) 65 { 66 exit(1); 67 } 68 69 // Allows the ability to use a mouse in the game 70 if (!al_install_mouse()) 71 { 72 exit(1); 73 } 74 75 al_set_new_display_flags(ALLEGRO_WINDOWED); // Set the display to window mode 76 77 ALLEGRO_DISPLAY *_display; 78 _display = al_create_display(400, 600); 79 80 ALLEGRO_EVENT events; 81 82 ALLEGRO_TIMER* _timer; 83 _timer = al_create_timer(1.0 / 60.0); // Game run 60 frames a second 84 85 ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue(); 86 87 al_register_event_source(event_queue, al_get_joystick_event_source()); // Register the joystick to the queue 88 al_register_event_source(event_queue, al_get_timer_event_source(_timer)); 89 al_register_event_source(event_queue, al_get_keyboard_event_source()); // Registers the keyboard to the queue 90 al_register_event_source(event_queue, al_get_mouse_event_source()); // Registers the mouse to the queue 91 al_register_event_source(event_queue, al_get_display_event_source(_display)); 92 93 ALLEGRO_JOYSTICK_STATE joy_state; 94 95 al_flip_display(); 96 97 al_start_timer(_timer); // Start the timer 98 99 Input _input; 100 101 _input.set_Up_Controllers(); 102 103 while (true) 104 { 105 al_wait_for_event(event_queue, &events); 106 107 if (_input.get_How_Many_Controllers() != 0) 108 { 109 al_get_joystick_state(_input.get_Joystick(0), &joy_state); 110 //_input.update_Controller_Input(events, joy_state); 111 } 112 113 _input.update_Keyboard_Input(events); 114 115 if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN) 116 { 117 printf("BUtton was pressed\n"); 118 } 119 else if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_UP) 120 { 121 printf("Button was released\n"); 122 } 123 124 125 126 if (events.type == ALLEGRO_EVENT_TIMER) 127 { 128 if (_input.was_Key_Pressed(KEYCODE_A) == true && _input.was_Key_Pressed(KEYCODE_B) == true) 129 { 130 break; 131 } 132 } 133 134 _input.resync_Controllers(); 135 136 137 } 138 139 return 0; 140}

bamccaig
Member #7,536
July 2006
avatar

We likely need to see the code for _input to understand what's going on here.. I don't see anything with the Allegro code that would explain this.

Append:

Correction. I wonder if repeatedly calling al_get_joystick_state every event is the culprit. I'm not familiar with the joystick API, but since that isn't event-based I bet you're using the slow method to get that data and I wouldn't be surprised if that was lagging you.

Eric Johnson
Member #14,841
January 2013
avatar

I'm glad my example worked for you. As for your code, nothing immediately jumps out at, though I'm not too sure about your use of al_get_joystick_state. I'm not too well-versed on the joystick API though, and I'm not sure what you're doing inside of the Input class either.

Why are you calling al_get_joystick_state every cycle? Try moving it just before the while-loop and see if that changes anything.

TripleG
Member #16,431
July 2016

I am calling al_get_joystick_state to determine which controller is making the input but I plan on removing it because I could just use events.joystick.id to determine which controller made that action but here is the code for the input class. I did comment it out to see if that made the difference but it did not.

I have just found the problem. It is the re-sync-controller function call. Since that was the other thing that stuck out that was different with the working code. When I comment it out their is no longer any delay.

#SelectExpand
1void Input::set_Up_Controllers() 2{ 3 if (al_get_num_joysticks() > 0) 4 { 5 using_Controllers = true; 6 how_many_controllers = al_get_num_joysticks(); 7 8 for (int i = 0; i < how_many_controllers; i++) 9 { 10 joysticks[i] = al_get_joystick(i); 11 } 12 } 13} 14 15void Input::resync_Controllers() 16{ 17 if (al_reconfigure_joysticks() == true) 18 { 19 set_Up_Controllers(); 20 } 21 22} 23 24ALLEGRO_JOYSTICK* Input::get_Joystick(int controller) 25{ 26 return joysticks[controller]; 27} 28 29void Input::update_Keyboard_Input(ALLEGRO_EVENT &events) 30{ 31 if (events.type == ALLEGRO_EVENT_KEY_DOWN) // If a key was pressed on the keyboard 32 { 33 keyDownEvent(events); 34 printf("Keycode %d\n", events.keyboard.keycode); 35 } 36 else if (events.type == ALLEGRO_EVENT_KEY_UP) 37 { 38 keyUpEvent(events); 39 } 40} 41 42void Input::keyDownEvent(const ALLEGRO_EVENT& events) 43{ 44 pressed_keys[events.keyboard.keycode] = true; 45 released_keys[events.keyboard.keycode] = false; 46} 47 48void Input::keyUpEvent(const ALLEGRO_EVENT& events) 49{ 50 pressed_keys[events.keyboard.keycode] = true; 51 released_keys[events.keyboard.keycode] = false; 52} 53 54void Input::clear_Keyboard_Input() 55{ 56 released_keys.clear(); 57 pressed_keys.clear(); 58} 59 60void Input::update_Controller_Input(ALLEGRO_EVENT &events, ALLEGRO_JOYSTICK_STATE state) 61{ 62 if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN) 63 { 64 pressed_buttons[match_Controller(events, state)].insert(std::pair<int, bool>(events.joystick.button, true)); 65 released_buttons[match_Controller(events, state)].insert(std::pair<int, bool>(events.joystick.button, false)); 66 } 67 else if (events.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_UP) 68 { 69 pressed_buttons[match_Controller(events, state)].insert(std::pair<int, bool>(events.joystick.button, false)); 70 released_buttons[match_Controller(events, state)].insert(std::pair<int, bool>(events.joystick.button, true)); 71 } 72 else if (events.type == ALLEGRO_EVENT_JOYSTICK_AXIS) 73 { 74 75 } 76} 77 78// Only call this when you know an input has been made by the controller 79int Input::match_Controller(ALLEGRO_EVENT &events, ALLEGRO_JOYSTICK_STATE) 80{ 81 for (int i = 0; i < how_many_controllers; i++) // Checks to see which controller made the input 82 { 83 if (events.joystick.id == joysticks[i]) 84 { 85 return i; 86 } 87 } 88 return -1; 89} 90 91void Input::clear_Controller_Input(int controller) 92{ 93 pressed_buttons[controller].clear(); 94 released_buttons[controller].clear(); 95} 96 97// Taken from the input.h 98private: 99 bool using_Controllers; // Is the user using a controller 100 int how_many_controllers; // How many controllers are being used in the program 101 102 ALLEGRO_JOYSTICK *joysticks[4]; 103 104 /* 105 * Used to store keyboard input 106 */ 107 std::map<int, bool> pressed_keys; 108 std::map<int, bool> released_keys; 109 110 /* 111 * Used to store controller input 112 */ 113 std::map<int, bool> pressed_buttons[4]; 114 std::map<int, bool> released_buttons[4];

bamccaig
Member #7,536
July 2006
avatar

Probably you should check first if Allegro sends any events when "joysticks" / "controllers" are plugged in or unplugged. If so then you'll know more accurately when you should try to re-detect them. Worst case, limit your polls to every few seconds. That will be hundreds of frames probably and you can probably afford a bit of waste if you only do it so often. Again, that's without any knowledge of Allegro's joystick/controller APIs. But I would bank on there being events to do this most efficiently.

Append:

The documentation for al_reconfigure_joysticks says Allegro will send an event when devices change and only then should you call al_reconfigure_joysticks(). Calling it every loop is probably super inefficient because Allegro is probably doing lots of unnecessary work to figure out what changed when nothing has.

TripleG
Member #16,431
July 2016

Your absolutely right I just looked at the api and found ALLEGRO_EVENT_JOYSTICK_CONFIGURATION which lets me know if a controller has been disconected or reconnected. That is when I should call al_reconfigure_joystick instead of calling it all the time like I did.

Thank you all so much!!!

;D

Go to: