Some of the stuff I've added

3 views
Skip to first unread message

Zach Conn

unread,
Mar 6, 2009, 12:43:54 AM3/6/09
to Mizzou Game Design
Well, I realized that it may not be entirely clear how to use some of
the stuff I've added. I thought I'd write something better explaining
how it works here.

The class was an attempt to do the input handler ticket. These were
the goals:

1) Make it event-based so that code can respond to general input
events, not specific key presses/releases; i.e., code could respond to
the event that the player hit the "jump" button without being tied to
whatever button specifically is mapped to jump.

2) Make it general enough that it can be used in all the different
game states. In different states, the same key or mouse button may do
different things. In-game space might jump, but in a menu it might
select the highlighted menu item.

3) Make it load the bindings between specific keys and general input
events from a JSON file.

4) Allow multiple keys to map to the same event; for example, in the
menu you should perhaps be able to select an item either by left-
clicking on it or by hitting enter.

In its current state, it does all four of these. To accomplish (1), it
uses Boost.Signals. To accomplish (2), it uses the idea of input
contexts. To accomplish (3), it uses JSONFile. And to accomplish (4),
well, that's just an implementation detail.

First, there is the mysterious file ButtonGosuValueTable.hpp. The
trick used here was inspired by something I saw in the Angel game
library. This is a very simple way to map the enumeration values in
Gosu representing keys and mouse buttons to strings. The strings are
used in specify keys/mouse buttons in the JSON file. If you need to
add support for a new key, it's as simple as adding a new line to that
file and looking up the Gosu enumeration value for the key. The actual
macro is defined in both InputManager.hpp and InputManager.cpp; in
each place it's given a different definition.

Right now the JSON file (commandBindings.json) looks like this:

{
"Menu" :
{
"Quit" : "Escape",
"Select" : ["Return", "LeftMouse"]
}
}

This is just a random test I put together.

The structure of this is simple. The "Menu" object represents an input
context. The input manager always operates within a certain context,
which can be changed simply by using InputManager::setCurrentContext
(). The idea is that it will only pay attention to events that are
within the current context. So if the context is "Menu", then only the
events in the Menu object above will be considered.

So to specify a context, you just put a top-level object into the JSON
file whose name is the name of the context. In the context, you can
specify input events as variables. The name of the variable is the
name of the event. The value can either be a single string
representing the associated key or an array of strings. The idea is
that you can use an array if you want multiple keys to both trigger
the same event.

To hook a function so that it responds to an input event, use
InputManager::hookIntoCommand. The first parameter is a specially-
formatted string that specifies the input event to respond to. The
syntax is as follows:

context.eventName:direction

This should be self-explanatory except direction. Direction is either
"Up" or "Down". If direction is "Up", then the callback will only be
called if one of the associated buttons is released; if it's "down",
then the callback will be called the moment one of the keys is pressed
down. In the above example, if you wanted to make a callback be called
in response to selecting a menu item, you could use this string:
"Menu.Select:Down".

The second parameter is the callback itself. Usually to construct this
it's simplest to just use Boost.Bind, particularly for methods of a
class. If the class is MUGE and the callback is named quitHandler,
say, then you could do

boost::bind(&MUGE::quitHandler, this)

to construct the correct callback, provided that occurs in the MUGE
object itself (so that 'this' points to the right place).

One thing that might be nice to have in the future would be a way to
distinguish a key that was just pressed the last frame from a key that
is merely pressed; this would probably be useful for a menu so that
pressing down, for example, would move down only once and not move
down one item every frame. This would take some extra code to monitor
key states, but it could probably be worked into the rest fairly well,
for example, by adding a new possible value for direction in the
command syntax for hookIntoCommand; maybe something like

Menu.Down:JustPressed

as opposed to

Menu.Down:Down
Reply all
Reply to author
Forward
0 new messages