Ryan Blanchard
Ryan Blanchard

Reputation: 559

Drawing "higher-level" object

So I'm using SFML for a Computer Science project - making a chess game. I have a class Square which is a single square of the chessboard - currently, it contains four vertices (four sf::Vertex objects in a member variable sf::VertexArray) and is colored either white or black. A class ChessBoard encapsulates a std::vector of Squares.

Using the tutorial given by SFML, I'm able to draw a single square. However, the draw() function works based on vertices, and since the ChessBoard class doesn't not actually contain vertices, but rather objects that themselves contain vertices, I'm not able to draw the chess board (i.e. its internal draw() function does not work).

Does anyone know how to work around this? (I can provide more info/clarification/code if necessary/helpful.)

Upvotes: 1

Views: 210

Answers (2)

Mario
Mario

Reputation: 36497

That's not really how "higher level drawing" is supposed to work.

Your parent class(es) shouldn't have to bother how to draw children. You're mixing responsibilities.

Instead, subclass sf::Drawable (and sf::Transformable, if required).

All this does is forcing you to implement a draw() member, which does all the drawing.

Here's a simple example for your ChessBoard class:

class ChessBoard : public sf::Drawable {

    void draw (RenderTarget &target, RenderStates states) const {
        for (auto &tile : mTiles) // Iterate over all board pieces
            target.draw(tile, states); // Draw them
    }
}

As you can see, this is trivial to setup. In a similar way, you can overload your Square class. (Isn't that name too generic? Why not simply reusing sf::RectangleShape?)

class ChessBoard : public sf::Drawable {

    void draw (RenderTarget &target, RenderStates states) const {
        target.draw(mVertices, states);
    }
}

So, back to your main game loop. How to draw the ChessBoard? Again, trivial:

while (window.isOpen()) {
    // All the other things happening

    window.draw(mChessBoard);
}

While the advantages of this approach might not be as obvious at first, it's pretty easy to see that you're capable of passing responsibilities down the line. For example, the ChessBoard doesn't have to know how to properly draw a Square. In a trivial example – using unicolored polygons only – it's not that easy to notice, but your code will be a lot cleaner once you start adding shaders, textures, etc. Suddenly you'd no longer just have to return a sf::VertexArray, but you'll also need pointers or references to the other ressources. So the ChessBoard would have to know, which components to request from Square to draw it properly (Does it have a shader? Do I need a texture?).

Upvotes: 2

Ryan Blanchard
Ryan Blanchard

Reputation: 559

Nevermind. Silly me. Implemented a getter inside class Square that returned the vertex array, & inside Chessboard looped through the vector of squares, calling the getter on each iteration.

Upvotes: 0

Related Questions