Tiled games

Started by
5 comments, last by Khatharr 11 years, 1 month ago

Hi, I'm reading the book Programming 2D Games, it's in C++ and DirectX.

I have an idea of how to render the scene with tiles, but how do you do collision detection? The only way I can think of would be to loop though all the tiles and check for a collision, but that would be slow. How can I check for only near by collisions?

Advertisement

Hi.

Have a look at this guide

The author describes different ways of implementing a 2D platformer (including tiling and collision detection).

While the guide is quite nice, a lot of it is theoretical, not practical.

OP - the most common solution to this is called a Quadtree. Basically, as you add objects to the screen (whether colliding map tiles or other actors), you continue to divide the screen up into continually smaller regions, each containing at most N number of objects; so that, whenever you check collisions, each object only has to check collisions with N other objects. This is exponentially faster than checking the entire grid.

http://veeableful.wordpress.com/2012/02/07/algorithm-space-partitioning-using-quadtree/ <-- This guy wrote a pretty good C++ quadtree-based space partitioning lib in C++ to support what he was working on, and put it up on github. There is a decent description of the technique, with a link to a much better description, to get the technical details. If you just want the code, skip down to the Github link for the C++ version without SFML.

Happy trails.

For tile collision:

The usual approach to tile based games is having them in an array (and thus concrete locations). Now you take the location and size of your object and calculate the tiles below the corners. This obviously only works if you have tiles of the same size.

Pseudo Code:

X1 = object Location x / tile width

X2 = ( object Location x + object width ) / tile width

Y1 = object Location y / tile height

Y2 = ( object Location y + object height ) / tile height

Now you only need to loop over X1,Y1 to X2, Y2

For object collision the quad tree method talked about above is a good solution

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

@Endurion, that solution is cool, the problem with it is that all the bounds checking (e.g. only check tiles X1,Y1-X2,Y2) is done at collision time (meaning it runs every single time). It is arguably more efficient to treat your colliding map tiles (not all map tiles collide with the player) just like enemies/bullets/etc, and have them use the same collision quadtree, which is only updated when something moves.

But +1 for static arrays, an often overlooked performance winner.

@Endurion, that solution is cool, the problem with it is that all the bounds checking (e.g. only check tiles X1,Y1-X2,Y2) is done at collision time (meaning it runs every single time). It is arguably more efficient to treat your colliding map tiles (not all map tiles collide with the player) just like enemies/bullets/etc, and have them use the same collision quadtree, which is only updated when something moves.


You only need to check objects against the static tiles when they move. Tiles in an array use less data than they would in a quad tree and look-ups are faster, so a dual approach should be a good one.
For something as simple as this kind of tile-based 2D side-scroller any intelligent broad phase test is probably sufficient. Even simply excluding collidables that are offscreen should be enough for the simple reason that the number of grid-arranged tiles on the screen is fairly low. For instance, in that screenshot you have a map that's 22x14 tiles in size. If every cell was filled with a tile that's only 308 tiles. AABB testing for 308 tiles should be trivial in terms of CPU time.

As long as the collision test itself isn't insane you should be fine. If the game becomes more complex and narrow phase testing gets heavier then the broad phase becomes more important and you would want to start looking into region-based solutions, though a quadtree is probably a little overkill until you get to the point where multiple overlapping collidable tiles becomes common. Additionally, tile collision is often handled differently than entity collision, so differentiating tile collision from entity collision isn't really unreasonable.

In my experience the real CPU concern is in how aggressively you update the entity logic.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement