【问题标题】:A clean way to render things一种干净的渲染方式
【发布时间】:2012-02-10 00:24:35
【问题描述】:

我现在的渲染方式确实没有任何问题,但我觉得这不是处理渲染的好方法。我正在使用 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;

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

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 个大循环。我尝试了一次拍摄,但在循环期间调整 _world 大小时遇到​​问题,导致大量破坏。但我并没有声称我做对了! :)

我在想可能涉及线程的事情?

编辑:

啊,抱歉含糊不清。 “更清洁”是指更高效。我的方法也没有“问题”,我只是觉得有一种更有效的方法。

【问题讨论】:

  • 我不明白你的方法有什么问题。性能?
  • 这是一个很难回答的问题,主要是因为“渲染”是一个非常笼统的术语,处理它的最佳方式很大程度上取决于特定的渲染类型。此外,“最佳”是主观的:您是在谈论最高性能吗?最简单的代码?
  • 您可以考虑使用 std::remove 而不是手动循环 _delQueue。

标签: c++ algorithm rendering sdl


【解决方案1】:

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

但是,我可以猜测并说,因为您使用的是 SDL,所以您有机会开发游戏。就个人而言,我总是通过为每个活动对象设置一个渲染方法来渲染游戏对象,并使用对象管理器在每个滴答声中循环通过指向每个对象的指针并调用此渲染方法。因为不断从向量中间删除一个项目可能会由于内存的内部复制而导致速度减慢(向量保证连续的内存),你可以在每个对象中设置一个标志,当它打算被删除时,并定期设置对象manager 执行“垃圾收集”,同时删除设置了此标志的所有对象,从而减少需要完成的复制量。与此同时,在垃圾回收发生之前,管理器只是忽略了标记的对象,而不是在每个滴答声中调用它的渲染方法——就好像它已经消失了一样。它实际上与您在队列系统中所拥有的并没有太大的不同,事实上,如果游戏对象是从您的“可渲染”类派生的,它可以被认为是相同的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 2011-03-12
    • 2012-07-09
    相关资源
    最近更新 更多