Bitmap Collision

Started by
6 comments, last by MrDoomMaster 18 years, 9 months ago
I can't imagine how many times this topic has been brought up on the forums, but considering that I have no search skills, I am unable to find them. So I apologize for another useless post on the topic. I plan to make a side scroller, pretty much just like Super Mario World. Yet, I have no idea how to detect collision with the ground so my sprite (mario) walks appropriately. I also have no idea how I would structure such a collision engine. As you know, the 'ground' tiles will not have the top of the ground at the very top of the tile square, so you can't really use 'rectangle' collision. I somehow have to use color collision of some sort for ONLY specific tiles, such as ground tiles, for example. I am not exactly sure how I would do this. Could someone lead me in the right direction? I've looked at articles at GDNet on collision, but none seems to cover this specific situation. Thanks for all the help guys!
Advertisement
Quote:Original post by MrDoomMaster
As you know, the 'ground' tiles will not have the top of the ground at the very top of the tile square, so you can't really use 'rectangle' collision.

Why not? It's up to you how the tiles are designed, and I'd guess that Super Mario World's tiles were largely designed to have the top of the ground at the top of the tile square. Even if for some reason that were not the case, it can be remedied with position offsets in the collision checking. (Translation: Add or subtract a predetermined amount from the player's actual position. This will mean, when checking for solidity of tiles, that you won't detect the solid tile until further down.)
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
I would imagine simple detection such as rectangle detection was used almost exclusively in those older games like Mario. And the use of tiles only makes it easier. I expect you probably know the location of each tile. Lets suppose your tiles are 16x16 big. So if you have a "ground" tile that you want to detect collision with, but not the very top then you would use something like

if ( x > tile.x && x < (tile.x + 16) )   // we've collided with the x axis, try the y axis  if( y > tile.y && y < (tile.y + 10) )     // we've collided with the lower area of the tile that is 16x10 big (ie. NOT colliding with the very top part)


PS. This assumes the tiles are tracked from their lower left point.
Quote:Original post by TDragon
Quote:Original post by MrDoomMaster
As you know, the 'ground' tiles will not have the top of the ground at the very top of the tile square, so you can't really use 'rectangle' collision.

Why not? It's up to you how the tiles are designed, and I'd guess that Super Mario World's tiles were largely designed to have the top of the ground at the top of the tile square. Even if for some reason that were not the case, it can be remedied with position offsets in the collision checking. (Translation: Add or subtract a predetermined amount from the player's actual position. This will mean, when checking for solidity of tiles, that you won't detect the solid tile until further down.)


What about the slanted tiles? If you watch the movement of the character, their feet are always touching the surface, even if it is a slanted surface. This means doing a lot more than just subtracting/adding an offset. A slanted surface may go from the bottom left of the tile to the top right, a direct 45 degree slant. Other slants may not be as simple.
Quote:Original post by MrDoomMaster
Quote:Original post by TDragon
Quote:Original post by MrDoomMaster
As you know, the 'ground' tiles will not have the top of the ground at the very top of the tile square, so you can't really use 'rectangle' collision.

Why not? It's up to you how the tiles are designed, and I'd guess that Super Mario World's tiles were largely designed to have the top of the ground at the top of the tile square. Even if for some reason that were not the case, it can be remedied with position offsets in the collision checking. (Translation: Add or subtract a predetermined amount from the player's actual position. This will mean, when checking for solidity of tiles, that you won't detect the solid tile until further down.)


What about the slanted tiles? If you watch the movement of the character, their feet are always touching the surface, even if it is a slanted surface. This means doing a lot more than just subtracting/adding an offset. A slanted surface may go from the bottom left of the tile to the top right, a direct 45 degree slant. Other slants may not be as simple.


Ahh. No, slanted tiles are not quite as simple. The way that I've seen it done, however, and the way I do it in my tile-based platformer, is a simple calculation within the movement function that detects whether the player is standing on a slanted tile (i.e. a different property than your basic "solid" tile), and sets the vertical position depending on where the player is in relation to the tile. For a 45-degree slope (by far the simplest) from upper left to lower right, something like:
int player_tile_y = (int)(player.y_pos / TILE_HEIGHT) * TILE_HEIGHT;int x_diff = (player.x_pos + player.width / 2) - (int)((player.x_pos + player.width / 2) / TILE_WIDTH) * TILE_WIDTH;player.y_pos = player_tile_y + (x_diff / TILE_WIDTH) * TILE_HEIGHT;

It probably looks rather complicated. To try to sum it up: It determines x_diff, the distance between the player's current X position (player.x_pos + player.width / 2) and the left edge of the tile the player is on. A fraction is obtained by dividing by the TILE_WIDTH, and then it is multiplied by TILE_HEIGHT. We add the resulting amount to player_tile_y, which is the absolute y value (in coordinates, pixels, what have you) of the tile that the player is on/within.

This is rather simplified (believe it or not), not taking offsets and such into account, but it's the easiest method. (Much easier, and faster, than some sort of per-pixel solution.)
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
when i was doing 2D collision detection a while ago, I googled for it and found this website. It has an awesome tutorial and it explains with demonstration with complex shapes. Check it out.
http://www.harveycartel.org/metanet/tutorials/tutorialA.html

if you want to see their game which uses this collision detection, go here:
http://www.harveycartel.org/metanet/downloads.html

~guyaton
~guyaton
I've heard about pixel perfect collision detection. The idea was to use spites masks (or, in even more sophisticated cases, additional layers) so check if sprites, objects, walls etc overlaps. The idea appears to be interesting but I’ve never found any tutorial or article on this topic that would explain how to do it properly.

There is one article on this topic here.

I'd be glad if someone could point some better article.
Well, I have to someway create "invisible lines" on my tiles, which serve as a placeholder for collision detection. The feet of my 'mario' character will have an invisible point. This way I can do point-line collision detection. His left and right side will also have points as well. I don't know how I would configure my tiles this way or how I would configure my sprites this way also. I could always hard-code it, but this isn't good practice. I would somehow have to implement this into my level editor, I guess.

Any ideas? Is my idea good?

This topic is closed to new replies.

Advertisement