gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > collisions

#7929 - whodoo - Sat Jun 28, 2003 8:12 pm

whats the best way of detecting collisions in a game such as super mario or something like that.. I wanna have walls, floors and slopes.. some guy told me that pixel-collisions was the best way, but I wonder if it isn?t faster using "lines" built from a BSP-tree?...

#8006 - jenswa - Mon Jun 30, 2003 12:48 pm

Perhaps some collisions boxes around your characters.

Take your characters dimensions as a collision box.
Most of the stuff in mario-like games can be done that way.
_________________
It seems this wasn't lost after all.

#8022 - Cyberman - Mon Jun 30, 2003 8:42 pm

whodoo wrote:
whats the best way of detecting collisions in a game such as super mario or something like that.. I wanna have walls, floors and slopes.. some guy told me that pixel-collisions was the best way, but I wonder if it isn?t faster using "lines" built from a BSP-tree?...

BSP are only useful for optimization of 3d environments.. Unless you plan on making a clone of mario 64.. it's really using the wrong thing. 2d bounding boxs are much better.

You really only need to check these depending on which surface is closest as well. It's not complicated I suggest experimenting with 'rectangles' as your objects and seeing when they hit each other and work from there. After that change it to the sprite they are and poof you are done practically.

Cyb

#8620 - Nessie - Wed Jul 16, 2003 6:34 pm

Using pixel tests is a bad idea if, say, the slope artwork you are using is deliberately rough and jaggy, like rough stone or clumpy grass. Pixel testing is probably also not going to work if you want to have secret walls that you can walk through to enter secret areas.

I'd guess many games use a collision array, which mirrors the dimensions of the BG layer that the player typically interacts with, though you'd be using more memory that way.

#8621 - Ninja - Wed Jul 16, 2003 7:18 pm

Nessie wrote:
I'd guess many games use a collision array, which mirrors the dimensions of the BG layer that the player typically interacts with, though you'd be using more memory that way.


I am just curious... why wouldn't it be a better idea to simply read the tile data in, and determine what type of tile is at the selected x and y coordinate on the screen, and go from there? Why would you need a second array for collisions?

If most games do things that way, then there's something that I am seriously missing here, and would appreciate some clarification.

#8624 - Nessie - Wed Jul 16, 2003 7:37 pm

If you are just determining what type of collision tile is at a given x,y location and then testing based on that, I don't see any problem with that. Except...Question is, how do you do that?

Do you use the map index into the BG tile array to also look up into a seperate collision tile array? In that case you've got a collision tile per BG tile, which might use less memory than a collision grid that matches the primary BG layer, 1 for 1....

Do you somehow look at the pixels in the tile and try to figure out why kind of slope it is? I really doubt you mean this because it'd be slow and not-too reliable.

If you look up the sub-tile pixel at the x,y location and check whether it's solid or not, well, then you're back to pixel testing and you may or may not have issues with that depending on your artwork, etc.

It's possible you mean something entirely different, but at the end of the day, we use a whole seperate collision grid for our game because it gives us the opportunity to embed all sorts of other things in there....we could decide to hook up touch triggers (that signal something to happen when the player passes through a certain area)...we could mark certain slopes as slippery if we want...we can mark certain tiles to do fire damage...we can mark tiles as being in water, we can mark certain solid tiles as being breakable, etc. These actions may or may not relate to the underlying BG tile, but in our game, we don't have to be tied to that limitation.

So, there is no one magic answer in game development, it all really depends on what you are trying to do and whether or not you can accept the limitations or performance cost that accompany any chosen design decision.

#8627 - Lord Graga - Wed Jul 16, 2003 9:06 pm

If you want some source then check this out (Ohh, my pimpage):* LordGraga is still too sexy for his hat

#8629 - whodoo - Wed Jul 16, 2003 11:14 pm

hmm I dunno if you understand fully... I know how to make odernary tilecollisions.. but I want slopes and some physics..e.g. that I wanna slide down if the slope isn?t that gentle and so on.. I thoug of pixelcollisions..to check which tile the player collides with and so on.. like the collisions in e.g. Mickeys magical quest or something.. not only blocks I want slopes and stuff

#8633 - Lord Graga - Thu Jul 17, 2003 12:02 am

ohh :P thats different stuff....
maybe make a collision map using the basic shapes needed, then you could check it like this:
Code:

cx = (x/8);
cy = (y/8);
xx = x%8;
xy = y%8;

basetile = collisionmap[cx+cy*MAPWIDTH];
tilepoint = basetile+xx+xy*8;
tile = collisiontiles[tilepoint];

if(tile==0) //nothing
{
temptilepoint = basetile+xx+8+xy*8;
temptile = tempcollisiontiles[tilepoint];
if(temptile==0) y++; //Fall down
}

if(tile==1) //Hard ground
{}//DO NOTHING

if(tile==2) //Wet slidy ground
{
temptilepoint = basetile+xx+9+xy*8;
temptile = tempcollisiontiles[tilepoint];
if(temptile==0) { y++; x++; } //Move down right
elseĀ  //if we didn't slide down right
{
temptilepoint = basetile+xx+7+xy*8;
temptile = tempcollisiontiles[tilepoint];
if(temptile==0) { y++; x--; } //Move down left
}
}


ewk.... I'm tired, this code would probably not work.... It it works, then it is only for one point of the map... not a bounding box.... if you needed bounding boxes, you should delay the moving of X and Y until every point of the box was tested....

zzZzzzZZZzzz

#8644 - Ninja - Thu Jul 17, 2003 3:32 am

Nessie, I have had a lot of sake to drink tonight, so be warned that I probably won't make sense. Anyways, here goes.

My own collision detection algorithm works as follows:

Upon level load, I load the map into a ScreenBaseBlock, where it is stored for the GBA to do whatever it does with it.

When I want to know what type of tile is at a given x and y position, I use the following forumla, where mapData is the ScreenBaseBlock where the map data is stored:

mapData[(x/8) + ((y/8)*32)]

when I am checking for a collision, I start at the lower left pixel of the character's sprite, and I move left 8 pixels at a time, so that I always move to the next tile, until I am at the end or past the last pixel in the character's sprite.

When I want to swap a tile out with a different tile, I just specify the tile to be swapped, and move in the new tile.

The different tile types available are stored in arrays, sort of like this:

const u16 clearTiles[] = {0x0000, 0x0001, etc.};

when a tile is checked for its properties, that array is consulted. Actually, I suppose I just answered my own question. A collision map is used to avoid using extra clock cycles to check the tile's type by sacrificing memory... That's what I am guessing. Maybe I should rewrite my code.