Context of the question :
When developing a game using Game State Management I came across a problematic when it came to handling user input : I want my game to retrieve user input a single way, but to handle it in a completely different way, depending on the context.
For example, the [Up] key will always mean "Menu Up" when you're in a menu, but if you're in the game, it might do different things, depending on the key bindings. Another difference would be, for example, that in a menu, a .5sec KeyDown
on a key should be interpreted as a single command, but when you're in game, a .5sec KeyDown
should often be seen as a .5sec movement / burst / charge shot / etc...
Then way I though about to achieve this result is the following :
- Have an
InputState
class that keeps the current and previous Keyboard/Gamepad input states, just like the usual InputState class. Have thisInputState
class implement all the methods I would need in all the different contexts. - Create an Interface per context. For example,
IMenuInputState
,IGameInputState
,ICutsceneInputState
, etc. These interfaces would only contain the method definitions related to the context. - Have the
InputState
implement all theI[...]InputState
interfaces. If two or more context need the same method, the same implementation would be used. - In the
ScreenManager
's Update method, theInputState
would be Updated, but depending on which screen must handle theInputState
, a differentI[...]InputState
would be sent. Even though the screen could access the other methods by casting the interface, only the contextual methods would directly be usable.
My question is the following : Is my idea a proper / common way of handling this issue?
If it is, could you tell me the name of that "pattern" or direct me to some online resources so I can read on that and avoid the known pitfalls. If it's not, how would you suggest I handle the problem?
Note: I know this question is borderline since the answer is partially subjective but I'd appreciate some help on this issue since I think it's a critical decision in my project.
Answer
If I am understanding, then you are saying that you will have a class called InputState
that implements many interfaces. Then, other classes should never use InputState
, but rather, pick an interface that applies to them.
With this model, you will be losing the advantages of inheritance. All of the code will be in one class, InputState
, and the way of accessing that class becomes less clear. These kinds of statements should be a red flag in object-oriented languages:
Have this InputState class implement all the methods I would need in all the different contexts.
How about something like this:
InputState
receives all inputs and reports on themContextualInput
is a class which defines all of the shared contextual methodsMenuInput
,GameInput
,CutsceneInput
all extendContextualInput
and have context-specific methods
InputState
will only have general methods such as InputState.isKeyHeld()
, InputState.getMousePosition()
, or InputState.getAccelerometer()
.
ContextualInput
holds a reference to the InputState
object, which can be easily swapped out when you want to do testing and supply fake user input. It can also have methods that are shared among all contextual inputs, such as ContextualInput.getLastAction()
.
Each of the classes that extend ContextualInput
implement their own methods that are completely abstracted from the way they are triggered. You could use a publish/subscribe pattern for other classes to be notified of these events:
MenuInput.onMenuOpen()
CutsceneInput.onAdvanceSlide()
GameInput.onCharacterJump()
No comments:
Post a Comment