Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

JavaScript simulation with optional sim/animate separation

By: a guest on Mar 22nd, 2013  |  syntax: JavaScript  |  size: 5.41 KB  |  hits: 27  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <!doctype html>
  2. <html>
  3. <head>
  4.   <style>
  5.     canvas { border:1px solid black;  width:480px; height:320px; }
  6.   </style>
  7. </head>
  8. <body>
  9.  
  10.   <canvas id='screen' width='480' height='320'></canvas>
  11. <p><input type="checkbox" id="sync">Sync update to animate</input>
  12. <p>Step delay (ms):<input type="text" id="stepdelay"></input>
  13. <p>Animate delay (ms):<input type="text" id="animatedelay"></input>
  14. <p><input type="text" id="counter"></input>
  15.  
  16.   <script>
  17.  
  18.   // Grab the canvas
  19.   var canvas  = document.getElementById('screen'),
  20.     ctx     = canvas.getContext('2d'),
  21.  
  22.     gamewidth = canvas.width,
  23.     gameheight = canvas.height,
  24.  
  25.     running = false,
  26.     sync = document.getElementById("sync"),
  27.  
  28.     timer = {
  29.       fps:   1/60,      // Frames per second
  30.       fpsMS: 1000/60,       // Frame time in ms
  31.  
  32.       accum:0,                // Accumulated deltas
  33.       delta:0,        // the delta between frames
  34.  
  35.       last:(new Date()).getTime(),
  36.       now: (new Date()).getTime(),
  37.  
  38.       // tick the clock on each update (simulation step)
  39.       tick: function() {
  40.         this.last = this.now;
  41.         this.now = (new Date()).getTime();
  42.         this.delta = Math.min(this.now - this.last, 250);
  43.         this.accum += this.delta;
  44.       }
  45.     },
  46.  
  47.  
  48.     // Keep track of the actual updates per second (ups) and frames per second (fps)
  49.     counter = document.getElementById("counter"),
  50.     laststep = Date.now(),
  51.     lastanimate = Date.now(),
  52.     avgdtu = 0,
  53.     avgdtf = 0,
  54.     updatecounter = function () {
  55.       counter.value = (1000/avgdtu).toPrecision(3) + "ups  " + (1000/avgdtf).toPrecision(3) + "fps";
  56.     },
  57.     // Call this once per step to keep count
  58.     countstep = function () {
  59.       var now = Date.now(), dt = now - laststep;
  60.       laststep = now;
  61.       avgdtu = 0.95 * avgdtu + 0.05 * dt;
  62.       updatecounter();
  63.     },
  64.     // Call this once per animate to keep count
  65.     countanimate = function () {
  66.       var now = Date.now(), dt = now - lastanimate;
  67.       lastanimate = now;
  68.       avgdtf = 0.95 * avgdtf + 0.05 * dt;
  69.       updatecounter();
  70.     },
  71.     // Do nothing for dt milliseconds
  72.     delay = function (dt) {
  73.       var end = Date.now () + dt;
  74.       while (Date.now() < end);
  75.     },
  76.     stepdelay = document.getElementById("stepdelay"),
  77.     animatedelay = document.getElementById("animatedelay"),
  78.  
  79.  
  80.     // A simple box to bounce around the canvas
  81.     box = {
  82.       position:      { x:228, y:135},
  83.       lastPostition: { x:228, y:135},
  84.       velocity:      { x1:1, x2:1},
  85.       speed: 60,
  86.       width:16, height:16
  87.     },
  88.  
  89.  
  90.     /*
  91.     **   This is the simulation step
  92.     */
  93.     pendingUpdate = null;
  94.     update = function() {
  95.       // ticks the clock,
  96.       timer.tick();
  97.  
  98.       // steps the simulation at a fixed delta until the accumlated delta time is consumed
  99.       while(timer.accum >= timer.fpsMS) {
  100.         timer.accum -= timer.fpsMS;
  101.         step(timer.fps);
  102.       }
  103.  
  104.       // if running continue the simulation loop
  105.       if(running && !sync.checked) { pendingUpdate = setTimeout(update, timer.fpsMS); }
  106.       else pendingUpdate = null;
  107.     },
  108.  
  109.     step = function(delta) {
  110.       countstep();
  111.       delay(+stepdelay.value);
  112.       // move the old position to lastPosition before updating to preserve two states
  113.       box.lastPostition = box.position;
  114.  
  115.       // compute the change in (x, y)
  116.       var dx = box.velocity.x1 * box.speed * delta,
  117.         dy = box.velocity.x2 * box.speed * delta;
  118.  
  119.       // if out of bounds reverse velocity, otherwise add the change in position
  120.       if(box.position.x + dx < 0  || box.position.x + dx + box.width > gamewidth) {
  121.         box.velocity.x1 = box.velocity.x1 * -1;
  122.       } else {
  123.         box.position.x  += dx;
  124.       }
  125.  
  126.       if(box.position.y + dy < 0 || box.position.y + dy + box.height > gameheight) {
  127.         box.velocity.x2 = box.velocity.x2 * -1;
  128.       } else {
  129.         box.position.y  += dy;
  130.       }
  131.  
  132.     },
  133.  
  134.  
  135.     /*
  136.     **  This is the animation step
  137.     */
  138.     animate = function() {
  139.       countanimate();
  140.       delay(+animatedelay.value);
  141.       if (!pendingUpdate) update();
  142.       // If running request a new frame continuing the loop
  143.       if(running) { window.requestAnimFrame(animate); }
  144.  
  145.  
  146.       // Linear Interpolation
  147.       var a =  timer.accum > timer.fspMS ? timer.accum / timer.fpsMS : 1,
  148.  
  149.         x0 = box.lastPostition.x, y0 = box.lastPostition.y,
  150.         x1 = box.position.x,    y1 = box.position.y,
  151.  
  152.         pt = {
  153.           x: x0 + ( (x1 - x0) * a ),
  154.           y: y0 + ( (y1 - y0) * a )
  155.         };
  156.  
  157.       // Canvas clear and drawing
  158.       ctx.clearRect(0, 0, gamewidth, gameheight);
  159.       ctx.fillRect(pt.x, pt.y, box.width, box.height);
  160.     },
  161.    
  162.  
  163.     // Called on load to start the loops
  164.     start = function() {
  165.       running = true;
  166.       update();
  167.       animate();
  168.     };
  169.  
  170.   window.onload = start;
  171.  
  172.  
  173.   // Awesome requestAnimationFrame shim by Paul Irish
  174.   // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  175.   window.requestAnimFrame = (function(){
  176.     return  window.requestAnimationFrame       ||
  177.             window.webkitRequestAnimationFrame ||
  178.             window.mozRequestAnimationFrame    ||
  179.             window.oRequestAnimationFrame      ||
  180.             window.msRequestAnimationFrame     ||
  181.             function( callback ){
  182.               window.setTimeout(callback, 1000 / 60);
  183.             };
  184.   })();
  185.  
  186.   </script>
  187. </body>
  188. </html>