游戏物理-如何加快这种移动算法?在Javascript中




我在JS中有一个由16个台球组成的数组,希望每个球都能以其方向和速度平稳移动
为此,我设置了一个计时器,每42ms调用UpdateThis()(每秒24帧)
问题是UpdateThis()以53ms作为萤火虫状态。
现在UpdateThis在每个球上迭代并调用UpdateBall(ball)
我认为问题就在那里
UpdateBall看起来像这样:

function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
    //ball moving!
    for(var i = 0; i < balls.length; i++) {
        //CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
    }
    var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
    if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
        ball.direction = VMul(ball.direction, -1); //Invert direction
        ball.speed *= 1;
        ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
    }
    ball.position = ps;
    ball.MoveTo(); //See explanation at the bottom.
    ball.speed *= GRK; //Gravity
    if(ball.speed < 0.05) {
        ball.speed = 0;
    }
  }
}

似乎大部分时间都花在ball.MoveTo()上,它看起来像这样:

function() 
{
     this.image.style.left = this.position.x + "px";
     this.image.style.top = this.position.y + "px"; 
}


--更新--

function UpdateThis() {
    for(var i = 0; i < balls.length; i++) {
         var cur = balls[i];
         UpdateBall(cur);
         balls[i] = cur;
    }
  }

加载看起来像

nx = setInterval(function() { UpdateThis(); }, 42);

有人对如何加快速度有什么想法吗?

--更新2-

您可以在此处下载带有HTML文件的文件夹(密码为密码)

将位置更新从图形中分离出来怎么样?所以有这样的东西(未经测试的代码):

function DrawBall(ball)
{
    ball.MoveTo(); //Take this line out of UpdateBall
}

-

function UpdateThis() {
    for(var i = 0; i < balls.length; i++) {
         var cur = balls[i];
         UpdateBall(cur);
         balls[i] = cur;
    }
}

-

function DrawThis() {
    for(var i = 0; i < balls.length; i++) {
         DrawBall(balls[i]);
    }
    setTimeout(function() { DrawThis(); }, 42);
}

-

nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);

如果确实是位置的移动很慢,那么逻辑更新仍然发生在42ms,帧速率不快于42ms,但它可以跳过帧。(我实际上还没有尝试过,所以这都是理论上的,你可能需要调整一些东西)

为什么移动可能(而且很可能)很慢

移动功能可能很慢,因为它要做的事情比简单的变量分配多。它必须实际将某个元素渲染到其他位置。如果你在IE9上运行这个,你可以测试它。我预计它应该运行得更快,因为它使用硬件视频加速。

至于另一个程序,我希望其他人能仔细分析一下

您的问题

  1. 你能描述一下球是如何移动的吗?零星如何为每个球调用UpdateBall()?你把这些电话排队吗?

  2. 提供VMulVAdd功能

  3. 你玩过造型吗?也许球的直接父对象的相对位置可以加快渲染速度。并在其上设置overflow:hidden。我不知道。这取决于你是如何做到的。因此,JSFiddle会很有帮助。

一个建议

与其使用setInterval来调用函数,不如将它们排队,让它们以最快的速度执行。因此,为中央setInterval提供一些观察程序,使其不会运行得太快。

但我想它仍然100%利用你的处理器,这无论如何都不好。

非常重要的注意事项:不要在启用Firebug时运行应用程序,因为众所周知,当Firebug运行时,Javascript执行速度要慢得多。

如果MoveTo()实际上是你的瓶颈,那就很难了,因为那里并没有发生太多事情。我现在唯一能想到的就是

1) 缓存图像的样式属性和位置以加快查找速度。每次你在对象链中看到一个点,它都需要遍历作用域链。理想情况下,您可以在构造MoveTo()的父级时缓存此属性。

2) 是否需要"px"字符串?它可能会导致无效的CSS规范,但它可能仍然有效。我很难相信2个字符串凹陷会真的改变这么多。

这里的主要问题可能是,无论何时更改DOM,浏览器都会重新流化整个页面。您唯一的其他选择可能是重构,这样您就可以删除以前的内容,并用描述新状态的文档片段替换它,而不是更改样式。这将导致整个步骤只有2次回流(1次用于移除,1次用于添加),而不是每个球2次。

编辑:关于上面的#1,当我说缓存时,我的意思并不仅仅是在函数调用中的本地。但可能是作为父对象中的闭包。例如:

var Ball = function(img){
    var style = img.style;
    var posX;
    var posY;
    function MoveTo(){
        style.left = posX + "px";
        style.right = posY + "px"; 
    }
};

最新更新