JavaScript time-based animation algorithm

Source: Internet
Author: User
Tags setinterval

Turn from: 1190000002416071

Objective

Some time ago bored or had a chat to do a few mobile side of the HTML5 game. Put on a different mobile platform for testing after the strange discovery, some mobile phone animation will be "fast" a little, some mobile phone animation will be "slow" a bit, some slow still not one or two points.

By finding the data, it is found that the frame-based algorithm (frame-based) to achieve the animation will cause different frame rate of the platform experience inconsistent, and time-based (time-based) animation algorithm can be a good way to improve the situation, so that the different frame rate can achieve a more uniform speed experience.

This paper introduces the difference between frame-based animation algorithm and time-based animation algorithm, and the improvement of time-based algorithm.

Frame-based animation algorithm (frame-based)

It is believed that people who have done the front end are familiar with the principles of using JavaScript to animate. Now that you have a JS code that lets a div move back and forth from left to right, you may be able to write it out:

    functionMovediv(Div, FPS) {var left =0;var param =1;functionLoop() {update (); Draw ();}function update () {left + = param * Span class= "Hljs-number" >2; if (Left > 300) {left = 300; param = -1;} else if (left < 0) {left = 0; param = 1;} function draw  () {Div.style.left = left +  "px";} setinterval (Loop, 1000/fps); } movediv (document.getelementbyid ( "Div1"), 60);               

The effect is as follows:

http://jsfiddle.net/livoras/4taf9hhs/embedded/result,js,html,css/

Looking at the code, we let a div move around in the 0 to 300px range. updatecalculates the position of the div depicted in the update and draw re-paints the div on the page. For convenience, this is used directly setInterval as a timer, in which case you can use your favorite setTimeout or requestAnimationFrame . Here set every second to update 60 times, 60fps is well-known to be more suitable for animating the frame rate.

Everyone on Earth knows that the timers in JavaScript are inaccurate. Because JavaScript is time-consuming and JavaScript is single-threaded, a timer can block the execution of the next timer if it is time-consuming. So even if you set a 1000 / 60 frame rate of 60 frames per second here, the differences in different browser platforms will actually cause you to have no 60fps frame rate.

So the above code on a phone can be executed on the 60fps frame rate, on the other phone may be only 30fps, more likely only 10fps.

Let's simulate what happens when this happens:

http://jsfiddle.net/livoras/Lcv1jm53/embedded/result,js,html,css/

This is totally wrong!

You can see that three blocks move at a speed that is not on the same channel at all. Imagine what a Super Mario game would look like in 10fps? By jumping, you'll see Mario throwing arcs in the air in a space-roaming gesture.

The reason for this is simple, as we calculate and draw each div position at the time of each frame update, moving 2px per frame. In the case of 60fps, we will execute 60 frames in 1 seconds, so the small block will move every second * 2 = 120px, if it is 30fps, the small block moves every second to 2 = 60px, and so on 10fps is the move 20px per second.

The three small pieces move in a different distance within a unit time!

If you want to do a Super Mario game now, how can you make Mario look so fast and handsome at different frame rates?

Solution is obvious. While running differences on different browser platforms can lead to inconsistent frame rates, one thing that is consistent on any platform is time. So we can improve our algorithm, instead of updating the position of the block on a frame basis, and updating it in time. That is to say, we were px/frame , and now we replace it px/ms .

This is the next time-based (time-based) animation algorithm.

Time-based animation algorithm (time-based)

In fact, the idea and implementation are very simple. We calculate how much time each frame has passed from the previous frame, and then update the position of the block based on the past time.

For example, the upper block should move 120px per second, moving 120/1000 = 0.12 pixels per millisecond (12px/ms). If the position of the previous frame in the left 10px position, to this frame, it is assumed that compared to the previous frame time elapsed 200ms, that time in this frame box should be moved 200ms * 0.12px/ms = 240px. The final position should be ten + 250px. Actually, it is left = left + detalTime * speed . The code is as follows:

    functionMovedivtimebased(Div, FPS) {var left =0;var current = +NewDate;var previous = +NewDate;var param =1;functionLoop() {var current = +NewDate;var dt = current-previous;Calculate time difference previous = current; Update (DT); Draw ()}function update(DT) {left + = param * (DT * 0.12); Update Position if (left > + ) {left = + ; param =-1;} Else if (left < 0) {left = 0; param = 1;}} function Draw() {Div.style.left = left + "px";} setinterval (Loop, 1000/fps);}  

See how it works:

http://jsfiddle.net/livoras/8da1nssL/embedded/result,js,html,css/

Looks much better than the above, 30fps and 10fps seems to be able to barely catch up with the pace of 60fps. But a long time will find that 30fps and 10fps are lagging behind 60fps. (It is recommended to refresh and see the effect will be more obvious)

This is because each time a small block touches the edge, it will lose a portion of time, and the lower the frame rate of the loss is greater. Look at the function above US update :

      function update(dt) {          left += param * (dt * 0.12); // 根据时间差更新位置 if (left > 300) { left = 300; param = -1; } else if (left < 0) { left = 0; param = 1; } }

If we are now in the position of the square in the left 290px position, this frame passed the DT is 100ms, then we left is 290 + 100 * 0.12 = 302, but 302 is greater than 300, so left will be set to 300. Then the time used to move 2px will be "discarded" in vain. The larger the DT, the more wasted, so 30fps and 10fps will be slower than 60fps.

To solve this problem, we have improved the existing algorithms.

Improved time-based animation algorithm

The solution is as follows: Do not calculate the time of the whole block (DT) to move the distance, but the DT into a fixed time slice, through the multiple update fixed time slice to calculate the dt time should go to where.

Rather abstract, we look directly at the code:

    functionMovedivtimebasedimprove(Div, FPS) {var left =0;var current = +NewDate;var previous = +NewDate;var dt =1000/60; var acc = 0; var param = 1; function loop  () {var current = +new date; var passed = current-previous; previous = current; ACC + = passed; while (ACC >= DT) {//can be updated when time is greater than our fixed time slices Update (DT); //Shard update time ACC-= DT;} Draw (); } //update and draw function unchanged setinterval (loop, 1000/fps);}   

We first determine a fixed update of the time slice, such as fixed to 60fps time frame: 1000/60 = 0.167ms. Then accumulate the time of the past and then update according to the fixed time slice shard. Also said, even if this frame and the previous frame of the past 100ms, I will also divide the 100ms into a number of 0.167ms to execute the update function. There are two benefits to doing so:

    1. Fixed time slices are small enough to reduce the time of edge loss when updating.
    2. The different frame rate, whether you are 60, 30, or 10fps, is also based on fixed time slices to perform the update function, so even if there is a loss, the loss between the different frame rate is the same. Then we can achieve the effect of the simultaneous movement of three blocks!

Looking at the code above, the update and draw functions remain the same, whereas in the loop function, the past time is accumulated, and the update can be performed when the time exceeds a fixed slice. The while loop guarantees updates until the accumulated time is updated.

Accumulate the time and then update it with the fixed slices. This way there is a very big advantage, if your frame rate is more than 60fps, such as 100fps or 200fps, when the passed will be less than 0.167ms, time will be accumulated, accumulate more than 0.167 to perform the update. The effect of the bunker is: whether your frame rate is high or low, the movement speed can be synchronized with the speed of 60fps.

Look at the final effect:

http://jsfiddle.net/livoras/25nut92z/embedded/result,js,html,css/

It's pretty good.

Summarize

Frame-based animation algorithms can cause a large difference in the animation experience with different frame rates, and all animations should be performed based on time. While the time-based animation algorithm should pay attention to the loss of the edge time, it is best to take the accumulation time and then update the animation mode by the fixed slice.

References
    • http://gafferongames.com/game-physics/fix-your-timestep/
    • http://blog.sklambert.com/using-time-based-animation-implement/
    • Http://viget.com/extend/time-based-animation
    • http://codetheory.in/time-based-animations-in-html5-games-why-and-how-to-implement-them/

JavaScript time-based animation algorithm

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.