API Reference
JoystickConfig
The JoystickConfig type defines joystick assignment options:
type JoystickConfig = {
joystick?: love.joystick.Joystick, -- Specific gamepad to use
auto?: boolean, -- Enable auto-assignment (default: false)
deadzone?: number -- Axis deadzone threshold 0-1 (default: 0.5)
}Fields:
joystick: A specific Love2D joystick/gamepad to assign to the controllerauto: Enable automatic gamepad assignment (default: false)- When
true: Auto-assigns available gamepads, prioritizes controllers with activity - When
false: Manual assignment only
- When
deadzone: Minimum axis value to register as input (prevents stick drift)
Bindings
The Bindings type defines the structure for control mappings:
type Bindings = {
controls: {string: {string}}, -- Map of control names to binding arrays
pairs?: {string: {string}} -- Optional map of pair names to 4 control names
}Fields:
controls: A table mapping control names (strings) to arrays of binding strings- Keys are control names like "jump", "attack", "moveLeft"
- Values are arrays of binding strings like
{"key:space", "button:a"}
pairs(optional): A table mapping pair names to exactly 4 control names- Keys are pair names like "move", "aim"
- Values must be arrays with exactly 4 control names:
{left, right, up, down}
Example:
local bindings: Bindings = {
controls = {
jump = {"key:space", "button:a"},
attack = {"key:z", "mouse:1"},
left = {"key:a"},
right = {"key:d"},
up = {"key:w"},
down = {"key:s"}
},
pairs = {
move = {"left", "right", "up", "down"}
}
}ControlManager
The ControlManager manages multiple controllers for different players in your game.
newManager
Creates a new control manager.
function controller.newManager(): ControlManagerReturns:
- A new
ControlManagerinstance.
A ControlManager is created automatically
You typically don't need to call this. A ControlManager is created and registered automatically when Tecs registers with Love2D.
addController
Adds a new controller with the specified bindings.
function ControlManager:addController(
bindings: Bindings,
config?: JoystickConfig
): Controllerbindings: Table containing control mappings and button pairs.config: Optional joystick configuration:joystick: Specific gamepad to useauto: Enable auto-assignment (true/false, default: false)deadzone: Dead zone threshold from 0 to 1 (default: 0.5)
Returns:
- The newly created
Controllerinstance.
Example:
local bindings = {
controls = {
jump = {"key:space", "button:a"},
attack = {"key:z", "button:x"},
left = {"key:a", "axis:leftx-"},
right = {"key:d", "axis:leftx+"},
up = {"key:w", "axis:lefty-"},
down = {"key:s", "axis:lefty+"}
},
pairs = {
move = {"left", "right", "up", "down"}
}
}
-- Manual mode (default)
local controller1 = controlManager:addController(bindings)
-- Auto-assignment enabled
local controller2 = controlManager:addController(bindings, {
auto = true,
deadzone = 0.25
})
-- Specific joystick assignment
local joystick = love.joystick.getJoysticks()[1]
local controller3 = controlManager:addController(bindings, {
joystick = joystick,
deadzone = 0.25
})removeController
Removes a controller from the manager.
function ControlManager:removeController(controller: Controller)controller: The controller instance to remove.
Example:
controlManager:removeController(player2Controller)get
Gets a controller by its index.
function ControlManager:get(index: integer): Controllerindex: The 1-based index of the controller.
Returns:
- The controller at the specified index, or nil if not found.
Example:
local player1 = controlManager:get(1)
local player2 = controlManager:get(2)Controller
The Controller represents a single player's input device with their control bindings.
isPressed
Checks if a button was just pressed this frame.
function Controller:isPressed(button: string): booleanbutton: The name of the button to check.
Returns:
trueif the button was just pressed,falseotherwise.
Notes:
- Only returns true on the frame the button is first pressed.
- Will not return true while the button is held down.
Example:
if controller:isPressed("jump") then
player:startJump()
endisDown
Checks if a button is currently being held down.
function Controller:isDown(button: string): booleanbutton: The name of the button to check.
Returns:
trueif the button is currently down,falseotherwise.
Notes:
- Returns true for every frame the button is held.
- Includes the initial press frame.
Example:
if controller:isDown("sprint") then
player.speed = player.runSpeed
endisReleased
Checks if a button was just released this frame.
function Controller:isReleased(button: string): booleanbutton: The name of the button to check.
Returns:
trueif the button was just released,falseotherwise.
Notes:
- Only returns true on the frame the button is released.
Example:
if controller:isReleased("charge") then
player:releaseChargedAttack()
endgetPair
Gets the directional input from a button pair.
function Controller:getPair(name: string): number, numbername: The name of the button pair.
Returns:
x: Horizontal direction (-1 for left, 0 for neutral, 1 for right).y: Vertical direction (-1 for up, 0 for neutral, 1 for down).
Notes:
- Button pairs must be defined in the bindings with exactly 4 buttons: left, right, up, down.
- Opposite directions cancel out (e.g., pressing both left and right returns 0).
Example:
local moveX, moveY = controller:getPair("move")
velocity.x = moveX * player.speed
velocity.y = moveY * player.speedgetPairNormalized
Gets the directional input from a button pair, normalized to work correctly with diagonal movement.
function Controller:getPairNormalized(name: string): number, numbername: The name of the button pair.
Returns:
x: Horizontal direction (-1 for left, 0 for neutral, 1 for right).y: Vertical direction (-1 for up, 0 for neutral, 1 for down).
getRaw
Gets the raw numeric value of a control.
function Controller:getRaw(button: string): numberbutton: The name of the control to check.
Returns:
- For buttons, keys, and hats: 0 when not pressed, 1 when pressed
- For directional axes (with + or -): 0 to 1 based on axis position
- For raw axes (without suffix): -1 to 1 for the full axis range
Notes:
- Useful for analog controls like triggers or thumbsticks.
- Values within the dead zone return 0.
Example:
local throttle = controller:getRaw("accelerate")
car.acceleration = throttle * car.maxAccelerationrebind
Changes the controller's bindings at runtime.
function Controller:rebind(bindings: Bindings)bindings: The new binding configuration to apply.
Notes:
- Useful for implementing control remapping in settings menus.
- Preserves the controller's joystick and deadzone settings.
- Clears all previous bindings before applying new ones.
Example:
-- In a settings menu: create new bindings with the changed control
local function remapJumpKey(newKey: string)
local newBindings = {
controls = {
jump = {"key:" .. newKey, "button:a"},
attack = player1Controller.bindings.controls.attack
},
pairs = player1Controller.bindings.pairs
}
player1Controller:rebind(newBindings)
end
-- Complete rebinding
local newBindings = {
controls = {
jump = {"key:w", "button:a"},
attack = {"key:q", "button:x"}
}
}
player1Controller:rebind(newBindings)notifyWithRumble
Triggers rumble feedback on the controller's joystick.
function Controller:notifyWithRumble(strength?: number, duration?: number)strength: Vibration strength from 0 to 1 (default: 0.5)duration: Duration in seconds (default: 0.2)
Notes:
- No-op if no joystick is assigned or if vibration is not supported.
Example:
if controller:isPressed("attack") and enemy:wasHit() then
controller:notifyWithRumble(0.7, 0.3)
endsetJoystick
Directly sets the joystick for this controller.
function Controller:setJoystick(joystick?: love.joystick.Joystick)joystick: The joystick to assign, ornilto clear.
Notes:
- Automatically triggers rumble feedback when a joystick is assigned
- Calls the
onJoystickChangedcallback if set - Does not change the auto-assignment setting
Example:
-- Assign a specific joystick
local joystick = love.joystick.getJoysticks()[1]
controller:setJoystick(joystick)
-- Clear the joystick
controller:setJoystick(nil)resetJoystick
Resets or changes the joystick assignment for the controller.
function Controller:resetJoystick(config?: JoystickConfig)config: Optional joystick configuration:joystick: Specific gamepad to useauto: Enable auto-assignment (true/false)deadzone: Dead zone threshold from 0 to 1nil: Disconnect gamepad and disable auto mode
Notes:
- Useful for switching controllers or changing modes at runtime
- Can update deadzone without changing joystick
Example:
-- Enable auto-assignment
controller:resetJoystick({auto = true})
-- Disable auto-assignment
controller:resetJoystick({auto = false})
-- Switch to specific gamepad
local joysticks = love.joystick.getJoysticks()
controller:resetJoystick({
joystick = joysticks[2],
deadzone = 0.3
})
-- Disconnect gamepad (keyboard only)
controller:resetJoystick(nil)Controller Properties
bindings
The current binding configuration. Can be read to inspect bindings or passed to rebind().
controller.bindings: Bindingsjoystick
The currently assigned joystick, or nil if no joystick is connected.
controller.joystick: love.joystick.Joystickdeadzone
The axis deadzone threshold (0 to 1). Values below this threshold are treated as 0.
controller.deadzone: number -- default: 0.5auto
Whether automatic gamepad assignment is enabled.
controller.auto: boolean -- default: falseonJoystickChanged
Optional callback function that's called when the controller's joystick changes.
controller.onJoystickChanged: function(
controller: Controller,
newJoystick: love.joystick.Joystick,
oldJoystick: love.joystick.Joystick
)Parameters:
controller: The controller whose joystick changednewJoystick: The new joystick (nil if disconnected)oldJoystick: The previous joystick (nil if was disconnected)
Example:
controller.onJoystickChanged = function(
ctrl: controller.Controller,
newJoy: love.joystick.Joystick,
oldJoy: love.joystick.Joystick
)
if newJoy then
print("Controller connected: " .. newJoy:getName())
updateControllerUI(ctrl, newJoy)
else
print("Controller disconnected")
showKeyboardControlsUI(ctrl)
end
end