【问题标题】:Modifier inside update function HTML5 Canvas Game?更新功能HTML5 Canvas Game里面的修饰符?
【发布时间】:2014-03-04 19:08:52
【问题描述】:

我在 HTML5、Canvas 游戏的更新函数中看到了这种结构,带有一个“修饰符”变量:

function update(modifier) {
    obj.x += obj.speed * modifier
    obj.y += obj.speed * modifier
}

function main() {
    var thisLoop = new Date
    var delta = thisLoop - lastLoop
    update(delta / 1000)
    render()
    var lastLoop = new Date
}

var lastLoop = new Date
setInterval(main, 1)

现在我自己使用这个结构:

function update() {
    obj.x += obj.speed
    obj.y += obj.speed

    render()

    window.requestAnimationFrame(update)
}

第一个结构中的“修饰符”应该做什么?

其中哪一个最好用,或者是否也有“修饰符”和“requestAnimationFrame”的结构?

【问题讨论】:

    标签: javascript html loops canvas


    【解决方案1】:

    如果您需要将动画锁定到时间,那么您需要一种方法来补偿可变帧速率,例如可变帧速率,当然每帧之间也有可变时间。

    可以使用修改器(因为它没有显示它是如何计算的)通过补偿这种变化来微调速度/运动。

    有几件事:不要使用诸如短时间间隔 (1),因为这可能会产生总体负面影响 - 无论如何,您将无法以比帧速率更快的速度更新任何内容,因此请使用不低于16 毫秒。

    尝试使用 requestAnimationFrame (rAF),因为这是唯一能够实际同步到监视器更新的机制。 rAF 还会传递一个高分辨率时间戳,您可以将其用于补偿器。

    例如:

    在 60 FPS 时,您预计一帧将持续大约 16.67 毫秒。

    所以修饰符可以设置为:

    modifier = timeElapsed / 16.67;
    

    如果框架能够按时运行,理论上该值为 1。

    modifier = 16.67 / 16.67 = 1;
    

    现在,如果帧迭代由于某种原因需要更多时间,例如双精度,您将获得 2 作为修饰符的值。

    modifier = 33.34 / 16.67 = 2;
    

    这在实际中是如何体现的?

    如果您需要每帧移动 100 像素,那么在我们准时的第一种情况下:

    modifier = 16.67 / 16.67 = 1;
    vx = 100 * modifier = 100;     // @ 1 frame  = 100 pixels / frame
    

    在第二种情况下,我们花费了两帧,这意味着我们需要它移动 200 像素,但由于我们没有在中间获得该帧,我们需要使用修改器来补偿:

    modifier = 33.34 / 16.67 = 2;
    vx = 100 * modifier = 200;     // @ 2 frames = 100 pixels / frame
    

    因此,您可以在此处看到,即使帧速率发生变化,我们仍会移动我们期望移动的内容。

    要计算经过的时间,只需使用 rAF 参数:

    var oldTime = 0                             // old time
        frameTime = 1000 / 60;                  // frame time, based on 60 FPS, in ms
    
    function loop(time) {
    
        var timeElapsed = time - oldTime;       // get difference
        oldTime = time;                         // store current time as old time
    
        var modifier = timeElapsed / frameTime; // get modifier based on FPS
    
        ...
    
        requestAnimationFrame(loop);
    }
    

    现在,所有这些 - 修饰符可能只是一个用于控制速度的值... :-)

    【讨论】:

      【解决方案2】:

      较新版本的 requestAnimationFrame 将返回动画开始后经过的时间。

      您可以使用此经过的时间来确定应在何处重绘动画对象。

      例如,假设您有一个带有x 属性的球对象,表明它是x 坐标。

      如果您希望球每 1000 毫秒向右移动 10 个像素,您可以这样做(未经测试!):

      // set the starting x-coordinate of the ball
      
      var ballStartingX=50;
      
      ball.x=ballStartingX;
      
      // get the time when the animation is started
      
      var startingTime = performance.now();
      
      // start the animation
      
      requestAnimationFrame(update);
      
      // update() is the animation loop function
      
      function update(timestamp){
      
          // request another frame
      
          requestAnimationFrame(update);
      
          // reposition the ball
          // (timestamp-startTime) is the milliseconds elapsed
      
          ball.x = ballStartingX + 10 * (timestamp-startTime)/1000;
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-23
        • 2011-10-15
        相关资源
        最近更新 更多