Log In  

Cart #cratesncrushers-0 | 2019-08-15 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Version 0.1

I've made dozens of platformers in Flash. We had to write all of our own code for collisions back in those days and there was a lot of demand for moving platforms and crates.

Moving platforms are hard. It has to move itself and anything on it.

Crates are even harder. It's like a moving platform, but you can push it and the moving platform can carry it too.

Push Me Pull You

A push can become a branching path with many things responding to one request for movement. This engine handles only one knobbly branch at a time. If the collision doesn't have too many parts, it will get it right.


I made this engine using an object pattern so I could figure out how the hell to make it. Hopefully it's readable and if you hate objects that much then please optimize it and post your results. I'm more than happy to see this engine updated.


The more contact points involved in a collision, the more code it takes to solve. The engine pushes the first thing it sees, it doesn't think about the consequences of a pyramid of crates stacked on your head with odd gaps and a random bit of wall in the middle. I once wrote a loop-solver that handles this but it was some heavy duty stuff, not Pico 8 material. Or prove me wrong, I'd be happy to see an engine that handles it without going full Box2D.

P#66704 2019-08-15 20:27 ( Edited 2019-08-15 21:08)

Nice work!
I wonder how you handle the collision between sprites. Could you give me some hints please?

P#69359 2019-10-27 15:13
:: st33d

This block of code looks at a part of the map and returns it as a list of objects with an x,y position and a w,h size. It also returns the sprite id. These are treated like the other rectangles you collide with.

--return a table of objects describing tiles on the map
 --ignore: do not return anything with this flag
 --result: a table of results to add to
 function mapobjects(x,y,w,h,ignore,result)
   result,ignore = result or {},ignore or 0
   local xmin, ymin = flr(x/8),flr(y/8)
   -- have to deduct a tiny amount, or we end up looking at a neighbour
   local xmax, ymax = flr((x+w-0.0001)/8),flr((y+h-0.0001)/8)
   local rxmin,rymin,rxmax,rymax = blokmap.x,blokmap.y,blokmap.x+blokmap.w-1,blokmap.y+blokmap.h-1
   for c=xmin,xmax do
     for r=ymin,ymax do
       --bounds check
       if c<rxmin or r<rymin or c>rxmax or r>rymax then
         add(result, {x=c*8,y=r*8,w=8,h=8,flag=f_outside,sp=0})
         local sp=mget(c,r)
         local f = fget(sp)
         if f > 0 and band(f, ignore) == 0 then
           add(result, {x=c*8,y=r*8,w=8,h=8,flag=f,sp=sp})
   return result

So, there is no collision between sprites. There is only collision between rectangles, and the map is scanned for implicit rectangles to collide with. The sprites are all drawn afterwards.

P#69442 2019-10-29 08:21

Thank you for your explanation! Really helpful.

P#69521 2019-10-31 14:01

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2021-04-10 19:45 | 0.020s | 4194k | Q:37