【问题标题】:Optimizing html5 canvas game优化html5画布游戏
【发布时间】:2011-12-02 16:16:12
【问题描述】:

现在我正在制作的游戏中有两个游戏循环。一个循环遍历屏幕上的对象数组的绘制循环和一个执行游戏逻辑的逻辑循环。我的逻辑循环比绘图循环运行了大约 10 帧。我之所以这样设置,是因为执行游戏逻辑可能需要更长的时间,而且我不希望它干扰绘图循环。

我的逻辑循环是这样设置的:

vs.logicloop = function(){
    vs.Gameloop();
    //do the updating of object scripts
    if(vs.windowActive){
        var l = vs.scenegraph.length;
        var i = 0;
        while(i < l){
            vs.scenegraph[i].logicScript();
            i++;
        }
    }
    //restart loop
    setTimeout(vs.logicloop, 1000/(vs.fps+10));
};

和这样的绘制循环:

vs.drawloop = function(){
    //clear the screen
    vsd.clr();
    //goes through everything in the scene
    //graph and draws it and runs each object's
    //personal draw code
    if(vs.windowActive){
        var l = vs.scenegraph.length;
        var i = 0;
        while(i < l){
            vs.ctx.save();
            vs.scenegraph[i].update();
            vs.scenegraph[i].draw();
            vs.scenegraph[i].drawScript();
            vs.ctx.restore();
            i++;
        }
    }
    //restart loop
    setTimeout(vs.drawloop, 1000/vs.fps);
};

我使用 setTimeout 是因为我听说 setInterval 会导致循环重叠,如果一个还没有完成。 我可以做一些优化来真正提高速度吗?尤其是优化游戏循环。

我听说过一些 javascript 引擎会同时在屏幕上显示数千个对象。我无法想象他们是如何做到的,在一台非常旧的计算机上最多可以在屏幕上显示 100 个对象,而在一台库存充足的计算机上最多可以显示大约 700 个对象。这还没有在后台运行大量游戏代码,在我研究出如何进行像素完美碰撞检测和物理之前。

我的过程是在每次绘制循环时在画布上绘制背景色填充矩形,然后遍历所有对象并绘制它们的绘制代码。它也不会尝试将对象绘制到视野之外。

这是我的第一份带薪工作,我真的很想给人留下深刻印象。另外,一旦我完成游戏,我就可以保留引擎的所有权。

非常感谢

【问题讨论】:

  • 评论是多余的,浏览器会为你做缓冲:)
  • 我进行了一些搜索,听说使用多个画布会有所帮助,我想我也会尝试一下,但我真的很想听听有关让游戏循环运行得更快的任何意见跨度>
  • 你支持哪些浏览器?

标签: javascript html optimization canvas


【解决方案1】:
  • 如果您对精灵坐标使用浮动值,请尝试将它们转换为整数。这将使您失去亚像素渲染,但您会获得很多速度。
  • 不要使用奇数宽度的图像。始终使用宽度作为 2 的幂。
  • 这在某些情况下很难实现,但如果您的游戏适合,请不要清除屏幕并每帧重绘所有内容。而是绘制更改的部分。
  • 如果您必须清除画布,请不要绘制空白矩形。尝试使用相同大小再次设置画布宽度/高度。这应该比矩形绘图更快地重置像素。

我可以建议的其他方法不依赖于 HTML5 画布,而是一般主题,例如在可能的情况下使用位移、逆循环和运算符而不是模数、预计算等。

【讨论】:

  • 此答案已过时且部分不正确。恕我直言,没有必要使用尺寸为 2 次方的图像。它不会为您带来任何性能提升。此外, clearRect 比 canvas.width hack 更快。 (来源:jsperf.com/canvas-clearrect-vs-width/5
  • 当我写这些建议时,我亲自在 IE、Chrome 和 FF 上做了一些测试。 IE 和 Chrome 在 canvas width hack 上的表现都更好,而 FF 在 Windows 平台上的速度几乎相同。所以,这不是一个未经测试的记忆建议,而是一个经过测试的建议。随着时间的推移,clearRect 成为了一个更好的解决方案,这是正确的。
  • 当谈到使用非二次幂 (NPOT) 宽度图像时,我仍然建议不要使用它们。因为canvas使用的是硬件加速,而且很多显卡驱动不喜欢NPOT纹理。如果您使用 WebGL 尝试 NPOT 图像,您可能会看到一个空白矩形。 NPOT 图像与画布一起使用的原因是浏览器通过解决方法来处理 NPOT 图像,并将它们放在两个大小的缓冲区中,这意味着失去 CPU 时间。如果我说“NPOT 图像在画布中不起作用”那将是错误的。最好不要使用它们,因为它们的速度较慢,因为图形卡的性质。
  • 在硬件加速的 Canvas 环境中,当您使用具有 POT 尺寸的图像时,仍然没有性能提升。如果您认为有,请随时发布证明。 ;) 我知道 POT 尺寸的优点 btw。我以前用 C++ 和 OpenGL 制作过游戏。它们只是目前不适用于浏览器内的 Canvas。
  • 当有硬件加速的时候,如果你对显卡如何处理纹理有基本的了解,你就不需要知道浏览器是如何处理的。因此,如果 NPOT 纹理无法像 WebGL 有时发生的那样渲染,您可以清楚地看到副作用。当它接受任何大小的纹理时,您必须了解他们为此创建了一些解决方法,即使仅在初始化阶段也会减慢执行速度。我不会在这里搜索链接或检查浏览器源代码来证明某事(我没有那么多空闲时间)但我可以给你一些链接。
【解决方案2】:

哦,天哪,如果您发布所有代码,我可能会在这里为您写一首完整的十四行诗。以下是简要介绍:

阅读埃米尔的回答。所有这些都很好,除了最后一个非常依赖于情况。在某些浏览器上设置 canvas.width = canvas.width 以清除画布可能会更快,但它也会破坏所有画布状态(即最后设置的填充和字体),这可能会减慢速度,因为设置这些属性实际上非常缓慢。

阅读我关于 Canvas 性能的文章:http://simonsarris.com/blog/tag/performance

我在一个私人文档中保存了许多其他提示,我正在用这些文档编写一本小型电子书。如果您想提前访问它,我可能会允许。

拿起 Zakas 的High performance JavaScript 阅读。

除非您必须,否则不要像引用代码中那样使用 save() 和 restore()。他们只是在放慢速度。

有关计时器,请参阅http://paulirish.com/2011/requestanimationframe-for-smart-animating/

前景-背景-中间背景的多个画布绝对可以提供帮助。在内存画布上缓存东西肯定会有所帮助。这完全取决于您要绘制的内容。

很多性能问题都是由于一千个微小的削减造成的。例如:

        vs.scenegraph[i].update();
        vs.scenegraph[i].draw();
        vs.scenegraph[i].drawScript();

        var scene = vs.scenegraph[i];
        scene.update();
        scene.draw();
        scene.drawScript();

将有助于 分钟 的数量。我不知道你有多少机会获得微量的东西 - 我们需要看到更多的代码。

【讨论】:

    【解决方案3】:

    我听说 setInterval 如果一个还没有完成,会导致循环重叠。

    这是错误的,JavaScript 是单线程的。这意味着如果您的第一个间隔在到达下一步时仍在运行,则下一步将延迟到第一步完成计算。这也意味着,如果您开始进行大量计算,您就不能依赖 setInterval 来准确。

    【讨论】:

      【解决方案4】:

      我会回应其他人所说的大部分内容。整数值,使用请求动画帧等。如果绘制文本要小心设置字体的频率。此外,如果您每帧创建大量临时对象,您可能会发现使用对象池会有所帮助。

      作为游戏循环的一般读物,我建议:http://www.koonsolo.com/news/dewitters-gameloop/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 2013-06-08
        • 1970-01-01
        • 1970-01-01
        • 2017-08-15
        相关资源
        最近更新 更多