Need help with making a tile map (SDL)

Hello!

I'm making a 2D rpg game. Right now am I using one large background image that I move around the screen to make the scrolling effect. Since it's one large background image, it use a lot of memory and it's also a very bad way to make a game. Therefore I want to make a tile map instead. The problem is that I dont know how to make one. I have tried many tutorials, but I find them a bit confusing. If someone could tell me how to create a simple tile map, maybe give me some examples, that would be nice.
Well, making a tiled map works something like this:

You have your map data stored in a file that you read in. the file may look something like this: (there is a nice map editor named Tiled to make a file like this, (http://www.mapeditor.org/))
1
2
3
4
5
6
7
8
1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 1
1 0 0 0 0 0 2 1
1 0 0 0 0 0 1 1
1 0 0 0 0 1 1 1
1 3 0 0 1 1 1 1
1 0 0 1 1 1 1 1
1 1 1 1 1 1 1 1

Now 1 could be a Wall, 0 could be nothing and 2 could be the goal and 3 could be the spawn point of your Character

You then you read the file in a 2D Map Array with the amount of Tiles in your map and you have the width and height of each block stored somewhere.
Then have a enumeration of Tiles you use (for example: NOTHING, WALL, GOAL, SPAWN)
1
2
3
4
5
enum Tile{ NOTHING, WALL, KILL, NTILES };
SDL_Textures (*Textures)[NTILES];
const int TILES_X = 50; const int TILES_Y = 50; //50x50 map
const int TILE_SIZE_X = 32; const int TILE_SIZE_Y = 32; // each block 32x32 pix
Tile MAP[TILES_X][TILES_Y];


And since you use SDL you could just make a class for all of the code above to make everything easier and more readable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Tile
{ 
//// If you split your code in *.cpp and *.h file you should put the members and the enum as far down as possible to make it more beautiful
public: 
    enum ETile { NOTHING, WALL, KILL, NTILES };

    static const int SIZE_X;
    static const int SIZE_Y;

private:
    static SDL_Texture (*pTextures)[NTILES]; // Array of pointer, point to the textures you want your tiles to look like
    SDL_Rect mRenderRect; /// Rectangle you draw to

public:
    Tile() 
    { 
        mRenderRect.w = SIZE_X; mRenderRect.h = SIZE_Y; 
    }
    void InitTextures() 
    { 
        /* Load the Textures you want your tiles to be */
    }

    ETile tile; // Which tile is this?

    void render(int PositionX, int PositionY)
    { 
        mRenderRect.x = PositionX; mRenderRect.y = PositionY;
        SDL_Render(mpRenderer, &pTextures[tile], NULL, &DestRect() ) 
    }
}; 
int Tile::SIZE_X = 32;
int Tile::SIZE_Y = 32;

SDL_Texture (*Tile::pTextures)[NTILES];

// somewhere in main.cpp
const int TILES_X = 50; 
const int TILES_Y = 50; //50x50 map
Tile MAP[TILES_X][TILES_Y];


Then you will have something like a viewport (mostly the upper left corner of the screen you want to see at the moment and the size)
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T>
class Vector2
{
public:
    T x;
    T y;
}; 
class Viewport
{
public:
    Vector2<int> position;
    Vector2<int> size;
};


And now you just Render all your tiles
1
2
3
4
5
6
7
8
9
10
11
12
for(int y = 0; y < TILES_Y; ++y)
    for(int x = 0; x < TILES_X; ++x)
    {        
        Vector2<int> position;
        position.x = x*Tiles::SIZE_X;
        position.y = y*Tiles::SIZE_Y;
        if((position.x + Tiles::SIZE_X > Viewport.x && 
            position.x - Tiles::SIZE_X < ViewPort.position.x + ViewPort.size.x) && 
            (position.y + Tiles::SIZE_Y > Viewport.x && 
            position.y - Tiles::SIZE_Y < ViewPort.position.y + ViewPort.size.y)) // check if the Tile is currently visible
            MAP[x][y].render(position.x, position.y);
    }


How to calculate the viewport position is up to you ;)
Note that the amount of memory used here is equal to the amoutn of different tiles you use
Last edited on
Thanks it helped a lot :D

But I have still two more questions. How could I import the tile map from a text file outside using the ifstream to load it into the program and afterwards display it?

I would also like to know if it's possible to make the tiles as a SDL Surface and use the blitting method to display the tile map. Since I'm quite new with SDL and therefore most experienced with working with surfaces and blitting.
Well, regarding the first question a look at the fstream library ifstream class will help (http://www.cplusplus.com/reference/fstream/ifstream/)
I'd store a 2D field as std::vector< std::vector< std::string > > svvMap to make it dynamically resizeable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::ifstream file("Level1.txt");

if (file.is_open()) 
{
    std::string line;
    std::string tile;
    std::vector< int > TileLine;

    while (std::getline(file, line)
   {
        /// Get the Data in the current line to TileLine

       std::string dummy;
       for(int i = 0; i < line.size(); ++i)
       {
             /// If line[i] != ' ' Get Data in current dummy
             /// otherwise make TileLine.push_back(itoa(dummy.c_str() ); or        
            ///something else to convert string to int
       }
        svvMap.push_back(TileLine); /// For each line push a new Vector Line to the Map 
   }
}
else 
   std::cout << "Error opening file";



As for question 2, sure it is possible, just replace the Textures with SDL_Surfaces and the SDL_Render(...) with SDL_BlitSurface and change the parameters accordingly :)

But since you are new code allways will help you so here's an answer from me a few days ago for you to see how you could use SDL_Renderer and SDL_Textures ;)
(http://www.cplusplus.com/forum/general/156922/ - 3rd last comment)
Topic archived. No new replies allowed.