这并不是“高级绘图”应该如何工作的。
您的父类不必费心如何绘制孩子。你在混合职责。
改为子类sf::Drawable(和sf::Transformable,如果需要)。
所有这一切都迫使你实现一个draw() 成员,它完成了所有的绘图。
这是您的 ChessBoard 类的一个简单示例:
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
}
}
如您所见,这很容易设置。以类似的方式,您可以重载 Square 类。 (这个名字是不是太笼统了?为什么不简单地重用sf::RectangleShape?)
class ChessBoard : public sf::Drawable {
void draw (RenderTarget &target, RenderStates states) const {
target.draw(mVertices, states);
}
}
那么,回到你的主游戏循环。如何绘制ChessBoard?再次,微不足道:
while (window.isOpen()) {
// All the other things happening
window.draw(mChessBoard);
}
虽然这种方法的优势一开始可能不那么明显,但很容易看出您有能力将职责向下传递。例如,ChessBoard 不必知道如何正确绘制Square。在一个简单的例子中——只使用单色多边形——这并不容易被注意到,但是一旦你开始添加着色器、纹理等,你的代码会干净得多。突然间你不再需要返回一个sf::VertexArray,但您还需要指向其他资源的指针或引用。所以ChessBoard 必须知道,要从Square 请求哪些组件才能正确绘制它(它有着色器吗?我需要纹理吗?)。