Precise collision detection on tile maps and object drawing

Started by
9 comments, last by GamDev 12 years, 6 months ago
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!
Advertisement
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?

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?


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.
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?
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
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/
However, further on, you mention objects in Mario which is a platformer and, like other platformers, doesn't use tiles at all.[/quote]

Btw, Mario games do use tiles.
"Do, or do not. There is no try." - Yoda
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
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. :)
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:


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

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

private: int id;
};


Now, your declaration becomes:


Tile *MAPDATA[MAPWIDTH * MAPHEIGHT];


and for each Tile, you can call


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


Savvy?

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


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.hasCollision(x, y, width, height)) {
return true;
}
}
return false;
}

private: ...
std::vector <CollisionObject *> collisionObjects;
};


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


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


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 ;)):


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;
};


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: http://www.phbouillo...ebpage&id=23971
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

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?


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?

This topic is closed to new replies.

Advertisement