Pixel-Perfect collision for tile-based game
So I have a 2D tiled Game that has gravity, and players slides with velocity when moving. the max speed can be -16 to 16 both x and y.
What I want is to implement pixel-perfect collision, so that when the player jumps or goes through a one tile air, it goes through instead of avoiding it.
It's also multiplayer but I already implemented networking.
Both players and tiles are 16x16.
149 Replies
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
box2d is too complicated and too big for the simple collision I want in my game.
my game will only consist of rects and never have fluid/dynamic mechanics apart from non-rotating rect players.
and I don't know how to move objects pixel-by-pixel every frame
like sonic the hedgehog games?
kindoff
the players slides
basically there's a little physics like dragging, gravity, and a velocity
but that's all that the game's physics will offer
and it's just applicable for players
(they don't collide with each other btw)
well Sonic does have pixel perfect collision detection
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
there's a programming guide on how to implement Sonic physics ,need link?
also there's gonna half tiles which basically has a size of half a normal tile (either 8x16 or 16x8)
sure
the max speed that the players can go is -16 to +16
which means 1 full tile per frame I suppose
however at normal speed they will only go up to smth like 8. (the max speed is reached only if the player gets boosted either by a specific non-collidable tile, or by a speed boost effect 'potion')
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
2. but isn't that gonna lag?
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
yeah but imagine detecting 16 pixels for both x and y
ur saying to loop through every tile?
no no
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
link above does show that
start and end point of a tile ur on yeah
my bad, it doesnt loop, it immediatly accesses it
I actually have a collision library ready (named JBump), and it gets collisions only at players,
but the library doesn't check pixel-by-pixel (but it can detect fast tunnel-traveling or whatever it's named)
Sonic did not check pixel by pixel
so what do I do?
there is a category called Solid Tiles there, should give you some ideas
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
also JBump is able to get collisions by points and lines
so do I check collisions for a line from past x to current x?
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
yes, JBump knows if you go into a tile or past a tile
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
but the thing is that if there's a 1 tile gap hole on the ground or on the wall, and the player goes a bit fast, it can easily avoid it and thus not fall/go through it
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
😦
but I don't want to avoid that one tile gap
what do you mean?
wait
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
O_O
this is how a one block gap looks like
ive actually implemented physics from scratch, thanks to some tutorials
if the player jumps and moves towards the wall, it will not go through that vertical air
or if the player moves a bit fast, it will not go through the ground hole
how big is ur collision box?
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
16x16
both players AND tile
well you can check if there is an empty tile under the player, then set their speed to 0 and align their position onto that empty block
and how do i check exactly?
in the bottom center of the player?
yeah
because if I do that, the player will then teleport a bit to the right/left
?
so that it can go aligned with that gap
the player will teleport if I check in the player's bottom center
use your brain
checking is just an if condition, why would that teleport the player
because I need to SET the x of the player to be equal to the tile's x, and the y -= 1
use player's x speed to predict the position of the player of the next frame
then with the predicted position, check if there is an empty tile below that predicted position
so now I would have a line between player's x and (x + speed x)
also if im gonna be honest, that annoyed me a bit
excuse me for that
what do you need that for?
how do I check if there's a gap
i believe i mentioned it here
or im not sure what u mean
and what's "predicted position"? is it x + velX?
yes
but that's the future x
with the current x, and the future x, how do I check if there's a gap?
actually you dont really need it
1 min
yes
but what if the player moves faster?
lets say the player moved from left square to right square, on the same frame, before the game renders
his max speed is 16 right?
yes
then no worries
but that's EXACTLY one tile
yeah
check the tile below from player's left bottom collision
so it would be the old collision = x + 16, and the new collision = nX
but that can make a length of 16 pixels
old collision - new collision
yeah, u can still check tho
oh ok
so now what
having (x+16) and nX
for example sonic only has 2 collision points, bottom left and bottom right collision box of the player
in the picture bottom right would detect a tile
bottom left did not detect a tile
the player and tiles has a rect collision
ok then you can loop through each pixel of the player's bottom rect
atleast one of them will find the gap
so
once u find that gap, adjust the player's position to where that gap is
((x+16) - nX) = line (between player's pos and future pos)
foreach(int x: line) {
jbump.checkPixel(x)
}
and checkPixel would tell me if there's a collision at that pixel
yeah
u dont really need a future position btw
you can just check after the player moves
before the game renders ofcourse
but that would always return no collision as that pixel is where the player would be
maybe
pixel.y -= 1
anyway
what do u mean?
what i said
the pixels I am checking are gonna be inside of the player
wait no
what i mean is
pixel.y is = to player.y
thus, no collision
where exactly is the pivot of the player?
bottom left
same as tiles
and it extends 16x16 to up right
as long as the player is on a tile, there is always a collision
not really
the player is ON a tile not in a tile
just check the tile below the pixel
so pixel.y - 1
yeah
ok, so now I would have a few pixels that doesn't collide like the other pixels.
now what do I do, knowing the positions of every non-colliding pixels?
this is where the player should be on the gap right?
yes
it is all the pixels below the player that do not touch a tile
now knowing them, what do I do?
change the player's position to fit into that gap tile
so if one pixel doesn't collide, i teleport the player?
yes
that's stupid
not if player's x speed is 1
but player's x speed is up to 16
what do I do if the speed is 8?
yeah player has to pass through the tile before the gap first
I don't understand
OH
but wait
if the player fell before he completely passed the last solid tile he was on, it would look like he teleported
so id check if there is a gap at the bottom left pixel of the collision rectangle if player's xspeed is > 0
otherwise id check the bottom right pixel of the collision rectangle if player's x speed is < 0
oh ok
what are u trying to show me?
but doesn't that mean that I do not have to check every pixel?
its pointless to check every pixel, since the tile is a full block anyway
so I check the player's future position (which is the bottom left corner)
and if below that pos there's nothing, the player's velX is set to 0, x = air tile x, and y -= 1?
pretty much yes
can the player move on air?
and I do that for velX > 0, velX < 0, velY > 0, and velY < 0 respectively?
only with an effect
there's gravitational effects in-game
because if ur holding right, after u teleported to that gap, u might land on the next tile
like boosting which makes the player go up to full speed (16)
or like no gravity effect
or super gravity effect
or negative gravity
or wall gravity
but I can make that thing not apply if the gravity is 0
in order to prevent that, if ur holding right, check if bottom right pixel's x + 1 has a tile there
you mean - 1?
is X from left to right or right to left?
origin (0) is left
then i mean +1
why
u want to check if there is a tile next to the bottom right pixel
so you mean x + 17?
afk
?
this is where the player will be after u teleport him
yes
what if you were holding right?
your velX is zeroed, y -= 1, and X = block.x
but holding right increases velocity right?
but that only if the player's right corner is still touching a tile
yes
so he might land on the next tile on the next frame
wdym
afk
if the player is falling
and ur holding right
he might land on the tile on his right
not really because he touches the right block
ok i guess you implemented that logic
jBump already checks collision, but it doesn't check pixel-perfectly
brb atleast 15 minutes i need to do something
ok
same
@TheRanger done?
back
k
Did you need something?
yes
read up
this?
yes
i have no idea what jBump is
it's a simple AABB based collision library in java
ur coding the game on java?
yeah
kinda odd for me to ask in a C# server
doesn't matter
it's still C# syntax
and the question I am asking (pixel-perfect collision) is not really language based
it might be better for you to ask in a game programming server anyway
as many people can help you, instead of only one
then why did you try to help me
why not? just saying more is better than 1
ok