[SFML] How do I load tilemaps in c++

How do I load tile maps in c++? Currently what I have tried to do is have an array with integers that specify a value eg 1 = ground, 0 = stone etc. and loop through the array to draw the tiles on screen.

int main()
{
sf::RenderWindow window(sf::VideoMode(1336, 768), "Blah");

sf::Sprite ground;
sf::Texture groundTex;
groundTex.loadFromFile("C:/Users/fad/Documents/maps/ground.png");
ground.setTexture(groundTex);

int map[5][5] = {
0,1,1,1,0,
1,0,0,1,0,
0,1,1,0,0,
1,0,0,1,0,
0,1,1,0,1
};

while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}

for (int h = 0; h < 5; h++)
{
for (int w = 0; w < 5; w++)
{
if (map[w][h] == 1)
{
window.draw(ground);
}
}
}

window.clear();
window.display();
}

return 0;

}

When I run it, the ground doesnt get rendered on screen. How can I make it render
on screen?
Last edited on
How do I load tile maps in c++?

The first thing you can do is start checking return values.

http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1Texture.php#a8e1b56eabfe33e2e0e1cb03712c7fcc7

Notice what the return value represents?

[Edit: Also, change the position of the sprite to where you want to draw it. Also, calling clear after you draw stuff to the window is kind of counter-productive.]
Last edited on
OK, I can now render the ground properly. But only 1 sprite of ground is rendered while I want it to render the sprite whenever there is a 1 in my array. How can I do that?
deniedanull wrote:
only 1 sprite of ground is rendered while I want it to render the sprite whenever there is a 1 in my array. How can I do that?
cire wrote:
Also, change the position of the sprite to where you want to draw it.

Alternatively, store sprites in the array with the positions already correctly set. Sprites are lightweight critters made for that sort of thing.

Could you give me an example on how that would work? Like each individual sprite should have a position?
Resetting sprite position:
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
41
42
43
44
45
46
47
48
49
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(1336, 768), "Blah");

    sf::Sprite ground;
    sf::Texture groundTex;
    if (!groundTex.loadFromFile(""C:/Users/fad/Documents/maps/ground.png""))
        return 0;

    ground.setTexture(groundTex);

    int map[5][5] = {
        0,1,1,1,0,
        1,0,0,1,0,
        0,1,1,0,0,
        1,0,0,1,0,
        0,1,1,0,1
    };

    auto gbounds = ground.getGlobalBounds();

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();

        for (int h = 0; h < 5; h++)
        {
            for (int w = 0; w < 5; w++)
            {
                if (map[w][h] == 1)
                {
                    ground.setPosition({ gbounds.width * w, gbounds.height *h });
                    window.draw(ground);
                }
            }
        }

        window.display();
    }
}


With an array of sprites:
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
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <SFML/Graphics.hpp>
#include <vector>

int main()
{
    sf::RenderWindow window(sf::VideoMode(1336, 768), "Blah");

    sf::Texture groundTex;
    if (!groundTex.loadFromFile("C:/Users/fad/Documents/maps/ground.png"))
        return 0;

    int map[5][5] = {
        0,1,1,1,0,
        1,0,0,1,0,
        0,1,1,0,0,
        1,0,0,1,0,
        0,1,1,0,1
    };

    auto gbounds = groundTex.getSize();
    std::vector<sf::Sprite> sprites;
    sprites.reserve(5 * 5);

    for (unsigned y = 0; y < 5; ++y)
    {
        for (unsigned x = 0; x < 5; ++x)
        {
            if (map[x][y] == 1)
            {
                sprites.resize(sprites.size() + 1);
                sprites.back().setTexture(groundTex);
                sprites.back().setPosition({ gbounds.x*float(x), gbounds.y*float(y) });
            }
        }
    }

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();

        for (auto& sprite : sprites)
            window.draw(sprite);

        window.display();
    }
}


Thanks a lot! It works now. i was wondering if there was a better method to do this than what I'm currently doing. Like using a vertex array or something like that?
Last edited on
Like using a vertex array or something like that?

There's a fairly straightforward example here:
http://www.sfml-dev.org/tutorials/2.3/graphics-vertex-array.php#example-tile-map
Yeah, I'll check it out later. Right now I'm having problems with collision. I tried to do
ground.getGlobalBounds().intersects(sprite.getGlobalBounds()) but it only registers the collision if I have less than 3 tiles. What can I do? Thanks in advance.
ground.getGlobalBounds() suggests that you're using the first method, where you set one sprite to different positions. All of those positions must be checked for collisions, so you would have to do something similar to the loop where they are drawn to the window to check them all for collisions.
Thanks, But I solved it like this:

if (map[w][h] == 1)
{
ground.setPosition({ gbounds.width * w, gbounds.height *h });
if (ground.getGlobalBounds().intersects(player.getGlobalBounds()))
{
player.move(0, -10.0f);
}
window.draw(ground);
}
Topic archived. No new replies allowed.