Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Event Driven VS. Polled Input

This thread is locked; no one can reply to it. rss feed Print
Event Driven VS. Polled Input
NyanKoneko
Member #5,617
March 2005
avatar

The other day, I wrote a short tutorial that showed how to save keyboard states to get input. Sort of like the allegro "key[KEY_L]" methood of polling for input. My good friend RuneLancer said it's a necessity to use event-driven input in games since you can grab multiple keyboard events while drawing a frame at 5 FPS (like if you're in the middle of taking a screen shot).

My response was that it's just a personal choice and not a necessity, since event based input can increase code complexity, but I want your opinions.

Marco Radaelli
Member #3,028
December 2002
avatar

If I'm getting it right, I think the comparison is a bit wrong.

There's event-driven software (like Word and such productivity software), where the program waits for your input, elaborate a response on that input and then waits again (for another input) and time-driven software (like games) where the program keeps elaborating data and some extra elaboration if you enter inputs.

So, in the first place noting happens if you don't do anything, while in the latter events do happen and your opportunity is to change their destiny.

Alternatively, you can compare instant-taken input versus buffered input.

In the first case you read the input and elaborate (almost) immediately that just-read data; the point is that if there are multiple inputs arriving subsequently you just read the one which arrives when you issue a read instruction (so if the user presses 'a' five times and your program has an instruction 'read_a()' the data will be read only if the user presses that key when the instruction is executed, losing all the other keypresses).

In the second case you store somewhere the inputs and process them in the order they arrived, no matter what the user actually is entering at a certain time. In this option you do not loose any input.

In my opinion, buffered input goes well with event-driven software, where the application works 'ignoring' the time. When comes to time-driven software, instant-taken input is the only option, because the user makes keypresses reacting to what it sees on screen, which directly depends on the time of execution.

So if your software takes too much time elaborating on a keypress and you're buffering the other keypresses, the user will keep entering input while not seeing a direct change in what is on screen.

This happened in, IIRC, some FIFA games in the last years, where while playing I pressed the 'pass' button while the character didn't control the ball, then, after one or two seconds he got the ball. In this second time my intention is almost surely changed due to the new situation (an enemy being closer than before) so I probably want to make a different move, but, because the game was buffering my input, no matter if I wanted to change direction, my character passed the ball.

I hope I got the point :)

A J
Member #3,025
December 2002
avatar

Are you Event Driven or Polled Input ?

___________________________
The more you talk, the more AJ is right. - ML

Marco Radaelli
Member #3,028
December 2002
avatar

After my previous post, I think that's not a proper question.
Please reformulate :P

NyanKoneko
Member #5,617
March 2005
avatar

I'll explain the two methods in more detail... But your post makes perfect sense in relation to the question I asked above. :)

In windows, your program can be set up to accept input through event queues. So the program will be told that the user pressed key W, or that the user released the Space Bar. You can also tie these into interupts, so each time a player presses a key, the program stops and calls the input-handling function. This is event-driven input handling. :)

Polling, on the hand, routinely checks the state of the keyboard (which keys are up, and which are down). For example, in Allegro, if I wanted to check if the W key is held down, I'd type if(key[KEY_W]).

The question is, "Is using event driven input handling necessary in modern games?" Certainly it makes typing easier if you have such a process in your game, but is it a bad coding practice to poll keyboard, mouse, or joystick states?

Thomas Harte
Member #33
April 2000
avatar

Quote:

My response was that it's just a personal choice and not a necessity, since event based input can increase code complexity, but I want your opinions.

I agree that it is personal choice. But beyond your observations, having an event driven messaging system at the core of your app can also decrease code complexity. For example, if you can receive application quit requests and attach a timer to your event queue for properly timed CPU reducing sleep then you've probably saved complexity over a pure polled method. You've also probably increased the amount of time you can sleep for.

It also depends what you want to do with your input. Supposing you have a move that is triggered by a double tap (e.g. running in Golden Axe or Streets of Rage), then if you had time stamped events coming in the implementation of that would be comparitively trivial. Ditto if you want to do something that requires sequences of keystrokes with well defined timings (e.g. Street Fighter 2 or any of the 1,000,000 other games like that). You also obviously simplify the task of detecting changes in state rather than just current state, which is useful for some games (e.g. steering out of a spin in Road Fighter).

Conversely, if you just want an Allegro-style key array then you've obviously complicated things. Not by much, but you could say the same about simulating an event driven input system with only a state array.

If I were designing a brand new cross-platform game API, I would probably go for events with timestamps because the reality of implementation on most modern OSs is that many input devices are event based and the timestamp information is easy to collate with a thread that just perpetually waits on new input then reformats the OS specific messages into the platform neutral form. Timestamps are inevitably artificial for devices that are inherently polling based (e.g. analogue joysticks), but without an event based input queue there is no way to keep the timestamp information where it can be determined reasonably well.

I believe new-API Allegro features a proper input queue as well as a simple state query interface. SDL already does the same. Alas I don't think either have timestamping.

Birdeeoh
Member #6,862
February 2006
avatar

I'm currently implementing a game GUI system based on OpenLayer. For any remotely modern windowing system, event based input is a must. Event queues can have sticky implementation details themselves, as I'm discovering, but on top of the queue having event-based input is very de-complicating.

Thomas Harte made some really strong points in his post, but I'll expand on it a bit and say even without timestamps, queued input is extremely valuable. For example in my event queue, I know if the mouse was moved first then the button clicked, versus the button clicked then the mouse moved. If I were doing poll-based input, I would have no idea which order these events occured in and therefore could incorrectly attribute a click to a window, or a window that got a click would miss out on it.

But outside of the realms of straight GUI and therefore turn-based games, I agree with everything Thomas Harte said. And event queue is EASIER to handle programatically if you structure your code right, and you get more information from it allowing simpler implementation of more complex ideas :)

[url http://developer.berlios.de/projects/openlayer/]OpenLayer[/url is an OpenGL accelerated 2D library for fast and easy graphics development under Allegro

Rick
Member #3,572
June 2003
avatar

As I agree with everything they said about event driven, it really does require your code to be structure differently. That is you have to put more thought into the structure when using event driven. Obviously these events are changing some data. So that means they need access to this data to change. The same event could mean many different things based on what state your game is in. So you have to take that into consideration. So unless you make everything global, and have a bunch of switch statements on the game state in each event method, it requires some solid structure.

Unless I'm missing something, either you add the complexity of how to structure your code upfront when using event driven, or you get it inside your code, when not.

========================================================
Actually I think I'm a tad ugly, but some women disagree, mostly Asians for some reason.

Marco Radaelli
Member #3,028
December 2002
avatar

(I'm sorry, mine are just thoughts, I have no experience on them)

Now I think I got your point, NyanKoneko.

But can't event-driven input 'derail' the program, causing changes when your code isn't ready to get them? What if there's a complex process being activated by a keypress and then, in the middle of it, another keypress changes the state of the object, making the result inconsistent, because part of it was done with certain data, and the second part was elaborated with different data?

Talking about GUIs I agree that an event based input is the best solution.
But with games, what if a user presses just too many times? Couldn't that be a problem? And let's think about an FPS (a la Doom) in which to go forward one would keep pressing the up-key? Or that would result just in a keydown and one keyup?

I do see anyway the value of having a queue of inputs, for example to detect special moves.

Carrus85
Member #2,633
August 2002
avatar

Quote:

But can't event-driven input 'derail' the program, causing changes when your code isn't ready to get them? What if there's a complex process being activated by a keypress and then, in the middle of it, another keypress changes the state of the object, making the result inconsistent, because part of it was done with certain data, and the second part was elaborated with different data?

There is a reason they have locking mechanisms in threaded enviroments, you know... Lock the resource while you are using it and unlock it when you are done if anyone else can use the selected resource. This way, only one person can alter a given item at a time (which, in effect, reduces your program to a single threaded application temporarily (sorta)). This prevents someone else coming along and giving you an inconsistant state, because for the time being you are the only thing allowed to even interact with a particular chunk of data.

Birdeeoh
Member #6,862
February 2006
avatar

But can't event-driven input 'derail' the program, causing changes when your code isn't ready to get them? What if there's a complex process being activated by a keypress and then, in the middle of it, another keypress changes the state of the object, making the result inconsistent, because part of it was done with certain data, and the second part was elaborated with different data?

This is why theres the concept of the event queue. The first keypress goes on the event queue, the object starts processing the keypress, and while the object is processing the keypress, another keypress is placed on the event queue.

After the object finishes processing the first keypress, it begins processing the second keypress.

In that way you can look at the keyboard buffer as an "event queue for key presses", and calling "readkey()" gets you the next event. But in a real world system, everything goes on the queue - key presses, mouse actions, software generated events... everything.

The key to the whole thing is that events are processed serially - 1 after another - and therefore EVERY event is handled in the order received, in contrast to a mismatch of state flags where, depending on the granularity of your timing, many things can be missed.

[url http://developer.berlios.de/projects/openlayer/]OpenLayer[/url is an OpenGL accelerated 2D library for fast and easy graphics development under Allegro

Marco Radaelli
Member #3,028
December 2002
avatar

Carrus85 said:

There is a reason they have locking mechanisms in threaded enviroments, you know...

I know, but I thought we were talking about making coding easier...

Birdeeoh said:

The key to the whole thing is that events are processed serially - 1 after another - and therefore EVERY event is handled in the order received

I see it, but I still think that that would add some 'false' separation from the actual user input (what he wants to do depending on what he sees on screen) and the data actually processed, won't it?

This thinking about processing an event at each frame, or are we talking about emptying the whole queue before proceeding to the next frame?

Thomas Harte
Member #33
April 2000
avatar

Quote:

This thinking about processing an event at each frame, or are we talking about emptying the whole queue before proceeding to the next frame?

Yep. Typically where you could handle input by checking key states you just process all the stack messages in turn until there are none left. Ordinarily if there are no messages then you don't wait for any.

If the queue were restricted to just keyboard input then the user should be unable to tell the difference from a polling method for most games. But the extra information can be helpful as stated above, even if you're just at the level Birdeeoh mentions of being able to use the queue to determine the order of events without anything like time stamping. Then even if your FPS drops to 20 you can still tell down->down right->right->punch all done in 50ms from down->punch done in 50ms.

Marco Radaelli
Member #3,028
December 2002
avatar

Thomas Harte said:

Typically where you could handle input by checking key states you just process all the stack messages in turn until there are none left.

But how to determine if there's no more input? I do see, though, that the speed of input is far less than the speed of processing...

Well, after all looks like event-driven is better than polling...

Thomas Harte
Member #33
April 2000
avatar

Quote:

But how to determine if there's no more input?

You poll the event queue until there is nothing left on it! Example SDL code:

1SDL_Event NewEvent;
2while(SDL_PollEvent(&NewEvent))
3{
4 switch(NewEvent.type)
5 {
6 case SDL_QUIT: Quit = true; return;
7 case SDL_VIDEORESIZE:
8 /* user wants window resized to NewEvent.resize.w, NewEvent.resize.h */
9 break;
10 case SDL_MOUSEBUTTONDOWN:
11 switch(NewEvent.button.button)
12 {
13 case SDL_BUTTON_WHEELUP: MouseScroll--; break;
14 case SDL_BUTTON_WHEELDOWN: MouseScroll++; break;
15 }
16 break;
17 default: break;
18 }
19}
Quote:

Well, after all looks like event-driven is better than polling...

It doesn't really have any advantages if the information about event ordering isn't interesting for you and you have different methods of getting all the other information. If you are just writing PacMan, why do you care if the user pushed left inbetween moving from down to up?

Allegro makes a slight hash of it in my opinion with set_close_button_callback, and doesn't have any way of opening up window resizing possibilities, but a specific implementation shouldn't be used to sully the name of poll based input forever!

Marco Radaelli
Member #3,028
December 2002
avatar

Quote:

You poll the event queue until there is nothing left on it!

What I was thinking was what if the player keeps pressing keys...

Anyway, it's all clearer now :)

Birdeeoh
Member #6,862
February 2006
avatar

It seems alot of your questions were answered since my last post but it wasn't explicitly said so I'll go ahead and say it -

"Emptying out the event queue" should be a VERY quick operation. If the only things going to the event queue are key presses and mouse events, you should be able to clear the queue out in mere microseconds.

To put it another way, the time spent clearing out the event queue is VERY small compared to doing anything graphical or other game-logic based :)

[url http://developer.berlios.de/projects/openlayer/]OpenLayer[/url is an OpenGL accelerated 2D library for fast and easy graphics development under Allegro

axilmar
Member #1,204
April 2001

I do not know if it has been said, but event-driven input comes in two flavors: blocking and non-blocking. In games, non-blocking event-driven input is better, since the code to check for keys pressed, mouse clicks etc is intergrated with the update loop. In apps that there is no update loop, the program should block while there is no event, in order to decrease the CPU load.

In any case, event-driven input is better than polling, because with polling one might loose critical events. For example, If I press up and release it almost instantly and my character does not go up, users of my game will complain.

Go to: