Platform game collision detection

Started by
14 comments, last by DekuTree64 13 years, 5 months ago
You don't need to create one giant bit-mask for your whole level. Divide the level into blocks, and leave out empty ones. A grid or quadtree should do fine. It'll save you some memory and it'll potentially speed things up a bit.

Alternately, reuse bitmasks, as you would do with images in a tilemap. First check the bounding box of a collision bitmask, and only if there's overlap do you need to check the overlapping area for pixel collisions.


I normally use rectangles and line segments and all that, but I'm looking into per-pixel collisions for a prototype right now, so yeah. ;)
Create-ivity - a game development blog Mouseover for more information.
Advertisement
For pixel-based smooth collision (i.e approximating/inferring surface normals), I'd recommend looking at the source of Collision Detection Kit, which does an amazing job:
http://code.google.com/p/collisiondetectionkit/
http://www.coreyoneil.com/portfolio/index.php?project=5

That seems like the best approach these days for pixel-based collision, but if you're interested in how it works in Sonic, there's some terrific info here:
http://info.sonicretro.org/Sonic_Physics_Guide
Raigan, thanks for posting that. I wanted to read up on how they did Sonic a while back, it seemed very interesting to me to compare what I thought is the proper approach to their actual work.
-----------------------------He moves in space with minimum waste and maximum joyGalactic Conflict demo reel -http://www.youtube.com/watch?v=hh8z5jdpfXY
np, AFAICR I found that site from a different thread on these forums :)

It's definitely super-interesting stuff.
Hi,

I'm interested in this type of stuff too. I'm creating a standard 2D platform side-scroller. I understand the physics and logic behind the various collision detections (including slopes), but having great difficulty implementing it.

I'm using a tile based system.

My issue is: How do you do this the SIMPLEST way? Right now, I am using rectangular bounding collision detection to see if the player hits walls in the X direction, using pixel-perfect collision detection based on 1 pixel (bottom middle of character) to see if it hits the ground (could be a slope), then a few other particular pixels while walking left/right to see if the player encounters a slope, etc. to decide whether to move the player up/down. Once you cover all the possibilities, you end up checking about 8 different particular pixels, just to get the slopes and everything right, and it still does not seem complete

Because while checking the bottom middle pixel to see if a player landed on a slope (to a void the player standing "next to" the slope), this doesnt work well when you test if they fell off a solid platform, because they fall off too early (its better to use rectangles for this so they have some buffer).

What's the easiest way to check all this stuff in one go?

And as a side note - is it better to apply gravity constantly, or lock the player to the ground if walking, and then only apply gravity if jumping/falling? It seems there are pros and cons to both but I can't seem to work out which is best in this context.

many thanks

PS - I am using PyGame, utilising the sprites & rect functions including collision functions, but the logic should be independent of this anyway.
Ah, this question tormented me for about 8 years, up until last year when I finally solved it. Pixel-perfect, integer based collision of variable sized rectangular sprites, versus tile based maps with slopes, which can be jump-through platforms, or tagged as ice, spikes, etc., and stand on other sprites as well.

No horizontal collision against sprites though, and slopes are limited to 4 levels of steepness, similar to Super Mario World (1 to 4, 1 to 2, 1 to 1, 2 to 1), although you may be able to add more. It's been a while since I wrote it so I don't remember all the details. I think most of the old games used simplifications to speed it up and reduce the size of the code, but I just had to know if a complete solution was possible. And it is. But it's very difficult, there are tons of iffy cases that have to be handled.

So without further ado, here's the code:
Collision.c
Collision.h
CollisionTables.c

The function CollisionMove is the main entry point. The collision grid is just a hash table optimization for sprites, to locate nearby sprites without having to loop through every active thing on the map. It's not even used by CollisionMove anyway, just for sprite collision stuff that's done separately.

The code for standing on sprites is handled in the character update function, but it's pretty simple. Basically a downward trace that shortens the Y movement if you landed on something. Here's how the player character does it:
CollisionGridIter objectIter;GameObject *object;gPlayer.groundObject = NULL;IntVector2Add(&objColNewPos, &gPlayer.position, &collideResult.validMotion);objColOldY = collideResult.validMotion.y > 0 ? gPlayer.position.y : objColNewPos.y;objColNewPos.y++;for (CollisionGridIterInit(	&objectIter, &gGameObjectGrid, &objColNewPos, gPlayer.collisionSize);	(object = CollisionGridIterIncGameObject(&objectIter));){	const IntVector2 *op = &object->position;	const u8xy os = object->collisionSize;	const int top = op->y - os.y;	if (objColOldY < top &&		objColNewPos.y >= top &&		objColNewPos.x + gPlayer.collisionSize.x > op->x - os.x &&		objColNewPos.x - gPlayer.collisionSize.x < op->x + os.x)	{		objColNewPos.y = top - 1;		gPlayer.groundObject = object;	}}if (gPlayer.groundObject){	collideResult.validMotion.y = objColNewPos.y - gPlayer.position.y;	collideResult.flags |= eCollideMoveFlag_collided | eCollideMoveFlag_onGround;}


Hopefully that helps some. Feel free to use the code directly if you can get it to run, or ask questions if you want more details of any part of it. One day I ought to write a tutorial to get the concepts across in a more readable way. So many collision tutorials out there, but all I've read simplify it until important parts are missing, and impossible to add without a total rethinking.

This topic is closed to new replies.

Advertisement