Tiling - I'm nearly crying

Started by
5 comments, last by Zakwayda 13 years ago
I am creating a 2d Side-scroller "engine/library" using sdl.

Hi, Can somebody PLEASE explain how I implement a tiled map in my game? I have literally been trying for hours, I just don't understand why I am finding it difficult to think about.
This is the only thing holding me back and it is so annoying!! I just wanted to try to make a simple tiled map and have some collision. The tutorial I look at, lazyfoo, seem to skip over the most important parts!

In the lazyfoo examples, I cannot find any evidence of where he assigns a surface to his tile array OR where he checks what the tileID is. So, this is how I have tried to do this:

My First Step: I have a tile class with an SDL_Rect, an int TileID and an enum TypeID(TYPE_NONE,TYPE_Solid) and also an SDL_Surface*.

Question on this: I have my map file as a .txt. With a 15x20 matrix of the numbers 1 or 0. 1 Should represent the solid type. If I check for collisions for example, do I need to check which type the tile is every loop?

My Second Step: I created a 2D array using the max number of tiles that will be in the level. Tile *tileArray[TOTAL_TILES];
My Third Step: I read the txt file using std::ifstream. I loop through the array, creating a new Tile each iteration using, tile = new Tile(x,y,tileType);.........Also, each iteration, the width is added onto X, and I then check X against the width of the screen. If X>=SCREEN_WIDTH then it will set Y+=TILE_HEIGHT.
My forth Step: I loop through the array again, this time Loading a surface for each tile using each tiles type which was entered earlier.
for(int i=0;i<TOTAL_TILES;i++)
{
tileList->load(tileList->getType());
}


This is the load function:

void Tiles::load(int typeID)
{
//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;
if(typeID == TYPE_None)
{
tile = SDL_LoadBMP("white.bmp");
}
else if(typeID == TYPE_Solid)
{
tile = SDL_LoadBMP("brick.bmp");
}

if( tile != NULL ) {
optimizedImage = SDL_DisplayFormat( tile ); //Free the old image
SDL_FreeSurface( tile ); }
tile = optimizedImage;


}

My Fifth Step: In my main game loop, I then call draw() on each tile.

void Tiles::draw()
{

SDL_BlitSurface( tile, NULL, g_SrWindow, &box );

}


Am I doing this correctly? I know I havent used the tileID, thats because I am trying it with a single 40x40 tile, not a tileset yet. Is there a better way to do this?
Important Question :): When checking for collisions with the map, I am not sure of what the logic is, can someone help me complete the following?


Loop through tile array
if(tile.x > cameras.x AND tile.x <= cameras.x+SCREEN_WIDTH)//if tile is on screen?? Would this work?
{
loop through all entities // ? This is all I can think of, but it has time complexity of O(n^2) doesnt it?
if(entity.x > cameras.x AND entity.x <= cameras.x+SCREEN_WIDTH)
{
drawAll()
if(tile.type == SOLID)
{
checkCollision()
}
else
//..........etc
}


}


I would REALLY appreciate some input here. Thanks.

Sorry I should have said, My map prints out as expected now, But I would still like your input on my methods and an answer to my questions if you will.

EDIT: I also get this error after I CLOSE the game window: Unhandled exception at 0x1048bfc8 (msvcp100d.dll) in TilingTest.exe: 0xC0000005: Access violation reading location 0xfeeefef2.
Advertisement

I am creating a 2d Side-scroller "engine/library" using sdl.

Hi, Can somebody PLEASE explain how I implement a tiled map in my game? I have literally been trying for hours, I just don't understand why I am finding it difficult to think about.
This is the only thing holding me back and it is so annoying!! I just wanted to try to make a simple tiled map and have some collision. The tutorial I look at, lazyfoo, seem to skip over the most important parts!

In the lazyfoo examples, I cannot find any evidence of where he assigns a surface to his tile array OR where he checks what the tileID is. So, this is how I have tried to do this:

My First Step: I have a tile class with an SDL_Rect, an int TileID and an enum TypeID(TYPE_NONE,TYPE_Solid) and also an SDL_Surface*.

Question on this: I have my map file as a .txt. With a 15x20 matrix of the numbers 1 or 0. 1 Should represent the solid type. If I check for collisions for example, do I need to check which type the tile is every loop?

My Second Step: I created a 2D array using the max number of tiles that will be in the level. Tile *tileArray[TOTAL_TILES];
My Third Step: I read the txt file using std::ifstream. I loop through the array, creating a new Tile each iteration using, tile = new Tile(x,y,tileType);.........Also, each iteration, the width is added onto X, and I then check X against the width of the screen. If X>=SCREEN_WIDTH then it will set Y+=TILE_HEIGHT.
My forth Step: I loop through the array again, this time Loading a surface for each tile using each tiles type which was entered earlier.
for(int i=0;i<TOTAL_TILES;i++)
{
tileList->load(tileList->getType());
}


This is the load function:

void Tiles::load(int typeID)
{
//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;
if(typeID == TYPE_None)
{
tile = SDL_LoadBMP("white.bmp");
}
else if(typeID == TYPE_Solid)
{
tile = SDL_LoadBMP("brick.bmp");
}

if( tile != NULL ) {
optimizedImage = SDL_DisplayFormat( tile ); //Free the old image
SDL_FreeSurface( tile ); }
tile = optimizedImage;


}

My Fifth Step: In my main game loop, I then call draw() on each tile.

void Tiles::draw()
{

SDL_BlitSurface( tile, NULL, g_SrWindow, &box );

}


Am I doing this correctly? I know I havent used the tileID, thats because I am trying it with a single 40x40 tile, not a tileset yet. Is there a better way to do this?
Important Question :): When checking for collisions with the map, I am not sure of what the logic is, can someone help me complete the following?


Loop through tile array
if(tile.x > cameras.x AND tile.x <= cameras.x+SCREEN_WIDTH)//if tile is on screen?? Would this work?
{
loop through all entities // ? This is all I can think of, but it has time complexity of O(n^2) doesnt it?
if(entity.x > cameras.x AND entity.x <= cameras.x+SCREEN_WIDTH)
{
drawAll()
if(tile.type == SOLID)
{
checkCollision()
}
else
//..........etc
}


}


I would REALLY appreciate some input here. Thanks.

Sorry I should have said, My map prints out as expected now, But I would still like your input on my methods and an answer to my questions if you will.

EDIT: I also get this error after I CLOSE the game window: Unhandled exception at 0x1048bfc8 (msvcp100d.dll) in TilingTest.exe: 0xC0000005: Access violation reading location 0xfeeefef2.


Ugh, I noticed you used OOP... That's a big turn away for me.

EDIT: I also get this error after I CLOSE the game window: Unhandled exception at 0x1048bfc8 (msvcp100d.dll) in TilingTest.exe: 0xC0000005: Access violation reading location 0xfeeefef2.


You're trying to access memory that no longer exist. Try running the app through the debugger and see if it tells you were exactly you're doing this. Or amke sure you're not using something that get's released when you close your app.


Ugh, I noticed you used OOP... That's a big turn away for me.


what?
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
I fixed the error, I had an array of size 200, but had 300 tiles in the end. But the rest of my posts still stands, can somebody help me out?

But the rest of my posts still stands, can somebody help me out?

I read over your post, but there are a lot of questions there :)

Can you maybe narrow it down to one question or issue that you're having trouble with? (To begin with, at least.) That might make it a little easier to provide useful feedback.


Ugh, I noticed you used OOP... That's a big turn away for me.

Hehe...care to elaborate?

[quote name='Mr.E' timestamp='1302978276' post='4799202']
But the rest of my posts still stands, can somebody help me out?

I read over your post, but there are a lot of questions there :)

Can you maybe narrow it down to one question or issue that you're having trouble with? (To begin with, at least.) That might make it a little easier to provide useful feedback.


Ugh, I noticed you used OOP... That's a big turn away for me.

Hehe...care to elaborate?
[/quote]

Thanks for your reply. I guess my main Questions are this:
1. Should I be loading each tile separately, thus meaning I have to render each separately and also check for collisions separately?
2. What is the standard technique for creating tilemaps? i.e. metadata used(what format?)....what structure to store them in? 2d array/2darray of linked lists etc.
3. What would be the standard technique for rendering and checking for collisions between entities and each tile? Obviously, checking collisions between tiles that are unreachable/not near any entities would be a waste of cpu, the same can be said for rendering tiles that are not yet visible.

I guess if I had an answer to those questions I would feel alot better about it all. I am looking to be a games programmer, and I am in my 2nd year at college. The fact that I am finding it hard to understand this is quite disheartening, seen as those big companies are making such epicly more advanced games than this.
I don't have a definite answer for you, but I get the sense you might be struggling with this a little.

Keep in mind that there are many ways to solve the kinds of problems you're talking about, many of which are equally viable. In other words, there's no one 'correct' solution, and searching for such a solution will likely just bog you down.

Here are some things to keep in mind though.

First of all, it's generally advisable to group things logically into modules, each of which has a fairly narrow scope. For example, rendering and collision detection are two fundamentally different and largely unrelated things, and should ideally operate more or less independently of each other. (The two modules will likely need to interact to some degree, but usually the degree of interaction can be kept to a minimum.)

There are various issues that usually need to be addressed with respect to both rendering and collision detection. With rendering, these issues include culling and batching; for collision detection, issues include whether broad-phase culling is needed and if so what type, and also what shapes will be used and how the narrow-phase tests will be implemented. There's also the issue of collision response, which is separate from (but related to) collision detection.

For the most part, these issues are highly context-dependent; the requirements for a top-down, 2-d tile-based RPG will be vastly different than those of a first-person 3-d game with cutting-edge graphics. I think you covered some of your requirements in your original post, but a good next step would probably be to lay out those requirements very clearly and specifically (and to post them here if you need advice regarding them).

1. Should I be loading each tile separately, thus meaning I have to render each separately and also check for collisions separately?[/quote]
I'm not sure what you mean about loading each tile separately, but generally you want to share resources where possible. That is, two 'grass' tiles, while distinct, will most likely share a reference to a single 'grass' image. Again though, rendering and collision detection are separate concerns, and what goes for one may not necessarily go for the other.

2. What is the standard technique for creating tilemaps? i.e. metadata used(what format?)....what structure to store them in? 2d array/2darray of linked lists etc.[/quote]
As long as memory constraints aren't an issue, a simple 2-d array would probably be the simplest solution. (Often such arrays are implemented using 1-d arrays under the hood, but that's an implementation detail. I would normally recommend boost::multi_array for this, but I believe it doesn't currently work correctly with Visual Studio's compiler.)

What data needs to be associated with each cell depends entirely on the nature and requirements of the game in question.

3. What would be the standard technique for rendering and checking for collisions between entities and each tile? Obviously, checking collisions between tiles that are unreachable/not near any entities would be a waste of cpu, the same can be said for rendering tiles that are not yet visible.[/quote]
Again, rendering and collision detection should generally be considered separately.

Regarding rendering, if it's a top-down or isometric game, it should be straightforward to determine what tiles are potentially visible and render only those tiles.

For collision detection, if the world is represented by a 2-d array, that can probably serve as your broad phase (that is, you can determine what entities an entity can potentially interact with by examining the surrounding cells in the array). Again though, the specifics will depend on the requirements.

This topic is closed to new replies.

Advertisement