Log In  

function mchk(x, y)
 return mget(flr(x/8),flr(y/8))

function move(x, y, w, h, dx, dy, col)
 if dx < 0
 and mchk(x+dx, y) != col
 and mchk(x+dx, y+h) != col
  then x += dx
 elseif dx > 0
 and mchk(x+w+dx, y) != col
 and mchk(x+w+dx, y+h) != col
  then x += dx end

 if dy < 0
 and mchk(x, y+dy) != col
 and mchk(x+w, y+dy) != col
  then y += dy
 elseif dy > 0
 and mchk(x, y+h+dy) != col
 and mchk(x+w, y+h+dy) != col
  then y += dy end

 return x, y

As an exercise, I wrote a small general-purpose collision script and thought I'd offer it up for folks new to P8 or relatively inexperienced with programming.

This is purposefully not a one-stop solution, but it may get you going. It is probably more in the spirit of PICO-8 to come up with specified collision routines yourself. At the very least, there's some study value here.

Things to consider:

  • This was built to collide bodies <= 8 pixels wide and tall. With some thoughtful fiddling you can get it to accommodate bodies of any size, but I kept it this way for brevity.
  • It takes up 226 memory.
  • This is made for colliding against maps only.
P#13111 2015-08-24 22:27 ( Edited 2016-07-25 02:23)

I think all (X+W)'s should probably be (X+W-1) and same for Y+H's.

(also you define the down() function but never use it)

P#13120 2015-08-25 04:11 ( Edited 2015-08-25 08:11)

:') woops. Thanks.

P#13121 2015-08-25 04:37 ( Edited 2015-08-25 08:37)

Really useful, thank you!

P#13190 2015-08-27 04:44 ( Edited 2015-08-27 08:44)

what type of input are you expecting with 'col'?
the sprite number?
I don't see any fget's so it's not a flag value.
I don't understand.

I'm having trouble getting map collisions to work myself, so im interested in finding and understanding a good way of handling it.


(sorry for the old bump.)

P#25482 2016-07-18 05:14 ( Edited 2016-07-18 09:14)
:: matt

Have you looked at the built-in demo collide.p8?

P#25512 2016-07-18 18:01 ( Edited 2016-07-18 22:01)

Hi! I have looked at it. Mainly I have trouble understanding the demo's code. It's not as well commented as I hoped. I have trouble understanding it enough to implement it into mine with slight alterations for my project.

I was interested in this post's code because I can understand how it works easily.

I've also looked at this post, which seemed to me at first to be the best one.
But I'm still having trouble modifying it.
The problem with this code is that the player can only move while not colliding with any surface.
If you are on top of a collision tile and hold down while holding left or right, the player will not move.

I would like it to work so that if the direction you are traveling in is not blocked then you can move that way. Essentially changing your input: (1,-1) (right and down) vector into a (1,0) (only right) vector. Still allowing the input vector to be whatever it wants, such as gravity or other powerups, etc..

Does the mget(x,y) function indeed require you to divide x and y by 8 to get the cell?
Some examples do this, while others do not.

My main trouble is that my player sometimes collides with empty space, but not the actual tiles.
I assume I am calculating the mget() wrong or something.

Right now my player collides correctly with the empty tiles one tile away from my actual tiles.
I'm trying to find tutorials or more examples, but pico-8 is not very widespread yet.

P#25515 2016-07-18 19:48 ( Edited 2016-07-18 23:48)

mget returns the tilesheet number a map cel, so yes, you have to divide by 8.
fget gives you the flag values from a spritesheet number, so you can use fget on the number you got from mget to check the flags on that tile. This is how I usually go about flagging certain tiles for collison. I hope this brief explanation is helpful!

Also, consider looking at the Jelpi demo. It's pretty good for this sort of thing.

P#25842 2016-07-24 22:23 ( Edited 2016-07-25 02:23)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2022-08-08 01:18:52 | 0.007s | Q:18