-
Notifications
You must be signed in to change notification settings - Fork 0
Core.Input
The input system in your project is a multi-layered, decoupled architecture designed to handle various input sources (Keyboard, Gamepads, etc.) and map them to player-specific game actions.
Here is an explanation of the core system components and how they interact.
The foundation of the system is the IInput interface, which represents the state of a single button or axis.
-
BaseInput: This is an abstract class that implements common logic for any input. It handles:- Normalization: Clamping values between -1 and 1.
-
Edge Detection: Using an internal
EdgeDetectorto determineIsPressed(rising edge),Down(current state), andUp. -
Animations: It supports an
IButtonAnimation(like theBlinkAnimationseen inMainGameObject) to provide visual feedback based on input state.
This layer interfaces with physical hardware.
-
SDLControllerDevice: Wraps the SDL2 controller API. it creates a dictionary ofControllerInputobjects for every button and axis on a gamepad. -
ControllerInput: A concrete implementation ofBaseInputthat polls the hardware state via a delegate (e.g.,device.GetButton(...)).
This class maps a generic Enum T (representing game actions like Jump or Action) to specific IInput instances.
-
Action Mapping: You use
AddInputto bind an enum value to a specific hardware function or a lambda. -
Axis Aggregation: It uses
GenericAxisInput<T>to combine four discrete directional inputs (Up, Down, Left, Right) into a singleVector2(e.g., for movement). -
Persistence: It supports
IGenericInputMapSaverto load and save player-specific keybindings.
This is the central "brain" of the input system. It implements IInputMapper<T> itself and acts as a dispatcher.
-
Multi-Player Support: It maintains a dictionary of
IInputMapperinstances assigned to different player IDs. -
Abstraction: The game logic asks the
PlayerInputRouterfor the state of "Player 1, Action", and the router decides whether that comes from a Keyboard mapper or a Gamepad mapper. -
Auto-Assignment: It can automatically switch the active mapper if
AnyInputPressedis detected on a specific device.
This service handles the high-level lifecycle of players.
-
Player Joining: It manages the
AssignMode, where it waits for a player to press a button and then tells thePlayerInputRouterto link that physical device profile to a player slot. -
Status Tracking: It tracks
PlayerInputStatus(ID, Online status, andPlayerInputType).
In your game logic (like in MainGameObject), you interact with the system via the router using your game-specific enum:
// Inside MainGameObject.cs
private PlayerInputRouter<GameInput> _controller;
protected override void OnInitialize()
{
// Retrieve the router from the Object Manager
_controller = GlobalObjectManager.ObjectManager.Get<PlayerInputRouter<GameInput>>()!;
}
protected override void OnPreUpdate(float deltaTime)
{
// Check if Player 1 pressed the "Action" button this frame
bool isPressed = _controller.GetState(1, GameInput.Action).IsPressed;
// Get movement axis for Player 1
Vector2 moveDir = _controller.GetAxis(1);
}When setting up the engine, you might configure a GenericMapper for the keyboard:
// Example setup for Keyboard
var keyboardMapper = new GenericMapper<GameInput>();
// Map GameInput.Action to a specific function (e.g., Space key check)
keyboardMapper.AddInput(0, GameInput.Action, "Jump", () => MyKeyboardHardware.IsKeyDown(Space));
// Map an axis using four directions
keyboardMapper.AddAxis(0, 1, GameInput.Left, GameInput.Right, GameInput.Up, GameInput.Down);
// Register the mapper to the router
router.AddMapper(keyboardMapper);Because BaseInput supports animations, you can trigger visual logic directly on the input object:
// Inside MainGameObject.cs OnLateUpdate
if (InternalState == GameInternalState.PlayerIsApplyingForce)
{
// Make the physical button on the arcade cabinet/UI blink rapidly
_controller.GetState(1, GameInput.Action).Animation = new BlinkAnimation(100);
}-
Hardware (
SDLControllerDevice) produces raw data. -
Input Objects (
ControllerInput) wrap that data into a standardizedIInput. -
Mappers (
GenericMapper) associate thatIInputwith a semantic action (e.g.,GameInput.Action). -
Router (
PlayerInputRouter) directs that action to a specific player index. -
Game (
MainGameObject) queries the Router to decide what happens on screen.