一种简洁的渲染方式

时间:2012-02-10 00:24:36

标签: c++ algorithm rendering sdl

我现在渲染的方式并没有任何问题,但我觉得这不是处理渲染的好方法。我正在使用SDL。

归结为此我有一些抽象类

class Renderable

有两个功能。

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

我有另一个班级

class RenderManager

使用1 std::vector

std::vector<Renderable*> _world;

和2 std::queue

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

这两个队列包含需要在下一个tick中添加的可渲染项和需要删除的渲染项。一次性完成所有事情给了我一些问题,现在我想到了它,它是有道理的(至少我做的方式)。

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更新,但它看起来非常简单易学。我很担心,因为我有3个大循环。我尝试过一次击球,但是我在循环过程中遇到了大量的破坏问题。但我不是说我做对了! :)

我在考虑涉及线程的事情?

编辑:

啊,抱歉模糊不清。 “更干净”我的意思是更有效率。我的方法也没有“问题”,我觉得有一种更有效的方法。

1 个答案:

答案 0 :(得分:0)

首先,我要说的是不要修复一些没有破坏的东西。您是否遇到性能问题?除非你每帧都大量添加和删除'renderables',否则我看不到你所拥有的大问题。当然,就整体应用而言,它可能是一种笨拙的设计,但你没有说明这是什么类型的应用,所以判断很难,甚至不可能。

然而,我可以猜测并说因为你正在使用SDL,你可能正在开发一款游戏。我个人总是通过为每个活动对象提供一个render方法来渲染游戏对象,并使用一个对象管理器在每个tick中循环遍历每个对象的指针并调用这个render方法。因为从向量中间不断删除项目会导致内存复制导致速度变慢(向量保证连续内存),所以在每个要删除的对象中都可以有一个标记,并定期对象manager执行'垃圾收集',删除同时设置此标志的所有对象,从而减少需要完成的复制量。在垃圾收集发生之前的平均时间内,管理器只是忽略标记的对象,而不是每次调用它的渲染方法 - 就像它已经消失一样。它实际上与您在队列系统中所拥有的内容并没有太大不同,事实上如果游戏对象来自您的“可渲染”类,则可以认为它是相同的。

顺便提一下,在访问元素之前是否有任何理由要查询队列大小?如果size()为0,for循环将无法运行。