Hi all, I looked at the vertex array tutorial, and I got the example up and running in regards to the tilemap loader. However, I'm having a little bit of trouble understanding exactly what a few parts of the code do.
First of all, I'm not sure what tu or tv is; but in debugging, I noticed that tu is always equal to tileNumber, and tv is always equal to 0.
I'm also unsure about the parameter list of quad[2] and quad[3]. I'm not sure why it works, unless the tileSize.y refers the bottom of the tile, and not the top.
Anyway, here's my code with comments added in to help me understand.
If possible, could you please read it, and where i have comments tell me how those specific parts work?
Thanks
!
//Create a class called tilemap, and inheret sf::Drawable and sf::Transformable
//i.e. TileMap class can use the methods from Drawable and Transformable directly.
class TileMap : public sf::Drawable, public sf::Transformable
{
public:
//load the tilemap.
//Param1 is the filename.
//Param2 is the tile size (i.e. 40 by 40).
//Param 3 is an int array with the level format. Explained later.
//Param 4 and 5 are the width and height of the level. (Imagine it like a grid; 16 accross, 8 down, etc.)
bool load(const std::string& tileset, sf::Vector2u tileSize, const int* tiles, unsigned int width, unsigned int height)
{
// load the tileset texture
if (!m_tileset.loadFromFile(tileset))
return false;
// resize the vertex array to fit the level size
m_vertices.setPrimitiveType(sf::Quads); //a quad is simply two trianges put together
m_vertices.resize(width * height * 4); //resize the vertex array so it can hold all the tiles
//must be * 4 or higher... I assume its bcause there are 4 parts to a quad.
// populate the vertex array, with one quad per tile
// loop through the width and height of the level
for (unsigned int i = 0; i < width; ++i)
for (unsigned int j = 0; j < height; ++j)
{
// get the current tile number
//Read TOP to BOTTOM, THEN LEFT TO RIGHT.
//Width = 16. Height = 8.
//1st element 1st row index = 0 + (0 * 16). 0.
//1st element 2nd row index = 1 + (0 * 16). 16.
//2nd element 1st row index = 1 + (0 * 16). 1.
//2nd element 2nd row index = (1 + (1 * 16). 17.
//and so on.
int tileNumber = tiles[i + j * width];
// find its position in the tileset texture
int tu = tileNumber % (m_tileset.getSize().x / tileSize.x); //gets the tile number from top to bottom.
//tu could simply be equal to tileNumber
tu = tileNumber;
int tv = tileNumber / (m_tileset.getSize().x / tileSize.x); //tv appears to be always 0?
//tv could simply be equal to 0.
std::cout << tu << std::endl;
// get a pointer to the current tile's quad
//it's a reference to the element inside the m_vertices array, so it also changes m_vertices value.
sf::Vertex* quad = &m_vertices[(i + j * width) * 4];
// define its 4 corners
//Get the positions of each corner, in a clockwise direction.
//i and j represent each ENTIRE tile.
quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
// define its 4 texture coordinates
//quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
//quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
//quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
//quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
quad[0].texCoords = sf::Vector2f(tu * tileSize.x, 0); //texture starts at top left
quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, 0); //texture ends at top right (i.e. top left of next tile, hence the +1)
quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tileSize.y); //I'm assuming tileSize.y is the BOTTOM of the tile.
quad[3].texCoords = sf::Vector2f(tu * tileSize.x, tileSize.y); //Otherwise, why would it work by simply having tileSize.y?
}
return true;
}
private:
//this virtual function is simply so we don't have to do window.draw(target, states), we can just do window.draw(instance)
//this is called polymorphism?
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// apply the transform
//this isn't our method, i assume it's something in draw() by default.
//or this generates the finished quads in one image instead of multiple ones.
states.transform *= getTransform();
// apply the tileset texture
//this puts the texture on to what we're going to draw (which is converted in to a single texture)
states.texture = &m_tileset;
// draw the vertex array
target.draw(m_vertices, states);
}
sf::VertexArray m_vertices;
sf::Texture m_tileset;
};