优化html5画布游戏

Isa*_*iah 6 javascript optimization html5 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));
};
Run Code Online (Sandbox Code Playgroud)

和这样的绘制循环:

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);
};
Run Code Online (Sandbox Code Playgroud)

我正在使用setTimeout,因为我听说如果还没有完成,setInterval会导致循环重叠.我有什么优化可以真正获得一些速度吗?特别是优化游戏循环.

我听说过一些javascript引擎一次在屏幕上获得数千个对象.我无法想象他们是如何做到这一点的,至多我可以在一台非常旧的计算机屏幕上获得多达100个对象,在合理库存的计算机上可以获得大约700个对象.而且在我完成像素完美碰撞检测和物理学之前,没有很多游戏代码在后台运行.

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

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

非常感谢

Emi*_*dın 15

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

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

  • 这个答案已经过时,部分不正确.在充分尊重的情况下,没有必要使用尺寸为2的图像.它不会让您获得性能提升.此外,clearRect比canvas.width黑客更快.(来源:http://jsperf.com/canvas-clearrect-vs-width/5) (3认同)

Sim*_*ris 13

哦,geez,如果你发布了所有的代码,我可能会在这里给你写一个完整的十四行诗.这是一个快速的概述:

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

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

我在私人文件中保存了很多其他提示,我正在写一本小型电子书.如果你想尽早访问它,我可能会允许它.

选择Zakas的高性能JavaScript并阅读它.

除非必须,否则不要像引用代码一样使用save()和restore().他们只是放慢了速度.

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

前景 - 背景 - 中间地带的多个画布绝对有帮助.在内存画布上缓存内容肯定会有所帮助.这一切都取决于你画的是什么.

许多性能问题是由于千次切割造成的死亡.例如:

        vs.scenegraph[i].update();
        vs.scenegraph[i].draw();
        vs.scenegraph[i].drawScript();
Run Code Online (Sandbox Code Playgroud)

        var scene = vs.scenegraph[i];
        scene.update();
        scene.draw();
        scene.drawScript();
Run Code Online (Sandbox Code Playgroud)

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


小智 7

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

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