Handling Input
Respond to keys and mouse.
Handling Input is a free Lua Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Two Ways to Read Input
LÖVE offers two input styles. Polling asks "is this key down right now?" each frame, ideal for continuous actions like movement.
Events are callbacks that fire once when something happens, like love.keypressed, ideal for one-shot actions like jumping or shooting.
Polling the Keyboard
love.keyboard.isDown(key) returns true while a key is held. Call it inside love.update for smooth, continuous response.
Because it is checked every frame, holding the key keeps the action going. This is the natural fit for moving a player around.
function love.update(dt)
if love.keyboard.isDown('right') then
player.x = player.x + player.speed * dt
end
endChecking Multiple Keys
love.keyboard.isDown accepts several keys at once and returns true if any of them are held, which is convenient for alternative bindings.
You can also chain separate checks to handle each direction independently for full four-way movement.
function love.update(dt)
if love.keyboard.isDown('a', 'left') then
player.x = player.x - player.speed * dt
end
if love.keyboard.isDown('d', 'right') then
player.x = player.x + player.speed * dt
end
endThe keypressed Event
love.keypressed(key) fires exactly once the moment a key goes down. Use it for actions that should not repeat while held, like jumping or pausing.
The engine passes the key name as a string, so you compare against names like 'space' or 'escape'.
function love.keypressed(key)
if key == 'space' then
player.jumping = true
end
endQuitting on Escape
A common pattern is closing the game when the player presses Escape. love.event.quit shuts the engine down cleanly.
Because keypressed fires once per press, this avoids accidental repeated triggers from holding the key.
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
endkeyreleased
love.keyreleased(key) fires once when a key is let go. Pairing it with keypressed lets you track held states yourself.
This is useful for charge mechanics: start charging on press, fire on release, measuring how long the key was held.
function love.keypressed(key)
if key == 'space' then chargeStart = love.timer.getTime() end
end
function love.keyreleased(key)
if key == 'space' then power = love.timer.getTime() - chargeStart end
endMouse Position
love.mouse.getPosition returns the cursor's current x and y inside love.update or love.draw. You can also use getX and getY separately.
Coordinates match the drawing space: origin at the top-left, y increasing downward.
function love.update(dt)
local mx, my = love.mouse.getPosition()
crosshair.x, crosshair.y = mx, my
endMouse Buttons
Poll buttons with love.mouse.isDown(1) where 1 is the left button, 2 is right, and 3 is middle.
For single clicks use the event love.mousepressed(x, y, button), which fires once and gives you the click coordinates directly.
function love.mousepressed(x, y, button)
if button == 1 then
spawnAt(x, y)
end
endText Input
For typing, love.textinput(text) delivers the actual character, respecting layout and modifiers. This is better than keypressed for building text fields.
Use keypressed alongside it to handle special keys like backspace and enter that textinput does not send.
function love.textinput(t)
inputBuffer = inputBuffer .. t
endCombining Polling and Events
Real games mix both styles: poll movement keys every frame in love.update, while one-shot actions live in event callbacks.
Choosing the right style avoids bugs. Polling a jump in update would fire every frame the key is held; an event fires it once, as intended.
function love.update(dt)
if love.keyboard.isDown('left') then player.x = player.x - 200*dt end
end
function love.keypressed(key)
if key == 'up' then jump() end
endGamepad Basics
LÖVE also supports controllers through the joystick API. love.joystickpressed and a joystick's isGamepadDown read buttons.
Analog sticks return values from -1 to 1 via getGamepadAxis, letting you scale movement smoothly just like keyboard polling with dt.
function love.update(dt)
if joystick then
local ax = joystick:getGamepadAxis('leftx')
player.x = player.x + ax * player.speed * dt
end
endQuick Check
Test your understanding of LÖVE input handling.
Recap
LÖVE input comes in two flavors: poll with love.keyboard.isDown and love.mouse.isDown for continuous actions, and react to event callbacks like love.keypressed and love.mousepressed for one-shot actions.
Mouse, text, and gamepad APIs round it out. Choosing the right style keeps controls responsive and bug-free.
Frequently asked questions
Is the “Handling Input” lesson free?
Yes — the full text of “Handling Input” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Handling Input”?
Respond to keys and mouse. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Handling Input” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.