Sign in to follow this  
GamDev

Precise collision detection on tile maps and object drawing

Recommended Posts

Hi, I am creating a framework for a bigger project. I am wondering how should I go about detecting collision on tilemaps? The tile collision detection doesn't work for me: I am going to have small and detailed objects, while tiles are 32x32, which means that I wouldn't be able to detect the collision between the character and enemies and the detailed objects. The same goes for rectangular collision detection.

Another question is how should I go about drawing static objects? But I think that that is related. Currently I have tried texture/sprite drawing, but they are not static that way, they move along with the tile map.

Thank you!

Share this post


Link to post
Share on other sites
static object meaning GUI perhaps? You usually render the GUI last/on top without any modelview (opengl,, not used d3d much) tranforms.

I do not understand your first paragraph. What does tile size have to do wth your object detail and how does that relate to collision?

Share this post


Link to post
Share on other sites
[quote name='Infernal-rk' timestamp='1317657178' post='4868588']
static object meaning GUI perhaps? You usually render the GUI last/on top without any modelview (opengl,, not used d3d much) tranforms.

I do not understand your first paragraph. What does tile size have to do wth your object detail and how does that relate to collision?
[/quote]

No, I'm not that far yet. First I want to make a collision and render logic to work smoothly. Let's say it's a building. You can jump on that building. Imagine... Mario first comes to my mind. In Mario there are stone blocks that you can jump on to, so this is what i had in mind.

As for the first paragraph - I was talking about tile-based collision and telling that it wouldn't work because some of the things that I want to collide are smaller than 32x32 and tile collision wouldn't work.

Share this post


Link to post
Share on other sites
I am a little confused on what you are trying to accomplish. Initially, you mention tiles which would imply that you are working with tile maps. However, further on, you mention objects in Mario which is a platformer and, like other platformers, doesn't use tiles at all.

So my question to you is, Are you using actual tile maps or are you really just looking for simple object collision?

Share this post


Link to post
Share on other sites
I'm drawing a scrolling background from tiles. And I am looking how to do this (image would explain more than I can, I guess): http://imageshack.us/photo/my-images/687/unled1oav.jpg/

Share this post


Link to post
Share on other sites
I am not entirely sure, if I understand you correctly, but in my project (a Rock'n'Roll clone, currently featured in the IOTD -- /end shameless commercial), I use tiles of 32x32 pixels size. Each tile has a list (vector) of "CollisionObjects", which are smaller bounding spheres and/or AABBs or whatnot...
So, for example: If I have a tile that is 32x32 pixels, and on it is -- say -- a wall with 16x32 pixels, I'd register an AABB (Axis Aligned Bounding Box) on the tile, which is only 16x32 pixels in size.
Now, if I want to check, if a collision occurs, I will first test, if the player "touches" the tile itself (quick test). If yes, I loop through all "collision objects" of the tile and check, if a collision occurs. If yes: Bingo: I know which collision object intersects with the player and can take it from there.

HTH,
Philipp

Share this post


Link to post
Share on other sites
Beren77, that sounds great! I am at friend's at the moment, so cannot check the code, but could you also give me a small code snippet? I've tried to write the code but it failed... Maybe because of the way I define the tilemap: "int MAPDATA[MAPWIDTH*MAPHEIGHT]", although I think it was a general failure in fully understanding the concept.

P.S. Could you give me a link to your game? I'd like to see what you're creating. :)

Share this post


Link to post
Share on other sites
Hi,

ok, when I look at your declaration, I think I see your problem more clearly: You have an _int_ value for each tile. This might not be the best approach. Why not define a Tile-Class and let it handle all the routines for you?
Let's keep it simple for starters, and suppose your Tile class only contains your int-value:

[code]
class Tile {
public: Tile(int identifier) {
id = identifier;
}

virtual ~Tile() { // Nothing to do, yet...
}

private: int id;
};
[/code]

Now, your declaration becomes:

[code]
Tile *MAPDATA[MAPWIDTH * MAPHEIGHT];
[/code]

and for each Tile, you can call

[code]
MAPDATA[y * width + x] = new Tile(whatever id you wish);
[/code]

Savvy?

Now, when it comes to your collision, you "simply" add a vector of "CollisionObjects" to your Tile declaration. For example:

[code]
class Tile {
public: ...
virtual ~Tile() {
collisionObjects.clear();
}

void addCollisionObject(CollisionObject *object) {
collisionObjects.push_back(object);
// Note, you should probably check if object == 0
// and if object is already in the list...
}

bool tileCollides(int x, int y, int width, int height) {
// The parameters are just an example, you'd probably have the coordinates in your "Player" class.
// The method checks, if the rectangle from x, y to x + width - 1, y + height - 1 touches this tile...
// (also see below, for the AABB implementation; same algorithm).
}

bool hasSubCollision(int x, int y, int width, int height) {
// Checks, if any of the CollisionObjects collide with the player
for (unsigned int i = 0; i < collisionObjects.size(); i++) {
if (collisionObjects[i].hasCollision(x, y, width, height)) {
return true;
}
}
return false;
}

private: ...
std::vector <CollisionObject *> collisionObjects;
};
[/code]

And for your CollisionObjects, you could define this base class:

[code]
class CollisionObject {
public: CollisionObject() {}
virtual ~CollisionObject() {}
virtual bool hasCollision(int x, int y, int width, int height) = 0;
};
[/code]

while, finally, a concrete subclass must override the hasCollision method with actual checks. So, for example (from the top of my head, forgive any errors ;)):

[code]
class AABB : public CollisionObject {
public: AABB(int x, int y, int width, int height) : CollisionObject() {
x1 = x;
y1 = y;
x2 = x + width - 1;
y2 = y + height - 1;
}

bool hasCollision(int x, int y, int width, int height) {
return x <= x2 && (x + width - 1) >= x1 && y <= y2 && (y + height - 1) >= y1;
}
private: int x1, x2, y1, y2;
};
[/code]

Note that this is only a skeleton setup! You'll probably need more information (like: where did the collision occur? What speed did the player have? ...)

But I hope you can build up from there...

The link to Rock'n'Roll is still in the IOTD gallery, but of course, you can also check here: [url="http://www.phbouillon.de/index.php?class=Calimero_Webpage&id=23971"]http://www.phbouillo...ebpage&id=23971[/url]
Note that my collision problems do not stem from the above ideas, but have a different source: The ball still gets stuck on some walls occasionally. That happens, because it doesn't know its direction... (Long story ;)).

Enjoy!
Philipp

Share this post


Link to post
Share on other sites
[quote name='jonbonazza' timestamp='1317663149' post='4868624']
I am a little confused on what you are trying to accomplish. Initially, you mention tiles which would imply that you are working with tile maps. However, further on, you mention objects in Mario which is a platformer and, like other platformers, doesn't use tiles at all.

So my question to you is, Are you using actual tile maps or are you really just looking for simple object collision?
[/quote]

mario IS tile based

he is asking for collisions with BOTH tiles and sprite OBJECTS

is it actually that hard to grasp the meaning of the op's initial question?

Share this post


Link to post
Share on other sites
Sorry for the late reply, but I had some trouble with my machine. Yesterday it started to work again.

Anyway, I have combined the code with my code and the drawing works, however I am unable to grasp the concept of the collision detection. I can detect collision perfectly between sprites but not between map tiles and character sprites. I have tried the following:

[code]void collision()
{
for (int y=0;y<mapy;y++)
{
for (int x=0;x<mapx;x++)
{
mapxx = x * 32;
mapyy = y * 32;
int frame = tilemap[y][x];
charx = character->getX();
chary = character->getY();
int colfrm = tilemap[chary / 32][charx / 32];
if (colfrm>0])
{
col = 1;
}
else col = 0;
}
}
}[/code]

My collision detection for sprites is very easy however: "if (x == y) {}" that simply means that they collide, and in the brackets I can insert whatever code I want on the occasion IF they collide. I've tried to transform each map tile into a sprite, but I think that would be very slow, memory consuming and all that.

Thank you!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this