为什么这段代码在火狐浏览器上运行缓慢?

3

我写了一个简单游戏的代码。在Chrome和Safari中,代码以60 fps运行,但Firefox仅能达到30-40 fps。我觉得代码看起来很简单。是什么原因导致了延迟?

我在Firebug中进行了检查,发现只有一个函数“follow”占用了所有时间。以下是代码:

function checkCollision (ball0, ball1) {
    var dx = ball1.X - ball0.X,
        dy = ball1.Y - ball0.Y,
        dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < ball0.rad + ball1.rad) {
      var angle = Math.atan2(dy, dx),
          sin = Math.sin(angle),
          cos = Math.cos(angle);

          var pos0 = {x: 0, y: 0}, 
          pos1 = rotate(dx, dy, sin, cos, true),
          vel0 = rotate(ball0.spdX, ball0.spdY, sin, cos, true),
          vel1 = rotate(ball1.spdX, ball1.spdY, sin, cos, true),
          vxTotal = vel0.x - vel1.x;
      vel0.x = ((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) /
               (ball0.mass + ball1.mass);
      vel1.x = vxTotal + vel0.x;
      var absV = Math.abs(vel0.x) + Math.abs(vel1.x),
          overlap = (ball0.rad + ball1.rad) - Math.abs(pos0.x - pos1.x);
      pos0.x += vel0.x / absV * overlap;
      pos1.x += vel1.x / absV * overlap;
      //rotate positions back
      var pos0F = rotate(pos0.x, pos0.y, sin, cos, false),
          pos1F = rotate(pos1.x, pos1.y, sin, cos, false);
      ball1.X = ball0.X + pos1F.x;
      ball1.Y = ball0.Y + pos1F.y;
      ball0.X = ball0.X + pos0F.x;
      ball0.Y = ball0.Y + pos0F.y;
      var vel0F = rotate(vel0.x, vel0.y, sin, cos, false),
          vel1F = rotate(vel1.x, vel1.y, sin, cos, false);
      ball0.spdX = vel0F.x;
      ball0.spdY = vel0F.y;
      ball1.spdX = vel1F.x;
      ball1.spdY = vel1F.y;
    }
}

function move()
{
    var side,i;
    for (i=0 ; i < balls.length; i++)
    {   
        var obj = balls[i];
        if (side=obj.edgeX())
        {
            if (side === 'l')
                obj.X = obj.rad;
            else if (side === 'r')
                obj.X = canvas.width() - obj.rad;
            obj.spdX*=-1;
        }
        if (side=obj.edgeY())
        {
            if (side === 't')
                obj.Y = obj.rad;
            else if (side === 'b')
                obj.Y = canvas.height() - obj.rad;
            obj.spdY*=-1;
        }

        if (leash == true && i === 0)
        {
            if (mouse.X>obj.X && (obj.spdX<10))
                obj.spdX+=obj.accX;
            else if (mouse.X<obj.X && (obj.spdX>-10))
                obj.spdX-=obj.accX;
            if (mouse.Y>obj.Y && (obj.spdY<10))
                obj.spdY+=obj.accY;
            else if (mouse.Y<obj.Y && (obj.spdY>-10))
                obj.spdY-=obj.accY;
        }


        obj.X+=obj.spdX;
        obj.Y+=obj.spdY;
        if (Math.abs(obj.spdX)>0.1)
            obj.spdX*=0.98;
        else obj.spdX=0;
        if (Math.abs(obj.spdY)>0.1)
            obj.spdY*=0.98;
        else obj.spdY = 0;
    };
}

function follow()
{
    var ballA, i, ballB,j;
    requestAnimationFrame(follow);
    //stats.begin();
    context.clearRect(0,0,canvas.width(),canvas.height());

    move();
    for (i = 0, len = balls.length - 1; i < len; i++) {
          ballA = balls[i];
          for (j = i + 1; j < balls.length; j++) {
            ballB = balls[j];
            checkCollision(ballA, ballB);
          }
     }
    balls.forEach(function(obj){
        drawCircle(obj.X,obj.Y,obj.rad, obj.color);
        if (leash == true && obj.control === true)
        {drawLeash(mouse.X,mouse.Y,obj.X,obj.Y,obj.color);}
    });
    //stats.end();
};

这是动画链接:http://ipsumturpis.xtreemhost.com/follower/index.html,它与IT技术相关。

http://ipsumturpis.xtreemhost.com/follower/index.html这个页面无法正常显示,因为缺少Stats对象...有没有可能提供一个能够展示问题的可用页面? - Boris Zbarsky
修复了链接和问题。请再次检查。 - Arsalan Ahmad
嗯,你是怎么测量帧率的?我观察了一下,火狐浏览器和谷歌浏览器的表现看起来差不多呢。 - Boris Zbarsky
2个回答

2

我模糊地记得在FF中存在有关画布绘制性能的问题,因此我已注释掉drawCircle(obj.X,obj.Y,obj.rad, obj.color);,神奇的事情发生了 - 我的帧率从11 FPS提高到了60。


1

尝试将球的长度缓存到一个变量中。除非出于我看不到的原因绝对必要,否则在循环的每次迭代中运行balls.length(或任何函数)自然会耗费时间。

因此,请尝试像这样做:

ballslen = balls.length;
for (j = i + 1; j < ballslen; j++)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接