简体   繁体   English

更新功能HTML5 Canvas Game中的修饰符?

[英]Modifier inside update function HTML5 Canvas Game?

I've seen this kinda structure inside the update function in HTML5, Canvas games, with a "modifier" variable: 我已经在HTML5 Canvas游戏的update函数中看到了这种结构,带有“修饰符”变量:

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)

Now I use myself this structure: 现在,我使用以下结构:

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

    render()

    window.requestAnimationFrame(update)
}

What is the "modifier" supposed to do in the first structure? 第一种结构中的“修饰符”应该做什么?

And which one of them is the best to use, or is there maybe structure with both "modifier" and "requestAnimationFrame" too? 哪一个是最适合使用的,或者也可能同时包含“ modifier”和“ requestAnimationFrame”的结构?

If you need your animation to be locked to time then you need a way to compensate for for example variable frame rates which of course then also have variable time between each frame. 如果您需要将动画锁定到某个时间,则需要一种方法来补偿例如可变帧速率,当然,在每个帧之间还具有可变时间。

A modifier could (as it's not shown how it is calculated) be used to fine-tune the speed/movement by compensating for this variation. 可以使用一个修改器(因为它没有显示它是如何计算的)通过补偿这种变化来微调速度/运动。

A couple of things though: don't use such as short time interval (1) as this could have an overall negative effect - you won't be able to update anything faster than the frame rate anyways so use nothing less than 16 ms. 不过,有两件事:不要使用较短的时间间隔(1),因为这可能会对整体产生负面影响-无论如何,您将无法以比帧速率更快的速度进行更新,因此请使用不超过16毫秒的时间。

Try to use requestAnimationFrame (rAF) instead as this is the only mechanism able to actually synchronize to the monitor update. 尝试改用requestAnimationFrame(rAF),因为这是唯一能够实际与监视器更新同步的机制。 rAF also passes a high-resolution timestamp which you can use for the compensator. rAF还传递了高分辨率时间戳,您可以将其用作补偿器。

For example: 例如:

At 60 FPS you would expect a frame to last about 16.67ms. 在60 FPS时,您希望帧持续约16.67ms。

So a modifier could be set as: 因此可以将修饰符设置为:

modifier = timeElapsed / 16.67;

If frame was able to run on time the value would be 1 in theory. 如果框架能够按时运行,则理论上该值为1。

modifier = 16.67 / 16.67 = 1;

Now, if a frame iteration for some reason took more time, for example the double, you would get 2 as value for modifier. 现在,如果由于某种原因而进行的帧迭代花费了更多时间(例如,两倍),则修饰符的值将为2。

modifier = 33.34 / 16.67 = 2;

How does this manifest in practical terms? 在实际中这如何体现?

If you needed to move 100 pixels per frame then in the first situation when we were on time: 如果您需要每帧移动100像素,则在第一种情况下我们准时到达:

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

In the second case we spent two frames which means we needed it to move 200 pixels but since we didn't get that frame in between we need to use the modifier to compensate: 在第二种情况下,我们花费了两个帧,这意味着我们需要它移动200个像素,但是由于我们之间没有得到该帧,我们需要使用修饰符来进行补偿:

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

So here you see even if the frame rate was variant we moved what we expected to move anyways. 因此,即使帧率是可变的,在这里您也可以看到我们无论如何都可以移动。

To calculate time elapsed simply use the rAF argument: 要计算经过的时间,只需使用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);
}

Now, all that being said - modifier could also be just a value used to control speed... :-) 现在,所有所说的-修饰符可以只是用于控制速度的值... :-)

The newer version of requestAnimationFrame will return an elapsed time since the animation began. 较新版本的requestAnimationFrame将返回自动画开始起经过的时间。

You can use this elapsed time to determine where your animated objects should be redrawn. 您可以使用这段经过的时间来确定应在何处重绘动画对象。

For example, assume you have a ball object with an x property indicating it's x-coordinate. 例如,假设您有一个带有x属性的球对象,该对象指示其x坐标。

If you want the ball to move 10 pixels right every 1000ms you can do this (untested!): 如果您希望球每1000ms向右移动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;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM