Handling cascading collisions
Lua Carousel » Devlog

Today I finally managed to wrap my head around a program I'd been struggling with for a few weeks: moving more than one block in response to collisions.
-- each rect is of the form:
-- pos={x=..., y=...} for the center
-- hs={x=..., y=...} for the half-width and half-height
Rects = {}
Move = nil
function car.draw()
for _,r in ipairs(Rects) do
color(r.r, r.g, r.b)
rect('fill', r.pos.x-r.hs.x,r.pos.y-r.hs.y, r.hs.x*2,r.hs.y*2)
end
end
function car.mousepressed(x,y, button)
local curr = within_any(x,y)
if curr then
Move = {target=curr, dx=x-curr.pos.x, dy=y-curr.pos.y}
else
new()
end
end
function car.mousereleased(x,y, done)
Move = nil
end
function car.update(dt)
if Move == nil then return end
local x,y = love.mouse.getPosition()
Move.target.pos.x = x-Move.dx
Move.target.pos.y = y-Move.dy
move_others(Move.target)
end
-- move any colliding Rects to make room for `a`
function move_others(a)
for _,r in ipairs(Rects) do
if r ~= a then
local msv = collide(a, r)
if msv then
r.pos.x = r.pos.x - msv.x
r.pos.y = r.pos.y - msv.y
move_others(r)
end end end end
-- returns the _minimum separation vector_ if there's a collision
function collide(a, b)
local delta = {x=a.pos.x-b.pos.x, y=a.pos.y-b.pos.y}
local abs_delta = {x=abs(a.pos.x-b.pos.x), y=abs(a.pos.y-b.pos.y)}
local size = {x=a.hs.x+b.hs.x, y=a.hs.y+b.hs.y}
local abs_amount = {x=size.x-abs_delta.x, y=size.y-abs_delta.y}
if abs_amount.x > 0 and abs_amount.y > 0 then
if abs_amount.x <= abs_amount.y then
return {x=abs_amount.x*sign(delta.x), y=0}
else
return {x=0, y=abs_amount.y*sign(delta.y)}
end
end
end
function within_any(x,y)
for _,r in ipairs(Rects) do
if within(r, x,y) then
return r
end end end
function within(a, x,y)
return x > a.pos.x-a.hs.x and x < a.pos.x+a.hs.x
and y > a.pos.y-a.hs.y and y < a.pos.y+a.hs.y
end
function new()
while true do
local r = randrect()
if not overlap_any(r) then
table.insert(Rects, r)
break
end end end
function randrect()
local w = rand(15, 60)
local h = rand(45, 150)
local x = rand(Safe_width-w-5)
local y = rand(Safe_height-h-5)
return {
pos={x=x, y=y},
hs={x=w, y=h},
r=rand(), g=rand(), b=rand()}
end
function overlap_any(a)
for _,r in ipairs(Rects) do
if collide(a, r) then
return true
end end end
function sign(v)
if v < 0 then return -1 end
if v > 0 then return 1 end
return 0
end
If you try pasting this program into Lua Carousel, remember to first run the abbreviations on one of the example screens. Or if you've deleted that screen, here are the abbreviations this program uses:
g = love.graphics rect = g.rectangle color = g.setColor abs, rand = math.abs, math.random
Get Lua Carousel
Lua Carousel
Write programs on desktop and mobile
| Status | In development |
| Category | Tool |
| Author | Kartik Agaram |
| Tags | LÖVE |
More posts
- Programming on your device with your preferred language74 days ago
- Lua Carousel: program on the device you have, with docs at your fingertipsMay 12, 2025
- Pong Wars, MMO editionFeb 16, 2025
- New version after 41 days, and stop-motion animationFeb 15, 2025
- Drawing with a pen on a pendulumJan 11, 2025
- New version after 16 daysJan 04, 2025
- New version after 9 daysDec 19, 2024
- New version after 3 daysNov 17, 2024
- New version after 40 daysNov 14, 2024
- Turn your phone or tablet into a chess clockNov 01, 2024
Leave a comment
Log in with itch.io to leave a comment.