优化html5画布游戏

时间:2011-10-07 00:37:36

标签: javascript html5 optimization canvas

现在,我正在制作的游戏中有两个游戏循环。一个绘制循环,循环通过屏幕上的对象数组和一个执行游戏逻辑的逻辑循环。我的逻辑循环比draw循环运行大约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个对象。而且在我完成像素完美碰撞检测和物理学之前,没有很多游戏代码在后台运行。

我的过程是在画布上绘制每个绘制循环的背景颜色fillRect,然后循环遍历所有对象并绘制它们的绘制代码。此外,它不会尝试在视图之外绘制对象。

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

非常感谢

4 个答案:

答案 0 :(得分:15)

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

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

答案 1 :(得分:13)

哦,天啊,如果你张贴了所有的代码,我可能会在这里给你写一个完整的十四行诗。这是一个快速的概述:

阅读Emir的回答。所有这些都很好,除了最后一个非常依赖于这种情况。在某些浏览器上设置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();

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

答案 2 :(得分:7)

  

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

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

答案 3 :(得分:0)

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

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