I'm currently working on creating an input-action system for my game. I simply wanted an easy way to map an ingame action to a certain key.
I've managed to do so with the following method: Create a class that holds both the action and the key for the action:
public static class InputManager
{
//states
public static KeyboardState previousKeyboardState;
private static KeyboardState keyboardState;
private static MouseState mouseState;
public static MouseState previousMouseState;
public static InputState currentInputState = InputState.Gameplay;
//different types of input layers
public enum InputState
{
Interface,
Gameplay
}
public enum GAction
{
Confirm,
Cancel,
MoveLeft,
MoveRight,
MoveUp,
MoveDown,
Inspect
}
public enum InputButtons
{
W,
S,
A,
D,
Enter,
Space
}
private static List<ActionMap> actionmaps;
/// <summary>
/// Map an action to a key, attaching conditions for the action in the progress
/// </summary>
/// <param name="gaction">the action enum item</param>
/// <param name="key">key for the action</param>
/// <param name="action">the function we want to run</param>
/// <param name="conditionList">allowed condition states</param>
public static void MapAction(GAction gaction, Keys key, List<InputManager.InputState> conditionList)
{
actionmaps[(int)gaction] = new ActionMap();
actionmaps[(int)gaction].conditions = conditionList;
actionmaps[(int)gaction].keyboardKeys.Add(key);
}
public static KeyboardState currentKeyboardState
{
get { return keyboardState; }
set { keyboardState = value; }
}
/// <summary>
/// Check if a key is pressed.
/// </summary>
public static bool IsKeyPressed(Keys key)
{
return currentKeyboardState.IsKeyDown(key);
}
public static MouseState currentMouseState
{
get { return mouseState; }
set { mouseState = value; }
}
// / / / / / / / / / / / / /
// f u n c t i o n s / /
// / / / / / / / / / / / / /
public static void init()
{
int count = Enum.GetValues( typeof( GAction ) ).Length;
actionmaps = new List<ActionMap>(count);
for (int i = 0; i < count; i++)
{
actionmaps.Add(new ActionMap());
}
InputManager.MapAction(InputManager.GAction.Confirm, Keys.Space, null,
new List<InputManager.InputState>() { InputManager.InputState.Interface});
}
public static void update()
{
previousMouseState = currentMouseState;
previousKeyboardState = keyboardState;
currentKeyboardState = Keyboard.GetState();
currentMouseState = Mouse.GetState();
}
/// <summary>
/// checks if action is both used and allowed to be used [conditions]
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public static bool IsActionUsedNAllowed(GAction action){
if(IsActionPressed(action) && isActionAllowed(action)){
return true;
}
return false;
}
public static bool isActionAllowed(GAction action){
return CheckAllowedActionStates(actionmaps[(int)action]);
}
private static bool CheckAllowedActionStates(ActionMap actionmap){
for (int i = 0; i < actionmap.conditions.Count; i++)
{
if (currentInputState != actionmap.conditions[i])
{
return false;
}
}
return true;
}
public static bool IsActionPressed(GAction action)
{
return IsActionMapPressed(actionmaps[(int)action]);
}
private static bool IsActionMapPressed(ActionMap actionMap)
{
for (int i = 0; i < actionMap.keyboardKeys.Count; i++)
{
if (IsKeyPressed(actionMap.keyboardKeys[i]))
{
return true;
}
}
return false;
}
}
}
To map and check for an action you use the following statements:
InputManager.MapAction(InputManager.GAction.MoveDown, Keys.S, ControlActor,
new List<InputManager.InputState>() { `InputManager.InputState.Gameplay });`
InputManager.IsActionUsedNAllowed(InputManager.GAction.MoveDown);
I'm not liking the fact that I have to use an if statement to check if any actions have been performed though. I would much rather use events. But create a delegate and event for each action seems sluggish.
Is there any way to generate an event for every field in the enum? I know I could write my own event system, but I want to avoid mixing up c#'s build in events and my own events.