InputManager¶
Handles input from physical buttons or keyboard (on PC).
Description¶
The InputManager polls configured pins (ESP32) or keyboard state (Native), handles debouncing, and tracks button states (Pressed, Released, Down, Clicked). It provides a unified input interface for both platforms.
The manager supports edge detection (just pressed/released) and continuous state (held down), making it suitable for both gameplay and UI navigation.
Namespace¶
Inheritance¶
- Base class: None (standalone class)
- Used by:
Engine(manages input manager instance)
Constructors¶
InputManager(const InputConfig& config)¶
Constructs the InputManager with a specific configuration.
Parameters: - config (const InputConfig&): The input configuration (pins, button count)
Example:
#include "input/InputManager.h"
#include "input/InputConfig.h"
// ESP32: Configure GPIO pins
pixelroot32::input::InputConfig inputConfig(6, 0, 2, 4, 5, 18, 19);
pixelroot32::input::InputManager inputManager(inputConfig);
inputManager.init();
// Native: Configure keyboard keys
// (Configuration handled differently on Native)
Public Methods¶
void init()¶
Initializes the input pins.
Returns: - void
Notes: - Must be called after construction and before use - Configures GPIO pins (ESP32) or keyboard state (Native) - Safe to call multiple times (idempotent) - Typically called automatically by Engine::init()
Example:
void update(unsigned long dt)¶
Updates input state by polling hardware pins (ESP32) or keyboard state (Native).
Parameters: - dt (unsigned long): Delta time in milliseconds
Returns: - void
Notes: - Must be called every frame for proper input detection - Handles debouncing automatically - Updates button states and edge detection - Typically called automatically by Engine::update()
ESP32 Example:
void update(unsigned long deltaTime) override {
// Input is updated automatically by Engine
// Access input via engine.getInputManager()
}
Native Example:
// On Native, update is called with keyboard state:
void update(unsigned long dt, const uint8_t* keyboardState);
bool isButtonPressed(uint8_t buttonIndex) const¶
Checks if a button was just pressed this frame.
Parameters: - buttonIndex (uint8_t): Index of the button to check (0-based)
Returns: - bool: true if the button transitioned from UP to DOWN this frame
Notes: - Returns true only on the frame the button was pressed - Useful for one-time actions (jump, shoot, menu select) - Resets automatically on next frame
Example:
auto& input = engine.getInputManager();
if (input.isButtonPressed(0)) { // Button A (index 0)
// Jump (only once per press)
player->jump();
}
if (input.isButtonPressed(1)) { // Button B (index 1)
// Shoot (only once per press)
player->shoot();
}
bool isButtonReleased(uint8_t buttonIndex) const¶
Checks if a button was just released this frame.
Parameters: - buttonIndex (uint8_t): Index of the button to check
Returns: - bool: true if the button transitioned from DOWN to UP this frame
Notes: - Returns true only on the frame the button was released - Useful for detecting button release events - Less commonly used than isButtonPressed()
Example:
auto& input = engine.getInputManager();
if (input.isButtonReleased(0)) {
// Button A was just released
player->stopCharging();
}
bool isButtonClicked(uint8_t buttonIndex) const¶
Checks if a button was clicked (pressed and released).
Parameters: - buttonIndex (uint8_t): Index of the button to check
Returns: - bool: true if the button was clicked (pressed then released)
Notes: - Returns true when button is released after being pressed - Useful for UI buttons and menu selection - Detects complete press-release cycle
Example:
auto& input = engine.getInputManager();
if (input.isButtonClicked(0)) { // Button A clicked
// Select menu item
menu->select();
}
bool isButtonDown(uint8_t buttonIndex) const¶
Checks if a button is currently held down.
Parameters: - buttonIndex (uint8_t): Index of the button to check
Returns: - bool: true if the button is currently in the DOWN state
Notes: - Returns true for as long as the button is held - Useful for continuous actions (movement, charging) - Use with deltaTime for frame-rate independent movement
Example:
auto& input = engine.getInputManager();
float speed = 100.0f; // pixels per second
float vx = 0.0f, vy = 0.0f;
if (input.isButtonDown(2)) { // Left button
vx = -speed;
}
if (input.isButtonDown(3)) { // Right button
vx = speed;
}
if (input.isButtonDown(0)) { // Up button
vy = -speed;
}
if (input.isButtonDown(1)) { // Down button
vy = speed;
}
// Apply movement (frame-rate independent)
x += (vx * deltaTime) / 1000.0f;
y += (vy * deltaTime) / 1000.0f;
Button Indices¶
Button indices are defined by the order in InputConfig:
Typical Mapping: - 0: Up / Button A - 1: Down / Button B - 2: Left - 3: Right - 4: Additional button 1 - 5: Additional button 2
Example:
// Configure 6 buttons: Up, Down, Left, Right, A, B
pixelroot32::input::InputConfig inputConfig(6,
GPIO_UP, // Index 0
GPIO_DOWN, // Index 1
GPIO_LEFT, // Index 2
GPIO_RIGHT, // Index 3
GPIO_A, // Index 4
GPIO_B // Index 5
);
// Use indices
if (input.isButtonDown(2)) { // Left
moveLeft();
}
if (input.isButtonPressed(4)) { // A button
jump();
}
Usage Example¶
#include "input/InputManager.h"
#include "core/Engine.h"
class PlayerController {
private:
pixelroot32::core::Engine& engine;
public:
PlayerController(pixelroot32::core::Engine& eng) : engine(eng) {}
void update(unsigned long deltaTime) {
auto& input = engine.getInputManager();
// Movement (continuous)
float speed = 150.0f; // pixels per second
float vx = 0.0f, vy = 0.0f;
if (input.isButtonDown(3)) { // Right
vx = speed;
}
if (input.isButtonDown(2)) { // Left
vx = -speed;
}
if (input.isButtonDown(0)) { // Up
vy = -speed;
}
if (input.isButtonDown(1)) { // Down
vy = speed;
}
// Apply movement
playerX += (vx * deltaTime) / 1000.0f;
playerY += (vy * deltaTime) / 1000.0f;
// Actions (one-time)
if (input.isButtonPressed(4)) { // A button
player->jump();
}
if (input.isButtonPressed(5)) { // B button
player->shoot();
}
}
};
Input State Comparison¶
| Method | Returns true when | Use Case |
|---|---|---|
isButtonPressed() | Button just pressed this frame | One-time actions (jump, shoot) |
isButtonReleased() | Button just released this frame | Release events (stop charging) |
isButtonClicked() | Button pressed then released | UI buttons, menu selection |
isButtonDown() | Button currently held | Continuous actions (movement) |
Performance Considerations¶
- Update frequency:
update()must be called every frame - Debouncing: Handled automatically, no performance impact
- State queries: All query methods are fast (inline accessors)
- Memory: Button state arrays are small and efficient
ESP32 Considerations¶
- GPIO pins: Configure pins in
InputConfig - Pull-up/pull-down: Ensure proper resistor configuration
- Debouncing: Hardware debouncing recommended for noisy buttons
- Pin limits: Some ESP32 pins have restrictions (check datasheet)
Native Considerations¶
- Keyboard mapping: Uses SDL scancodes
- Key detection: Automatically handles keyboard state
- Multiple keys: Can detect multiple keys simultaneously
See Also¶
- InputConfig - Input configuration
- Engine - Engine that manages InputManager
- Manual - Input and Control
- API Overview