Javascript 优化HTML5画布游戏循环

Javascript 优化HTML5画布游戏循环,javascript,optimization,html5-canvas,Javascript,Optimization,Html5 Canvas,我目前正在制作一个HTML5游戏,我正在尝试在画布上绘制各种各样的东西。我的游戏基本上就是在一个无限的区域内移动,但我不知道如何优化我的代码,以便在屏幕上绘制灌木丛。它工作正常,但滞后很多,我知道有办法优化它。以下是我当前的代码: for(var x=offset[0];x许多年前,由于计算机的速度不如今天,你必须做一些繁重的数学运算,比如计算正弦或余弦,甚至模,只有一个选择: 不必每次都计算它,只需计算一次并将其存储在一个巨大的查找表中。查找值当然比计算快得多 所以在你的例子中,我建议为x和y

我目前正在制作一个HTML5游戏,我正在尝试在画布上绘制各种各样的东西。我的游戏基本上就是在一个无限的区域内移动,但我不知道如何优化我的代码,以便在屏幕上绘制灌木丛。它工作正常,但滞后很多,我知道有办法优化它。以下是我当前的代码:


for(var x=offset[0];x许多年前,由于计算机的速度不如今天,你必须做一些繁重的数学运算,比如计算正弦或余弦,甚至模,只有一个选择:

不必每次都计算它,只需计算一次并将其存储在一个巨大的查找表中。查找值当然比计算快得多

所以在你的例子中,我建议为x和y的模生成两个数组

let xModulo = [];
let yModulo = [];
for (let a = 0; a < canvas.width; a++) {
  xModulo.push(a % 85);
}
for (let a = 0; a < canvas.height; a++) {
  yModulo.push(a % 85);
}
这将显著提高性能。根据需要,您可能需要将canvas.width/canvas.height更改为更高的值。
你甚至可以考虑为单纯形噪声生成一个查找表。

许多年前,由于计算机没有像现在这样快,你不得不做一些很重要的数学运算,比如计算正弦或余弦,或者甚至是模-只有一个选项:

不必每次都计算它,只需计算一次并将其存储在一个巨大的查找表中。查找值当然比计算快得多

所以在你的例子中,我建议为x和y的模生成两个数组

let xModulo = [];
let yModulo = [];
for (let a = 0; a < canvas.width; a++) {
  xModulo.push(a % 85);
}
for (let a = 0; a < canvas.height; a++) {
  yModulo.push(a % 85);
}
这将显著提高性能。根据需要,您可能需要将canvas.width/canvas.height更改为更高的值。 你甚至可以考虑为单纯形噪声生成一个查找表。 条件会减慢代码的速度。如果可能的话,你应该尽量避免它们

例如排队

if(x%85==0&&y%85==0&&noise.simplex2(x,y)==0){

…意味着您要对
if
语句进行85*85(7225)次求值,每次求值的树数少于一棵,这是大量不必要的开销

  • 删除那些7224次无用的迭代

  • 通过在变量中存储重复的数组查找,尽可能避免索引数组

  • 简化你的数学。例如
    ((x-offset[0])*-1)+canvas.width
    可以简化为
    canvas.width-x+offset[0]

  • 尽可能多地卸载到GPU上。默认情况下,所有位置计算都是通过GPU上的转换完成的,因此上述数学可以在循环之前完成一次

  • 性能的一般规则是,通过将可以的代码移到循环外,减少循环内的代码量

下面的代码段实现了以上几点

由于您没有提供有关偏移量和画布大小范围的详细信息,下面的代码可以进一步优化

    var x, y;
    const STEP = 85;
    const offsetX = offset[0];
    const offsetY = offset[1];
    const startX =  Math.floor(offsetX / STEP) * STEP;
    const startY = Math.floor(offsetY / STEP) * STEP;
    const endX = startX + canvas.width;
    const endY = startY + canvas.height;
    ctx.setTransform(1, 0, 0, 1, canvas.width - offsetX, canvas.height - offsetY);
    
    for (x = startX; x < endX; x += STEP) {
        for (y = startY; y < endY; y += STEP) {
            if (noise.simplex2(x, y) == 0) {
                ctx.drawImage(treeimage, x, y);
            }
        }
    }
    // reset transform
    ctx.setTransform(1, 0, 0, 1, 0, 0);
var x,y;
常数步长=85;
常数offsetX=偏移量[0];
常量偏移量=偏移量[1];
常数startX=数学楼层(偏移量/步长)*步长;
常数起始=数学楼层(偏移/台阶)*台阶;
const endX=startX+canvas.width;
const endY=startY+canvas.height;
setTransform(1,0,0,1,canvas.width-offsetX,canvas.height-offsetY);
对于(x=startX;x
考虑一下 对
simplex2
的调用可能会非常慢。我所看到的所有实现都做得非常糟糕。由于simplex对于任何坐标都是常量,因此在游戏开始之前,每个坐标只能执行一次(在生产代码之外)

因为你想要一个无限(like)的游戏场(无限是不可能的),RAM需求太大了。除了……放弃无限,对游戏场大小设置一个实际的限制,这将允许你创建一个地图,让它飞起来。

7225无意义的操作每幅图像 条件会减慢代码的速度。如果可能的话,你应该尽量避免它们

例如排队

if(x%85==0&&y%85==0&&noise.simplex2(x,y)==0){

…意味着您要对
if
语句进行85*85(7225)次求值,每次求值的树数少于一棵,这是大量不必要的开销

  • 删除那些7224次无用的迭代

  • 通过在变量中存储重复的数组查找,尽可能避免索引数组

  • 简化你的数学。例如
    ((x-offset[0])*-1)+canvas.width
    可以简化为
    canvas.width-x+offset[0]

  • 尽可能多地卸载到GPU上。默认情况下,所有位置计算都是通过GPU上的转换完成的,因此上述数学可以在循环之前完成一次

  • 性能的一般规则是,通过将可以的代码移到循环外,减少循环内的代码量

下面的代码段实现了以上几点

由于您没有提供有关偏移量和画布大小范围的详细信息,下面的代码可以进一步优化

    var x, y;
    const STEP = 85;
    const offsetX = offset[0];
    const offsetY = offset[1];
    const startX =  Math.floor(offsetX / STEP) * STEP;
    const startY = Math.floor(offsetY / STEP) * STEP;
    const endX = startX + canvas.width;
    const endY = startY + canvas.height;
    ctx.setTransform(1, 0, 0, 1, canvas.width - offsetX, canvas.height - offsetY);
    
    for (x = startX; x < endX; x += STEP) {
        for (y = startY; y < endY; y += STEP) {
            if (noise.simplex2(x, y) == 0) {
                ctx.drawImage(treeimage, x, y);
            }
        }
    }
    // reset transform
    ctx.setTransform(1, 0, 0, 1, 0, 0);
var x,y;
常数步长=85;
常数offsetX=偏移量[0];
常量偏移量=偏移量[1];
常数startX=数学楼层(偏移量/步长)*步长;
常数起始=数学楼层(偏移/台阶)*台阶;
const endX=startX+canvas.width;
const endY=startY+canvas.height;
setTransform(1,0,0,1,canvas.width-offsetX,canvas.height-offsetY);
对于(x=startX;x