21
\$\begingroup\$

I'm developing a game using polling for the input method. However, now that I'm delving deeper into the game menus and other UI components, I'm finding that I'd probably like to have event driven input. Perhaps even having both, using event driven for the UI and polling for the "world" input. I'm curious on what the best way to go is.

I'm defining polling as: each update loop I check what keys are press, where the mouse is, buttons pressed, then run through them and do actions based on the info collected.

I'm defining event driven as: interrupt based events, when an event happens and interrupt is triggered and a code block is run based on the event.

Do you think it's best to go all event driven, all polling, or is a combination of both acceptable? If you have pros and cons for either please list them. Thanks.

EDIT

The game is Java/OpenGL based, so will be released to Windows/Mac/Linux. The possibility of extending that to mobile devices is low. The game is RTS style, 3rd person 3D.

EDIT 2

I'm still not totally happy with the way I've implemented this, but what I'm moving toward is catching events in my UI and if they're not handled by any of my UI components, I pass the event on to the "World" for picking/selection. Something like:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

This way I don't get clicks leaking through the UI to select objects behind buttons and what not.

Currently my camera controls are still based on polling, and that seems to be working for now, but I may update that later on.

I appreciate all the answers, sorry I could only pick one!

\$\endgroup\$
2
  • 6
    \$\begingroup\$ I am not sure in Java, but in general you always have to poll input. You might then post events when things change, but this is still based off of a polling system. \$\endgroup\$
    – James
    May 10, 2011 at 18:33
  • \$\begingroup\$ The most relevant point of focus in my opinion is to design an event loop that is free of any other layload than input collection. Let me explain: the operating system will do the input driven interruption and treat it in the global "input thread", then this OS-thread will redirect messages into currently in-focus application and write the intel into its message queue. The message queue has to be polled by PeekMessage, or GetMessage. The fastest way to get this is to use GetMessage and let the scheduler wake you up, you can then timestamp the message very precisely. \$\endgroup\$
    – v.oddou
    Sep 5, 2014 at 3:37

3 Answers 3

19
\$\begingroup\$

It depends on the requirements of your game and hardware. Most games are usually interested in changes to input state, i.e. user presses the fire key and their weapon starts firing, user releases the fire key and their weapon stops firing, user presses the move key and starts moving, releases the move key and stops moving, etc., so an event-driven input system makes the most sense in those cases since the information is already in a suitable format. Plus on the Windows platform, you already receive events for changes to keyboard and mouse state, so it's often a 1:1 conversion from low-level input events to high-level game events. With polling, you'll often find yourself having to generate such events manually by comparing state between the current and last frame. Basically, "which buttons are pressed now?" tends to be far less useful information than "which buttons have been pressed/released this frame?", and given an initial keyboard/mouse state when you initialize your input subsystem, the former can be inferred from the latter anyway for those cases when you need it.

That being said, on certain platforms you're stuck with polling input at a low-level and there's no way around doing the edge checking yourself. However, I've always achieved the best results using events for all high-level logic since that's naturally how those systems tend to operate.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks, I've included additional information about the game's platform and purpose. \$\endgroup\$
    – House
    May 10, 2011 at 18:26
  • 1
    \$\begingroup\$ Note that GetAsyncKeyState is a simple way to use polling on Win32. \$\endgroup\$
    – Macke
    May 10, 2011 at 21:14
  • \$\begingroup\$ Derp, I asked a question in Nate Bross' comments that you deal with here, so I guess I'll refine it. Do all PCs offer that 1:1 hardware interrupt to OS keyboard event relationship, and what kind of platforms are limited to low-level polling? \$\endgroup\$ May 10, 2011 at 22:16
  • \$\begingroup\$ @Macke : sometimes antivirus reports programs that use this API because they can receive key-press from the whole global system, thus enabling malicious keylogging. The most awesome article about it on the whole internet (I know of) is this one: securelist.com/analysis/publications/36358/… \$\endgroup\$
    – v.oddou
    Sep 5, 2014 at 3:34
9
\$\begingroup\$

I see no reason that you cannot do both, and get the best of both worlds.

Input Events are generated by polling (at some level the driver polls the hardware to see what state its in), and since your main loop polls all input devices, you can easily implement your own. Something simple like below is what I've used in the past.

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

I know that you defined events to be interrupts and what I've put here is not "truely event based", but I don't see what the above doesn't give you that interrupts do give you -- most users will not notice the single frame lost, unless your game runs at very low frame rate.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I'm curious about the nature of getting input from devices. Are keyboard events dispatched by the OS the result of polling at the device driver level? Or does a keyboard event correspond with an interrupt? Or are there interrupts, but the OS buffers them and dispatches them when it sees fit? \$\endgroup\$ May 10, 2011 at 22:13
  • 1
    \$\begingroup\$ I am not positive on how it works at that level, but it's most basic, some software runs in a loop and checks the keyboard state and compares it to the previous state, if its changed the change gets bubbled up. \$\endgroup\$
    – Nate
    May 10, 2011 at 22:23
7
\$\begingroup\$

There are two different issues here:

  1. How do you read user input from the OS/hardware?

  2. How do you process user input in your engine?

For reading, it clearly depends on your platform, and what kind of input you want to read. Note that it's easy to convert one thing to another in your input layer. (I.e. poll and emit events to the engine, or listen to events and emit state to the engine.)

For processing, there are a few different options:

  • For player movement control (and similar schemes), polling might be simpler as you need to recompute speed each frame. It's very likely that your inner loop will be polling based:

    i.e. something like speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • For discrete events (fire missile, pause game, teleport to other side of planet), event processing is preferrable, otherwise your code will be littered with maybeLaunchMissile(key_state); calls, and that's just ... bad, m'kay. ;)

Hope it helps.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .