Can you please explain some of this code to me

Ok So i'm learning SFML and I learned how to make a program that gets a grid from a text document and puts graphics from a sprite sheet on it, but there are some things I dont understand:

Here is the code

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <vector>
#include <sstream>
#include <SFML/Graphics.hpp>

using namespace std;

int main()
{
    ifstream openfile("Overworld.txt");

    sf::Texture tileTexture;
    sf::Sprite tiles;
    vector<vector<sf::Vector2i> > map;
    vector<sf::Vector2i> tempMap;

    if(openfile.is_open())
    {
        string tileLocation;
        openfile >> tileLocation;
        tileTexture.loadFromFile(tileLocation);
        tiles.setTexture(tileTexture);
        while(!openfile.eof())
        {
            string str, value;
            getline(openfile, str);
            stringstream stream(str);

            while(getline(stream, value, ' '))
            {
                if(value.length() > 0)
                {
                    string xx = value.substr(0, value.find(','));
                    string yy = value.substr(value.find(',') + 1);

                    int x, y, i, j;
                    for(i = 0; i < xx.length(); i++)
                    {
                        if(!isdigit(xx[i]))
                        {
                            break;
                        }
                    }
                    for(j = 0; j < yy.length(); j++)
                    {
                        if(!isdigit(yy[j]))
                        {
                            break;
                        }
                    }

                    x = (i == xx.length() ? atoi(xx.c_str()) : -1);
                    y = (j == yy.length() ? atoi(yy.c_str()) : -1);

                    tempMap.push_back(sf::Vector2i(x, y));
                }
            }

            map.push_back(tempMap);
            tempMap.clear();
        }
    }

    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Loading Tile Maps");

    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                {
                    window.close();
                }break;
                case sf::Event::Resized:
                {
                    sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                    window.setView(sf::View(visibleArea));
                }break;

            }
        }
        window.clear(sf::Color(0, 240, 255));

        for(int i = 0; i < map.size(); i++)
        {
            for(int j = 0; j < map[i].size(); j++)
            {
                if(map[i][j].x != -1 && map[i][j].y != -1)
                {
                    tiles.setPosition(j * 32, i * 32);
                    tiles.setTextureRect(sf::IntRect(map[i][j].x * 32, map[i][j].y * 32, 32, 32));
                    window.draw(tiles);
                }
            }
        }

        window.display();
    }
}


Here is the contents of the text docuemnt:

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
tiles.png
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,4 0,4 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,4 0,4 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,4 0,4 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,4 0,4 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,4 0,4 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 5,0 5,0 5,0 5,0 5,0 5,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0


Here is the code I dont understand starting from the top down:

1. stringstream stream(str);

I assume stringstream is putting the entire contents of the text file, the map, into the str variable in memory, right?

2. while(getline(stream, value, ' '))

So if i understand this correctly, this is getting the entire contents of the file, it is storing everything in stream, storing 0,0 in value and ' ' adds a space to it, right?

3. if(value.length() > 0)

If there is a value, so saying if the map is no empty, then do the next part, right?

4.
1
2
string xx = value.substr(0, value.find(','));
string yy = value.substr(value.find(',') + 1);


So on this im not exactly sure what's going on, I have a vague idea but if you could elaborate please it would help a lot.

5.
1
2
3
4
5
6
7
8
for(i = 0; i < xx.length(); i++)
{
   if(!isdigit(xx[i])){break;}
}
for(j = 0; j < yy.length(); j++)
{
    if(!isdigit(yy[j])){break;}
}


So this the row and column length of the map is drawn right? It's checking to see if the character is a decimal digit, and if it isn't then it doesnt draw anything right?

6.
1
2
x = (i == xx.length() ? atoi(xx.c_str()) : -1);
y = (j == yy.length() ? atoi(yy.c_str()) : -1);


I'm not too sure about this either, I dont know much about the ? : operator, I never even used it myself, I looked at the C++ documentation on it and i dont quite understand it still. But i know atoi converts a string to an integer.

7.
1
2
3
tempMap.push_back(sf::Vector2i(x, y));
map.push_back(tempMap);
tempMap.clear();


I know that this is putting the x and y values in the tempMap vector. and then it pushes it back to the main map vector and then clears the temp one.

8.
1
2
3
4
5
6
7
8
9
10
11
12
 for(int i = 0; i < map.size(); i++)
        {
            for(int j = 0; j < map[i].size(); j++)
            {
                if(map[i][j].x != -1 && map[i][j].y != -1)
                {
                    tiles.setPosition(j * 32, i * 32);
                    tiles.setTextureRect(sf::IntRect(map[i][j].x * 32, map[i][j].y * 32, 32, 32));
                    window.draw(tiles);
                }
            }
        }


This is outputting the vector map and setting the tiles to it. can you explain it a little more though please?



Also at this line: while(getline(stream, value, ' ')) is it getting one line at a time or the entire contents of the file?
1. str already contains a single line from the file. An std::stringstream is created and the line is copied into it.
2. Read from stream into value from the current position on the stream up to the next newline or the next space, whichever comes first.
3. If the value that was read is something that could be valid. Probably to guard against copying an empty string when the stream is just before the end.
4. substr() is a common function throughout many programming languages. The first parameter is an initial index from which to start copying. The second parameter is optional and is the length of the returned string. If it's not present, the entire string after the initial index is returned. Interpretations differ on what to do if str.size() < initial_index + length.
6. (true ? x : y) == x. (false ? x : y) == y.
So str holds tiles.png?
No. Line 23 reads one word from the file. That word is "tiles.png" in your example data.

The str contains an entire line (of numbers). The read occurs within a loop.
Ah i see, ok well that text being in the file is screwing up my map so I need to load it from a different file. Here are the contents of my file.

Overworld:tiles.png

There is the name and the tile sheet, the code below is supposed to find the ':' and for storing the world name, it should delete the : and the contents to the right of it, and vice versa for storing the tile set, but I cant seem to get it working. What do I do?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(mapList.is_open())
    {
        while(!openfile.eof())
        {
            while(getline(mapList, line))
            {
                position = line.find(":");
                cout << position << endl;
                line.erase(line.begin() + position, line.end() - line.length() / position);
                mapName = line;
                cout << mapName << endl;
            }
        }
    }
Ok so I think I ay have gotten it, it seems to work, but let me know if there is an easier way to do it, or if im doing something wrong.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(mapList.is_open())
    {
        while(!openfile.eof())
        {
            while(getline(mapList, line))
            {
                    position = line.find(":");

                    cout << position << endl;
                    mapName = line.substr(position + 1);
                    cout << mapName << endl;
                    tileName = line.substr(0, line.find(":"));
                    cout << tileName << endl;
            }
        }
    }
You find() on line 7, so repeating the search on line 12 is unnecessary: position is still valid.

However, you don't validate the position at all. What if position is 0 or there is no ':' in the input?
Topic archived. No new replies allowed.