Hello! I love Pico-8, however I've been trying to find out how to do collision. I've done tons of stuff, however the closest I get does the job for some games. However it can't slide.
Let's say you could move the player in 8 directions top down, and there's a wall on your right. If I hold right, I will run into the wall, however due to the way my code works (and I've tried different ways) if you hold up and right, instead of just going up it just makes you stay there. Meaning it's hard to get into 1 tile gaps in walls.
I've also noticed platformers are hard to do as well, as my code checks each corner, I have no way to check what direction a wall is, meaning if you're jumping while running into a wall, when you get to the top and only one corner is touching the wall, it makes you stick.
So is there any good collision systems that is easy to understand, and allows sliding? Thanks. :)
As always, have a look at the demos/collide sample.
In short, the trick is to separate axis responses:
- check x+dx, kill dx if wall
- check y+dy, kill dy if wall
For much more complex collisions, have a look at Celeste, Tomb of Gnur, Micro Platformer Toolkit...
For me, I'm using this on my Jump'n Run-Games:
function update_player(f) repeat if f.dx>0 then f.dx-=f.friction if(f.dx<0)f.dx=0 elseif f.dx<0 then f.dx+=f.friction if(f.dx>0)f.dx=0 end until not is_solid(f.x+f.dx,f.y) f.x+=f.dx end
"is_solid" is a function that checks all 4 Corners and returns "true", if one of them is a solid Block.
The same goes for Jumps. Code between "f.x+=f.dx" and "end":
f.dy+=f.gravity while is_solid(f.x,f.y+f.dy) do if f.dy>0 then f.dy-=f.gravity if(f.dy<0)f.dy=0 elseif f.dy<0 then f.dy+=f.gravity if(f.dy>0)f.dy=0 end end f.y+=f.dy
I must confess that the Code is somewhat "ugly" (especially the Part where f.dy gots "negative-Gravity"), but for me, it works like a charm. Sliding absolutely works.
To be complete, the code for the "is_solid"-function. It just checks the Flags for the Sprites:
function is_solid(x, y, flag) flag = flag or 0 if(fget(mget(flr(x/8),flr(y/8)),flag))return true if(fget(mget(flr((x+7)/8),flr(y/8)),flag))return true if(fget(mget(flr(x/8),flr((y+7)/8)),flag))return true if(fget(mget(flr((x+7)/8),flr((y+7)/8)),flag))return true return false end
[Please log in to post a comment]