Jump to content
  • Advertisement
Sign in to follow this  
Haytil

Advice on Collision Detection in Tiled Sidescroller

This topic is 4796 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need some advice as to whether my idea for collision detection in my 2D tiled sidescroller is a good idea or not (perhaps it is too slow and there is a better way?). Here's how it works. First, I have a tile map. Let's assume each tile is 32x32 pixels. 0000 0100 4444 Each tile, aside from graphics, also has collision info. I have decided to make everything that blocks the main character's path out of 8x8 blocks of pixels. So each tile has a 2D array of ints reflecting whether or not its component 8x8 pixels are solid or not. For example: Tile 0: 0000 0000 0000 0000 Tile 0 is completely transparent to movement. Tile 1: 0000 0000 0100 0101 Tile 1 represents an impassable barrel (the stacked 1's, or an 8x16 rectangle of pixels) and an impassable, smaller crate (the lonely 1, or an 8x8 square). Tile 4: 1111 1111 1111 1111 Tile 4 is completely solid and cannot be passed (it's a floor tile). So here's what the level does when it loads: It creates an array of tiles (in this case, 4x3): int tile_array[4][3]; Then, for each tile type, it creates a 4x4 array for collision info (since each tile is 32 pixels x 32 pixels and each collision block is 8 pixels x 8 pixels). In this case, there are 5 kinds of tiles (0, 1, 2, 3, and 4, though only 0 and 4 were represented on my little example map): int tile_collision_array[5][4][4]; Then I create a 2D array for the collision info of the entire level, by using the tile_array and the tile_collision_array. int final_collision_array[4 * 4][4 * 3]; I then check the tile_array, match each tile to the info in the tile_collision_array, and fill in the final_collision_array. I will spare you the code, though the final picture of final_collision_array should look like this: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000010000000000 0000010000000000 1111111111111111 1111111111111111 1111111111111111 1111111111111111 Ok, now in order to move the main character, his position and dimensions are used for collision detection against this giant array. If his future position would place part of him in a cell on this array with a value of '1,' then he'd be walking into an object, so movement is refused. Otherwise, movement is granted. My question is this: Is this a good way of performing collision detection and creating a variety of solid aspects to my tiles? I want tiles with stairs, odd platforms, cliffs, etc, so I need to be able to customize my tiles with collision info. Obviously using an array like this isn't a big deal right now....but what if the level is 100 tiles long and 20 tiles high, with each tile being 128 pixels by 128 pixels and each little piece of collision info being an 8x8 square and a total number of 32 differing tiles? The tile_array would be 100x20, the tile_collision_array would be 32x16x16, and the final_collision_array would be (100 * 16) x (20 * 16)....512000 bytes. This wouldn't be too much as far as RAM would be concerned (only 512 KB), but might there be issues when looking up values located all over this giant array (remember, the main character isn't the only one moving and thus checking collision info....so are all the enemies, as many as 100 AIs doing the same as the main character)? Is this a bad idea? Is there a better way, that allows me to use a decent number of large-sized tiles, each with differing collision info? Sorry for the long post. I'll be happy to clarify any confusion. Thanks. -Gauvir_Mucca

Share this post


Link to post
Share on other sites
Advertisement
Just a bit of clarification as to why I'm using this method as opposed to independently using objects in the world for collision detection:

I wanted to tie collision info with the tiles and artwork directly, so that an artist, using my level editor, can draw something on a tile (like stairs), and then manipulate the collision squares on the tile (like blocks in a staircase pattern), and then simply save one big piece of data.

Furthermore, this removes the need for my engine to load in different shaped graphics and unique collision info for each kind of object (like a staircase).

-Gauvir_Mucca

Share this post


Link to post
Share on other sites
Hey,

A project that I'm working on uses a [somewhat] similar concept, except with per pixel collision detection. So long as you check all of your small moving objects against this large static array intelligently, methinks the speed loss will be minimal.

My personal opinion though is that you should have lookups for each of the tiles and never actually combine them all into one large array. That way, you're halving the amount of memory required [eg for a 500x200 map or something this will be noticable]. Similarly you can have a special case flag for tiles which are completely transparent or completely opaque, so that the entire collision detection routine does not have to be run for no reason.

The only downside that I can think of to a system like this is that making things like ramps is somewhat difficult.

--CJM

Share this post


Link to post
Share on other sites
yeah thats the exact same idea i cam up with:


char map[10][10] = {
// 0 1 2 3 4 5 6 7 8 9
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //0 BOTTOM RIGHT
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //1
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //2
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //3
{1, 0, 0, 0, 2, 0, 0, 0, 0, 1}, //4
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //5
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //6
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, //7
{1, 0, 0, 0, 0, 0, 0, 6, 3, 1}, //8
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //9 TOP RIGHT
};
[\CODE]

each value repersents the texture used, and what is passible and not.

0= Passable
1= Wall
2= game character

to move my character all i do is a simple test to check if the next tile doesnt
equal 1, otherwise its alloud 2 move.
and it swaps values around.
so if i press up then it will check the above tile, if not equal to 1 then swap.

this is sort of the same thing as u i guess, its a nice easy way for collision detection, and best of all it works :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Here is the kind of thing I do, here is what my struct might look like:


struct Tilemap {
int map[3][20][15];
bool collision[20][15];
};



I actually use a class and zero out the memory in the constructor, for my editor, in the actually game the Tilemap is loaded from a file.

When setting a tile with an edit function, or method, if the tile is a collision tile I set the collision flag to true, if not -false. A collision tile would be distinguished by its index. Tiles above 64 for example would be collision tile.

With the single layered maps with approach this isn't necessary, but I find that it is useful when designed layered maps, say you set a water tile which is a collision tile then you set a bridge over the water which is a walkable tile. the collision is set to false. So you can effectively walk through/over the water tile.

A single layered map might as well be represented like...

int map[20][15];

and collision checks like...


bool Collision(int x, int y)
{
if(map[x][y] >= 64)
return true;
return false;
}



It is also more efficient to only do collision tests against one variable rather than 3+. I deal with the game objects using regular rectangular collision tests.

Things that lay over collision tiles would be a collision tile (i.e. a sign that hangs on a wall) because the collision tiles would be walkable if it was the other way around. You can make secret walls by setting a walkable tile over a collision tile.

Share this post


Link to post
Share on other sites
That was me who just posted, also I'd like to add.

This is how I perform collision response, I move the character to its target, and if there is a collision I move the character back. If you perform both x, and y at the same time it will appear sticky. If you check x and y positions independently it will be more realistic.

Share this post


Link to post
Share on other sites
Your method is the exact same thing I used back in 1993, and it worked great. I used 4x4 pixel collision boxes, and it worked great.

I also used a variation on this scheme to do occlusion testing for parallax scrolling.

Share this post


Link to post
Share on other sites
Same here, I just make the .index either passable or not

map[file_tilex][file_tiley].type = file_tiletype;
map[file_tilex][file_tiley].index = file_collide;

//Grab the map index
checkmap = map[cmapx][cmapy].index;

if (checkmap==COLLIDE_OBJECT)
{
//Check which object

now whatever the object do something like dont walk or die

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!