Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Seriously severe input delay on AL5.0.10

This thread is locked; no one can reply to it. rss feed Print
Seriously severe input delay on AL5.0.10
Maurício Gomes
Member #15,461
January 2014

I made this sample program that demonstrates that Allegro has some serious input delay, I tested it on Windows (no other OS nearby now, sorry :( )

You can play "normally" and you will notice that the controls are not tight as they should (for a action game at least), but you can REALLY see the effect if you just press arrow keys in random directions as fast as you can (like if you was making a fighting game input), and then just watch the screen, the longer you made your "combo", the longer the ship will move on its own.

EDIT: Fixed a bug in the example code that Elias noticed.

#SelectExpand
1//libraries 2#include <stdio.h> 3#include <allegro5/allegro.h> 4#include <allegro5/allegro_primitives.h> 5 6//project headers 7#include "gamelogic.h" 8 9const int PLAYFIELD_W = 1280; 10const int PLAYFIELD_H = 720; 11#define UPDATE_TIME 1.0/125 //1 second divided by 125 frames per second, this is to guarantee a round milisecond speed 12 13ALLEGRO_KEYBOARD_STATE keyboardState; 14 15int main() 16{ 17 ALLEGRO_MONITOR_INFO monitorInformation; 18 ALLEGRO_DISPLAY *display; 19 ALLEGRO_EVENT_QUEUE *events; 20 ALLEGRO_TIMER *updateTimer; 21 int screenWidth; 22 int screenHeight; 23 int counter; 24 25 //////////////////////////// 26 //Setup phase starts here // 27 //////////////////////////// 28 if(!al_init()) 29 { 30 fprintf(stderr, "Failure loading Allegro\n"); //should not happen, but who knows... 31 return 1; 32 } 33 34 //now we create our display 35 counter = 0; 36 while(al_get_monitor_info(counter, &monitorInformation)) //this function returns false when it fails 37 { 38 if(monitorInformation.x1 == 0 && monitorInformation.x2 != 0) break; //we found what we wanted 39 ++counter; 40 } 41 42 screenWidth = monitorInformation.x2 - monitorInformation.x1; 43 screenHeight = monitorInformation.y2 - monitorInformation.y1; 44 45 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 46 al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST); 47 display = al_create_display(screenWidth, screenHeight); 48 if(!display) 49 { 50 fprintf(stderr, "Failure setting up the display\n"); 51 return 2; 52 } 53 54 if(!al_install_keyboard()) 55 { 56 fprintf(stderr, "Failure installing keyboard\n"); 57 al_destroy_display(display); 58 return 3; 59 } 60 61 if(!al_init_primitives_addon()) 62 { 63 fprintf(stderr, "Failure loading primitives addon\n"); 64 al_destroy_display(display); 65 return 4; 66 } 67 68 updateTimer = al_create_timer(UPDATE_TIME); 69 70 events = al_create_event_queue(); 71 if(!events) 72 { 73 fprintf(stderr, "Somehow there was a failure creating a event queue, this really should not have happened\n"); 74 al_destroy_display(display); 75 return 5; 76 } 77 78 al_register_event_source(events, al_get_display_event_source(display)); 79 al_register_event_source(events, al_get_timer_event_source(updateTimer)); 80 81 /////////////////////////// 82 //Setup phase ended here // 83 /////////////////////////// 84 85 al_start_timer(updateTimer); 86 87 double playerX = 20.0; 88 double playerY = (double)PLAYFIELD_H/2.0; 89 90 bool redraw = false; 91 92 while(true) 93 { 94 static ALLEGRO_EVENT event; 95 al_wait_for_event(events, &event); 96 97 if(event.type == ALLEGRO_EVENT_TIMER) 98 { 99 //updateGame(); 100 al_get_keyboard_state(&keyboardState); 101 if(al_key_down(&keyboardState, ALLEGRO_KEY_DOWN)) 102 { 103 playerY+=10; 104 } 105 if(al_key_down(&keyboardState, ALLEGRO_KEY_UP)) 106 { 107 playerY+=-10; 108 } 109 if(al_key_down(&keyboardState, ALLEGRO_KEY_LEFT)) 110 { 111 playerX+=-10; 112 } 113 if(al_key_down(&keyboardState, ALLEGRO_KEY_RIGHT)) 114 { 115 playerX+=10; 116 } 117 redraw = true; 118 } 119 else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 120 { 121 break; 122 } 123 124 if(redraw && al_is_event_queue_empty(events)) 125 { 126 redraw = false; 127 al_clear_to_color(al_map_rgb(0,0,0)); 128 al_draw_filled_triangle(playerX-10, playerY-10, playerX+10, playerY, playerX-10, playerY+10, al_map_rgb(255, 255, 255)); 129 al_flip_display(); 130 } 131 } 132 133 134 printf("hello world!\n"); 135 136 137 /////////////////////////////// 138 // Cleanup phase starts here // 139 /////////////////////////////// 140 al_destroy_timer(updateTimer); 141 al_destroy_event_queue(events); 142 al_destroy_display(display); 143 return 0; 144}

Bruce Perry
Member #270
April 2000

You should put brackets around the value of UPDATE_TIME, just in case it ever trips you up.

As for the delay problem, what happens if you attach the keyboard event source to that event queue? (Obviously your existing code would ignore the new events you get, but I wonder if it will cause some voodoo changes inside Allegro.)

--
Bruce "entheh" Perry [ Web site | DUMB | Set Up Us The Bomb !!! | Balls ]
Programming should be fun. That's why I hate C and C++.
The brxybrytl has you.

pkrcel
Member #14,001
February 2012

I THINK that with your code you're only checking for input change every time your timer fires up an event, so you're processing only the last event in the Keyboard state when this happens and not the Keyboard events themselves.

So basically, what Bruce said....changing your code accordingly.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

Maurício Gomes
Member #15,461
January 2014

pkrcel that was my intention all along.

But what I got to see instead is a accumulation of keyboard input, that keeps acting on the game even after you let them go.

Source delving by me and others suggest that is because of misuse of WinAPI, for example every time a key is pressed it calls GetKeyboardState, plus GetKeyState three times. And in WinAPI itself it alread warns that those functions have delays.

SiegeLord
Member #7,827
October 2006
avatar

I have reproduced this delay on my system, and it stems from some odd design choices in the D3D backend as well as keyboard handling. I have created a proof-of-concept set of changes to both to try to eliminate this lag as much as possible. It requires a lot more testing before I feel comfortable committing it to Allegro proper.

That said, attached is a version of the program in the OP with the changed Allegro alongside it, as well as the patch to Allegro (relative to 5.1) just so you can see what I did. I'm not sure it can get much better than that, but even going as far as I did has basically eliminated the lag for me. See if it does so on your system as well.

EDIT:

I should note, when you run speeder.exe you can pass in any argument to cause it to launch in fullscreen, if you want. Also, the allegro5.cfg alongside it can be used to force it into OpenGL mode.

EDIT2:

The diff wasn't quite right. Fixed it.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Maurício Gomes
Member #15,461
January 2014

SiegeLord whatever you did, it worked here. I think I don't see any delay on this test exe

pkrcel
Member #14,001
February 2012

pkrcel that was my intention all along.

Yeah, now that I took more time to look at it, I understand the underlying desing...I misunderstood your description of the problem.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

Elias
Member #358
May 2000

I like the patch, also the UNICODE part. I think this also will fix http://sourceforge.net/p/alleg/bugs/376/ - for example al_set_window_title will work under Windows when the string contains non-ASCII letters.

--
"Either help out or stop whining" - Evert

SiegeLord
Member #7,827
October 2006
avatar

Ok, so fixing the keyboard is turning out to be very difficult. The issue is that Allegro emits ALLEGRO_EVENT_CHAR for both printable characters and for other keys. The "proper" and fast way of handling input on Windows uses WM_CHAR to do the unicode characters... unfortunately Windows only sends WM_CHAR for printable characters, e.g. it won't send them for arrow keys and other such non-character keys. It is turning out to be very hard to not send superfluous ALLEGRO_EVENT_CHAR events. E.g. if you use the US-international keyboard you can press Shift+6 followed by an e to get an ê. Using WM_CHAR and my best attempt you will get an extra ALLEGRO_EVENT_CHAR when you do the Shift+6.

Anyway, the keyboard wasn't really the major component of this delay, rather it was the display loss checking code. Attached is the patch and binaries of the code that only fixes that (and enables unicode along the way). Please check it to see if it has appreciable input lag (maybe compare it with the binary in my earlier post).

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Elias
Member #358
May 2000

Does ALLEGRO_EVENT_CHAR work correctly for shift+6+e right now?

--
"Either help out or stop whining" - Evert

SiegeLord
Member #7,827
October 2006
avatar

Yes. The only issue with the current approach is that it is supposedly laggy (I think I can perceive it, but it's hard to tell) and I also noted that it doesn't work with IME... i.e. if you try to enter Chinese characters using IME, the little IME window won't show up (I haven't determined what part of my work handles the IME window... if it's just TranslateMessage, then I could put it in without actually handling WM_CHAR's).

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Maurício Gomes
Member #15,461
January 2014

Great work SiegeLord :)

The lag is not random anymore (random lag is TERRIBLE) and is now 1 frame.

Not zero yet... but good enough for most games and players I guess.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

SiegeLord
Member #7,827
October 2006
avatar

Just perceptually. I guess I could look at the original timestamp of the MSG structure and compare it to when we emit the Allegro event.

EDIT: I tried it with this code: printf("Lag %ld\n", GetTickCount() - GetMessageTime()); at the spot where the keyboard events are emitted, and it showed a reduction from as much as 400 ms to 0 ms with an occasional 16 ms.

EDIT2: Committed the above patch.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Go to: