0Pricing
Lua Academy · Lesson

Movement and Collisions

Make a playable scene.

Movement and Collisions is a free Lua Academy lesson on CoddyKit — lesson 4 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.

Position and Velocity

Movement in LÖVE means changing an object's position over time. Store x and y, then add velocity in love.update scaled by dt.

Keeping velocity as dx and dy per second makes diagonal motion and physics clean and frame-rate independent.

function love.update(dt)
  player.x = player.x + player.dx * dt
  player.y = player.y + player.dy * dt
end

Input-Driven Movement

Combine polling with velocity to steer an object. Read direction keys in love.update and apply speed times dt.

Because love.keyboard.isDown is checked every frame, the player moves smoothly while the key is held.

function love.update(dt)
  if love.keyboard.isDown('left') then player.x = player.x - player.speed*dt end
  if love.keyboard.isDown('right') then player.x = player.x + player.speed*dt end
end

Normalizing Diagonal Speed

Pressing two direction keys at once makes diagonal motion faster, since both axes add full speed. To fix this, normalize the movement vector.

Divide the direction by its length so its magnitude is 1, then multiply by speed. Now diagonal travel matches straight-line travel.

local dx, dy = ix, iy
local len = math.sqrt(dx*dx + dy*dy)
if len > 0 then
  player.x = player.x + (dx/len) * player.speed * dt
end

Keeping Inside the Screen

Clamp position so objects stay on screen. Read the window size with love.graphics.getWidth and getHeight, then bound the coordinates.

math.max and math.min together clamp a value between a minimum and maximum cleanly.

local w = love.graphics.getWidth()
player.x = math.max(0, math.min(player.x, w - player.size))

Axis-Aligned Bounding Boxes

The simplest collision uses rectangles, called AABB for axis-aligned bounding boxes. Each object has x, y, width, and height.

Two boxes overlap when they intersect on both the horizontal and vertical axes at the same time. This check is fast and good enough for most 2D games.

-- box: { x, y, w, h }

The AABB Overlap Test

Two rectangles overlap when one's left edge is past the other's right edge on neither axis. The classic test combines four comparisons.

If all four are true, the boxes intersect. This single condition is the workhorse of 2D collision detection.

function overlaps(a, b)
  return a.x < b.x + b.w and
         b.x < a.x + a.w and
         a.y < b.y + b.h and
         b.y < a.y + a.h
end

Reacting to a Collision

Once overlaps returns true, decide what happens: pick up a coin, take damage, or stop movement. Check collisions in love.update after moving.

For pickups, simply remove the item or increment a score. For solid walls, you push the player back out.

function love.update(dt)
  movePlayer(dt)
  if overlaps(player, coin) then
    score = score + 1
    coin.dead = true
  end
end

Circle Collisions

For round objects, distance-based collision is more accurate. Two circles collide when the distance between centers is less than the sum of their radii.

Comparing squared distances avoids the costly square root, a common optimization when checking many objects.

function circlesHit(a, b)
  local dx, dy = a.x - b.x, a.y - b.y
  local rsum = a.r + b.r
  return dx*dx + dy*dy < rsum*rsum
end

Resolving Wall Collisions

To stop a player at a wall, a simple approach is to move on each axis separately and undo a step that causes overlap.

Move x, test; if it collides, revert x. Repeat for y. This axis-separated resolution prevents sticking on corners.

player.x = player.x + vx * dt
if overlaps(player, wall) then player.x = player.x - vx * dt end
player.y = player.y + vy * dt
if overlaps(player, wall) then player.y = player.y - vy * dt end

Applying Gravity

Platformers add constant downward acceleration. Increase vertical velocity by gravity times dt each frame, then apply velocity to position.

When the player lands on ground, zero out vertical velocity so they stop falling. Jumping sets a negative vertical velocity.

function love.update(dt)
  player.dy = player.dy + GRAVITY * dt
  player.y = player.y + player.dy * dt
end

Removing Dead Objects

After collisions you often remove objects. Iterate a list backward and call table.remove so indices stay valid while deleting.

Backward iteration is the safe Lua idiom for removing items mid-loop, avoiding skipped entries that forward iteration would cause.

for i = #coins, 1, -1 do
  if coins[i].dead then
    table.remove(coins, i)
  end
end

Quick Check

Test your understanding of movement and collisions in LÖVE.

Recap

Movement combines position, velocity, and dt, with normalization for fair diagonals and clamping to keep objects on screen. Collisions start with AABB overlap tests, with circle distance checks for round objects.

Resolve walls by reverting per-axis moves, add gravity for platformers, and remove dead objects by iterating backward with table.remove.

Frequently asked questions

Is the “Movement and Collisions” lesson free?

Yes — the full text of “Movement and Collisions” 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 “Movement and Collisions”?

Make a playable scene. 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 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Movement and Collisions” 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.

All lessons in this course

  1. The LOVE Game Loop
  2. Drawing Shapes and Images
  3. Handling Input
  4. Movement and Collisions
← Back to Lua Academy