一种干净的渲染方式

A clean way to render things

本文关键字:方式 一种      更新时间:2023-10-16

我现在的渲染方式没有任何问题,但我觉得这不是一种很好的渲染方式。我正在使用SDL。

归根结底,我有一些抽象类

class Renderable

具有两个功能。

virtual void update() = 0;
virtual void doRender(SDL_Surface* surface) = 0;

我有另一类

class RenderManager

带1个std::vector

std::vector<Renderable*> _world;

和2个CCD_ 2

std::queue<Renderable*> _addQueue;
std::queue<Renderable*> _delQueue;

这两个队列包含需要在下一次勾选中添加的可渲染对象和需要删除的可渲染内容。一次完成所有事情给我带来了问题,现在我想起来,这是有道理的(至少我的做法是这样的)。

Renderables可以静态地在RenderManager中添加和删除它们自己。

这里或多或少是处理一切的函数。

void renderAll() {
    std::vector<Renderable*>::iterator begin, end;
    begin = _world.begin();
    end = _world.end();
    for (;begin != end; ++begin) {
        (*begin)->update();
        (*begin)->doRender(_mainWindow); // _mainWindow is the screen of course
    }
    begin = world.begin();
    if (_delQueue.size() > 0) {
        for (unsigned int i = 0; i < _delQueue.size(); i++) {
            std::vector<Renderable*>::iterator del;
            del = std::find(begin, end, _delQueue.front());
            if (del != end) {
                delete *del;
                _world.erase(del);
            }
            _delQueue.pop();
        }
    }
    if (_addQueue.size() > 0) {
        for (unsigned int i = 0; i < _addQueue.size(); i++) {
            Renderable* front = _addQueue.front();
            // _placement is a property of Renderable calculated by RenderManager
            // where they can choose the level they want to be rendered on.
            _world.insert(begin + front->_placement, front);
            _addQueue.pop();
        }
    }
}

我对C++有点陌生,但我想我至少在平均水平上了解它。我甚至是SDL的新手,但它看起来很简单,很容易学习。我很担心,因为我有三个大循环。我尝试了一次拍摄,但在循环过程中,我遇到了调整世界大小的问题,导致了大量的破坏。但我并不是说我做得对!:)

我在想可能有什么线索?

编辑:

啊,很抱歉有歧义。我所说的"更清洁"是指更高效。我的方法也没有"问题",我只是觉得有一种更有效的方法。

首先,我想说不要修复未损坏的东西。您是否遇到性能问题?除非你在每帧中都大量添加和删除"可渲染对象",否则我看不出你所拥有的有什么大问题。当然,就整体应用程序而言,这可能是一个笨拙的设计,但你还没有说明这是用于什么类型的应用程序,所以很难判断,如果不是不可能的话。

然而,我可以猜测并说,因为你正在使用SDL,所以你有可能正在开发一款游戏。就我个人而言,我一直通过为每个活动对象提供一个渲染方法来渲染游戏对象,并使用对象管理器在每个刻度循环遍历指向每个对象的指针,并调用此渲染方法。由于不断从矢量中间删除一个项可能会由于内存的内部复制而导致速度减慢(矢量保证连续内存),因此您可以在每个对象中都有一个标志,该标志是在要删除时设置的,并且对象管理器会定期执行"垃圾收集",同时删除所有设置了该标志的对象,从而减少了需要进行的复制量。同时,在垃圾收集发生之前,管理器只是忽略标记的对象,而不是每次调用其呈现方法——就好像它已经消失了一样。事实上,它与您的队列系统没有太大的不同,事实上,如果游戏对象是从您的"可渲染"类派生的,它可以被认为是相同的。

顺便问一下,在访问队列的元素之前查询队列大小有什么原因吗?如果size()为0,则for循环无论如何都不会运行。