Implementation copied from: https://akkartik.itch.io/carousel/devlog/649349/handling-cascading-collisions
B3I5MC55KGDCKCCC6VTSZXCTMWULONPWPBL6PKBME7TOCODWONDQC YASTFHTECB4SLOHBRREMWGEVDSNUC2USP7P4PJLXZPKC3J5G3CKQC R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC 7KX3WBFEXMIHNKWNF4NUOBW5HO3PEL3ZEFFMTAXFOQG6V7BYXZ3AC 7TQAF4BYIK75EEYCCK7VEUSZHNCWMWIA3HZGQKIILYESUZ5ZZRVQC FBDRJ53NJ5BWDQGU2GWZ6NEYHKCCRD7RODMIG7QQZBRFUB4HR7OAC OELP2MAL5RGZ3AZ42V6H7RLGX52JLNHGUD7GV6YIVZ3ACOK5SFSQC YLD23PUKZXGVU4Z6WXTNA2TS42TJPZO7CKTFP7WK2JNMZKOY3DGAC ZANGJNNX6EITFBOF6NWCF2EM5BDQDEIOD4UPWMF5I6SKAURRTIHAC sign = function(v)if v < 0 then return -1 endif v > 0 then return 1 endreturn 0end
move = function(def, msv)def.x = def.x - msv.xdef.y = def.y - msv.ydef.pos.x = def.pos.x - msv.xdef.pos.y = def.pos.y - msv.yend
prepare_to_move = function()for _,def in pairs(Definitions) doassert(def.w)assert(def.h)if def.pos == nil then def.pos = {} endif def.hs == nil then def.hs = {} enddef.pos.x = def.x + def.w/2def.pos.y = def.y + def.h/2def.hs.x = def.w/2def.hs.y = def.h/2endend
-- move any colliding Rects to make room for `a`move_others = function(a)for _,d in pairs(Definitions) doif d ~= a thenlocal msv = collide(a, d)if msv thenmove(d, msv)A1(d.key)move_others(d)endendendend
-- returns the _minimum separation vector_ if there's a collision-- requires a pos+halfsize representation for nodescollide = function(a, b)local delta = {x=a.pos.x-b.pos.x, y=a.pos.y-b.pos.y}local abs_delta = {x=math.abs(a.pos.x-b.pos.x), y=math.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 thenif abs_amount.x <= abs_amount.y thenreturn {x=abs_amount.x*sign(delta.x), y=0}elsereturn {x=0, y=abs_amount.y*sign(delta.y)}endendend