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
- New version after 3 days25 days ago
- New version after 40 days28 days ago
- Turn your phone or tablet into a chess clock42 days ago
- Guest program: bouncing balls58 days ago
- New version after 3 months, and turtle graphics69 days ago
- Interactively zooming in to the Mandelbrot set on a touchscreen88 days ago
- A little timer app89 days ago
- New version after 4 monthsJun 28, 2024
- Visualizing the digits of πMay 04, 2024
Leave a comment
Log in with itch.io to leave a comment.