Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Tiles: Questions about Layers[SOLVED]  (Read 3386 times)

0 Members and 1 Guest are viewing this topic.

Resethel

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Tiles: Questions about Layers[SOLVED]
« on: July 07, 2015, 04:02:24 pm »
Hello everyone


I'm currently working on a hexagonal tile based game and I got a little problem when it comes to layers.

Since in the game, all Layers are not forced to be drown at the same time I use only one vertexArray to stock the Layers of the map. When I have to draw all of them, I will just call my drawing function for layer-0,-1,-2,...,layer-N.

Given that each layer has a different texture, a specific texture is set for every single one of them.

The problem I got is that even with a color mask for each texture, while drown, tiles of inferior layers with no Tiles above them ( so they're theorically visible ) are not shown.

Here are my drawing functions:

bool MapManager::displayGlobalMap(sf::RenderWindow &window, int Layer)
{
    if (m_mapLoaded and Layer < m_Layers)
    {
        int tileType;
        int textureX,textureY;
       
        m_CurrentTileSet = Layer;
       
        Vector2f Center(0,0);
       
        m_vertices.setPrimitiveType(Quads);
        m_vertices.resize(m_TileNumber * 4);
       
       
        for (int j(0); j < m_MapSize.y; ++j)
        {
            for (int i(0); i < m_MapSize.x; ++i)
            {
           
                tileType = m_Map[i][j][Layer]; // le numéro de tuiles dans le set
           
           
                textureX = tileType % (LayersTilesets[Layer].getSize().x / m_TileSize.x);
                textureY = tileType / (LayersTilesets[Layer].getSize().x / m_TileSize.x);
           
           
                Vertex* quad = &m_vertices[(i + j * m_MapSize.x) * 4]; // on récupere 4 vertex(quads) que l'on va modifié
           
                Center = Vector2f(m_TileSize.x * ( (0.5*(j%2) + i) ), 0.75 * m_TileSize.y * j );
               
                // Position des vertex par rapport au centre
                quad[0].position = Center + Vector2f(+m_TileSize.x/2 , -m_TileSize.y/2);
                quad[1].position = Center + Vector2f(-m_TileSize.x/2 , -m_TileSize.y/2);
                quad[2].position = Center + Vector2f(-m_TileSize.x/2 , +m_TileSize.y/2);
                quad[3].position = Center + Vector2f(+m_TileSize.x/2 , +m_TileSize.y/2);
           
                // Texturage de la tuile
                quad[0].texCoords = sf::Vector2f(textureX * m_TileSize.x, textureY * m_TileSize.y);
                quad[1].texCoords = sf::Vector2f((textureX + 1) * m_TileSize.x, textureY * m_TileSize.y);
                quad[2].texCoords = sf::Vector2f((textureX + 1) * m_TileSize.x, (textureY + 1) * m_TileSize.y);
                quad[3].texCoords = sf::Vector2f(textureX * m_TileSize.x, (textureY + 1) * m_TileSize.y);
            }
        }
    }
   
    window.draw(*this);
    return m_mapLoaded;
}



bool MapManager::displayGlobalMap(sf::RenderWindow &window)
{
    for (int i(0); i < m_Layers; ++i)
    {
        displayGlobalMap(window, i);
    }
}


 

So i guessed it was a bad idea to stock them all in a single VertexArray/ As I understand it, while re-calling the draw function i just redefine the previous vertex, and I just erase from screen the previous layers?


In your opinion, how should I process to display them correctly? Like making multiple vertexArray but then, how do I draw them separately????

Thank you for taking the time to read my lounge post and my bad english :D
« Last Edit: July 08, 2015, 03:52:32 am by Resethel »

kitteh-warrior

  • Guest
Re: Tiles: Questions about Layers
« Reply #1 on: July 07, 2015, 05:20:02 pm »
In your opinion, how should I process to display them correctly? Like making multiple vertexArray but then, how do I draw them separately????

It is up to you how it is done (but putting everything of the ground into one draw call every frame would be a bit of processing). If you have multiple sf::VertexArray's, you would just have multiple draw calls...

Like so:
sf::VertexArray va1;
sf::VertexArray va2;
sf::VertexArray va3;
renderWindow.draw(va1);
renderWindow.draw(va2);
renderWindow.draw(va3);

In this case, va1...va3 would be the layers.

Quote from: Resethel
As I understand it, while re-calling the draw function i just redefine the previous vertex, and I just erase from screen the previous layers?

Yes. Reconstructing a sf::VertexArray every frame during the drawing isn't the best way to go about doing this, for most occasions. Make the sf::VertexArray a property of the class, and update it that way.

A possible way to do this would be (breaking down what is to be done using rough non-UML UML):

Layer (inherited from sf::Drawable)
    (**This is optional, whereas it would essentially be a re-implementation of sf::VertexArray, only more specific to this design by only drawing the things within the view of the parent Map)
    parent : Map* (the parent map)
    draw() const: void (puts each vertex within the view of the parent into the vertex array and draws it, this should probably be broken into two functions)

Map (inherited from sf::Drawable)
    layers : std::array<Layer, 5> (this example specifically talks about 5 layers)
    draw() const: void (draws each layer to the render target)
    updateView() : void (updates the views of each)
 

In this example, Map has the single purpose of storing and controlling access to the Layer's (the model and controller). Layers have the single purpose of being what is in such a layer (abstracted to also contain only displaying what is visible). You could also abstract Map to contain all of the non-layered objects (possibly entities?), it depends on your use of what it is.

Quote from: Resethel
When I have to draw all of them, I will just call my drawing function for layer-0,-1,-2,...,layer-N.

Try storing all of the sf::VertexArray's into a std::vertex (or std::array if you specifically know how many layers to will be), and then when you want to draw the layer, provide the corresponding sf::VertexArray for the layer being drawn.

Also, classes that are call "*Managers" represent a bad programming design. A class should generally have a single purpose. I recommend structuring out all of the components of your project on paper, and either come up with a better more specific name or break what is does into smaller classes. (see my above example for a new possible design)

Another small thing, I would put into the sf::VertexArray's things that are currently visible via the sf::RenderWindow's view, to avoid unnecessary processing.

Quote from: Resethel
tileType = m_Map[i][j][Layer]

Nested arrays/vectors are not very efficient. Instead, single dimensional array. An example of that can be found here(<this is a link, people don't seem to notice the difference in colours, apparently).

Quote from: Resethel
The problem I got is that even with a color mask for each texture, while drown, tiles of inferior layers with no Tiles above them ( so they're theorically visible ) are not shown.

This may be due to the fact that you aren't checking to see if there is a tile in the layer prior to adding the quad to the sf::VertexArray for that layer. Though, I do not recommend at all to keep using the name "MapManager" for the class. Redesigning this class to be more specific will help you notice mistakes and problems much more clearly, because that class only accesses this, and this is only accessed by that class, in which case logic errors can be easily isolated.

Quote from: Resethel
I'm currently working on a hexagonal tile based game and I got a little problem when it comes to layers.

You are drawing hexagons which quads? ???

Resethel

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Re: Tiles: Questions about Layers
« Reply #2 on: July 07, 2015, 06:10:28 pm »
It is up to you how it is done (but putting everything of the ground into one draw call every frame would be a bit of processing). If you have multiple sf::VertexArray's, you would just have multiple draw calls...

Like so:
sf::VertexArray va1;
sf::VertexArray va2;
sf::VertexArray va3;
renderWindow.draw(va1);
renderWindow.draw(va2);
renderWindow.draw(va3);

In this case, va1...va3 would be the layers.

Erf, I should have known it was that simple!  :-X


Quote from:  kitteh-warrior
Yes. Reconstructing a sf::VertexArray every frame during the drawing isn't the best way to go about doing this, for most occasions. Make the sf::VertexArray a property of the class, and update it that way.

A possible way to do this would be (breaking down what is to be done using rough non-UML UML):

Layer (inherited from sf::Drawable)
    (**This is optional, whereas it would essentially be a re-implementation of sf::VertexArray, only more specific to this design by only drawing the things within the view of the parent Map)
    parent : Map* (the parent map)
    draw() const: void (puts each vertex within the view of the parent into the vertex array and draws it, this should probably be broken into two functions)

Map (inherited from sf::Drawable)
    layers : std::array<Layer, 5> (this example specifically talks about 5 layers)
    draw() const: void (draws each layer to the render target)
    updateView() : void (updates the views of each)
 

So you're advising me to create a specific class derived from sf::Drawable who manage Layers and make a pointer, pointing on the parent Map class? And the Map class containing the N-Layer in a std::array ( because I know how many layer there will be before compilation time )
Because in fact I've done a specific class too Manage the view and another similar fonction who draws what is within the view, and it seemed to worked pretty fine ^^ so it would make me restart from scratch :(. But I'll give it a try ,following your way which seems way more clean and optimized than mine!!!!



Quote from: kitteh-warrior
Also, classes that are call "*Managers" represent a bad programming design. A class should generally have a single purpose. I recommend structuring out all of the components of your project on paper, and either come up with a better more specific name or break what is does into smaller classes. (see my above example for a new possible design)

I always feared really little classes, coming from C language I'm still not so used to classes :( . I already made a whole class diagram and such for the whole game, I just didn't cut them in smaller pieces! Thanks a lot for your advice I'll reconsider the whole thing!


Quote from: kitteh-warrior
Nested arrays/vectors are not very efficient. Instead, single dimensional array. An example of that can be found here(<this is a link, people don't seem to notice the difference in colours, apparently).

I used a dynamic arrays for it since the map size will not change. I actually know how to convert N-d arrays into a single D one, but is the difference in perfomances really that noticeable?

Quote from: kitteh-warrior
You are drawing hexagons which quads? ???


xD yea it seems a bit akward but it allow me to use only 4 vertex instead of minimum 6, I just make them overlap a bit and here is the result:
(click to show/hide)


And mostly because rendering 3 to4 times 4billion instead of 3 to 4 times 6(or more)billion vertex might be greater ^^ ( even if with the occlusion culling it's way smaller )


Well thanks a lot for your advices!!!
« Last Edit: July 07, 2015, 06:13:37 pm by Resethel »

kitteh-warrior

  • Guest
Re: Tiles: Questions about Layers
« Reply #3 on: July 07, 2015, 06:55:21 pm »
I actually know how to convert N-d arrays into a single D one, but is the difference in perfomances really that noticeable?
Quote from: Resethel
rendering 3 to4 times 4billion

If you weren't going through so many at once, then it wouldn't have that much of an effect, but with billions of loops, there would be a noticeable amount. Also, like I said, you only need to draw what is visible (typically), so don't draw something outside of the render window's view, unless you have a reason for it.

Quote from: Resethel
I used a dynamic arrays for it since the map size will not change.

If the map size will not change, use a static array. Dynamic should be used when it is changing after compile time. The link I gave was just representing how you could do the calculation. std::vector<>'s can be worked with the exact same way.

Quote from: Resethel
[...]manage Layers[...]
Not manage. Manage is far too ambiguous of a word. Manage could refer to controlling the lifetime of the objects, which may not be the case.

Quote from: Resethel
I'm still not so used to classes
Not to sound rude or anything, but get used to them. ;) They are one of the most important features of C++. Imagine if you designed a class called FordCar. And from there, you put every piece of code required for FordCar to accelerate, steer, change gears, etc. Now when you make a new class called FiatCar, you would have to reinvent the wheel (not an intentional pun), by creating all of these functions again.

The more efficient way to do it is to break it into it's small components:
Transmission
Wheels
Steering Wheel
Axles
etc.
Then you should make an abstract BaseCar class, which all cars should inherit from. You could also make an abstract BaseCompany class, and have the companies inherit from that, and attach a BaseCompany child class to the BaseCar child class.

I recommend looking into some good C++ books if you do not understand this. (as this is now almost nothing to do with SFML)

Resethel

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Re: Tiles: Questions about Layers
« Reply #4 on: July 07, 2015, 07:26:42 pm »
Woo I should have correct some of my answer they seems rude and I'm sorry about that  :'(


Quote from: kitteh-warrior
(click to show/hide)


I think i can see the picture: as for example for the scene related scene i could:
Create some basic classes like:
       Map
       Scene
       View
       Layers
       Cursor

Make Layers members of a Map
And then make the Scene, which handle what the player can see, handle a Map, a View, and a Cursor


Once again a lot of thanks, I'll study a bit more before continuing, and thanks for the link to the books! :D