spritejs/sprite-core

View on GitHub
benchmark/birds_fly.spritejs.html

Summary

Maintainability
Test Coverage
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
  <title>Birds Flying</title>
  <style>
    *{      
      -webkit-touch-callout: auto; /* prevent callout to copy image, etc when tap to hold */      
      -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */      
      -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */       
      -webkit-user-select:none;
    }  
    html,body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      max-width: 500px;
    }
    canvas {
      width: 400px;
      height: 400px;
    }
  </style>
</head>
<body>
  <div>fps: <span id="fps">--</span> | sprites: <span id="spriteCount">1</span></div>
  <canvas id="paper" width="800" height="800"></canvas>
  
  <script src="https://s3.ssl.qhres.com/!ed7dc4fe/animator-0.3.2.js"></script>
  <!-- <script src="js/animator-dev.js"></script> -->
  <!-- <script src="https://unpkg.com/sprite-core/dist/sprite-core.min.js"></script> -->
  <script src="/js/sprite-core.js"></script>
  
  <script>
    const Sprite = spritejs.Sprite;
    const Layer = spritejs.Layer;
    const context = document.getElementById('paper').getContext('2d');
    const fglayer = new Layer({context, autoRender: false});

    const birdTexture = new Image();
    birdTexture.crossOrigin = 'anonymous';
    birdTexture.src = 'https://p.ssl.qhimg.com/d/inn/c886d09f/birds.png';

    const axisZero = [400, 400];

    function pointAdd(p1, p2 = [0, 0]) {
      return [p1[0] + p2[0], p1[1] + p2[1]].map(Math.round);
    }

    function pointSub(p1, p2 = [0, 0]) {
      return [p1[0] - p2[0], p1[1] - p2[1]].map(Math.round);
    }

    function sleep(time) {
      return new Promise(resolve => setTimeout(resolve, time));
    }

    async function randomAnimate(bird) {
      const birdPoint = bird.attr('pos');
      const randomArc = Math.random() * 2 * Math.PI;
      const randomPoint = pointAdd([350 * Math.cos(randomArc),
        350 * Math.sin(randomArc)], axisZero);

      const dist = pointSub(randomPoint, birdPoint);
      const distance = Math.round(Math.sqrt(dist[0] * dist[0] + dist[1] * dist[1]));
      const flip = dist[0] < 0 ? -1 : 1;
      const duration = 5 * distance + 100;

      bird.attr('scale', [flip, 1]); // scale 放在外面,触发缓存

      const anim = new Animator(duration, (p) => {
        const pos = pointAdd(birdPoint, [p * dist[0], p * dist[1]]);
        bird.attr({pos});
      });
      await anim.animate();

      // const anim = bird.animate([
      //   {pos: birdPoint},
      //   {pos: pointAdd(birdPoint, dist)}
      // ], {
      //   duration,
      //   fill: "forwards",
      // })
      // await anim.finished

      await sleep(500);
    }

    let birdCount = 0;
    const wings = [[2, 126, 86, 60], [2, 64, 86, 60], [2, 2, 86, 60]];

    async function addBird() {
      spriteCount.innerHTML = ++birdCount;
      const bird = new Sprite();

      bird.attr({
        textures: [{image: birdTexture, srcRect: wings[0]}],
        anchor: [0.5, 0.5],
        pos: axisZero,
        size: [86, 60],
        // bgcolor: 'red',
      });
      window.bird = bird;

      fglayer.appendChild(bird);

      // let idx = 0;
      // setInterval(() => {
      //   bird.textures = [{image: birdTexture, srcRect: wings[idx++ % 3]}];
      // }, 100);

      // noprotect
      do {
        await randomAnimate(bird);
      } while(1);
    }

    birdTexture.onload = function () {
      addBird();
      requestAnimationFrame(function f() {
        if(birdCount < 600) {
          addBird();
        }
        fglayer.draw();
        requestAnimationFrame(f);
      });
    };

    // 显示 fps ,注意,因为本框架采用的是非定时渲染,即只有 sprite 有更新时才渲染
    // 所以所有精灵不运动的时候 fps 也会降下来
    setInterval(() => {
      fps.innerHTML = fglayer.fps;
    }, 1000);
  </script>
</body>
</html>