Tuesday, January 14, 2014

Input System Update 2

Hello Again,

I've been working more on our input system and now I'm almost done coding the Gesture Interpreter, functionality-wise, for simple controllers (digital buttons). It will be enough for keyboards and some gamepads. Next step will be polishing, testing and getting rid of all bugs and leaks that certainly are hidden in there. When I am done with this, I'll then move to creating an specialized interpreter for mouse and one for gamepads with thumbsticks.

Like this one.

As of now, the GestureInterpreter has only one working approach, Callbacks. Since it is the most common, and I find it easier to program and test, I decided to add it before the other two: Messaging and the Polling systems. But don't worry, I'm going to implement them as well eventually (Valve time? oh boy, you know nothing).

Overview

The system is simple. You have a GestureInterpreter that receives events from a Controller and translates its keys into internal game codes by using a KeyTranslator. Once translated, the GestureInterpreter compares the last received inputs with all Patterns you created by serializing BasicInputs such as " 'Space' Key Down" or " 'W' Key Up"; and, if it finds a match, it calls that Pattern's registered Callback. Pretty simple isn't it?

The system was designed to stop comparing patterns as soon as it finds a match, but can easily be changed to always compare with every pattern and call all callbacks. I decided to stop at the first match so you know that it will only call a single callback for a single input event.

"Why?", you ask me. Let me illustrate the situation with a simple example: imagine an old-school fighting game. One of the buttons, say 'A', is responsible for the 'punch' action, but the sequence " ↓↘→ A " is responsible for an 'uppercut' action. In addition, the other sequence " ←↙↓↘→ A " unleashes an even stronger 'special attack' action. Notice how all three patterns end with an input event of " 'A' Key Down". If the player presses the correct sequence for the special attack, the GestureInterpreter would then call all three callback functions, for the punch, the uppercut and the special attack.

Moving on, the code basically calls a return true; when it gets the first match. That means we will only call the "higher" pattern's callback function, instead of all three. However, changing this is as simple as moving the return statement to outside the comparison loop and make it return a variable that stores if there was a pattern match or not. This is the function:



The problem with this approach is that it forces us to manually call the updateStep() method until it returns false. Under normal circumstances, it will be one single call, but if we have an special type of controller (say, a gamepad with autofire) or a really (i mean, really) fast tapper playing, it might be a problem. This input system is intended to be initialized and configured once, and then all you need to do is to call the updateStep() function on your interpreter until it is satisfied; it will call all your callbacks with no need for any further steps. Or you can simply call update() once if you don't need the value updateStep() returns.

As of now, the memory cycle is complete. All created events should be deleted on the GestureInterpreter (or by their creators, if the creator's dtor is called before the event got checked out).

This version of the code is an earth field, sometimes you can find some earth between the mines! I haven't made a single test, since I am lazy. But will do; tomorrow.

If you are crazy enough, download it!

Over and Out.