canvas小球隨機漂浮碰撞程式碼例項

admin發表於2017-02-10
本章節分享一段程式碼例項,它利用canvas實現了小球的隨機漂浮碰撞效果。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>螞蟻部落</title>
<style>
* {
  margin: 0;
  padding: 0;
}
html, body {
  height: 100%;
}
#myCanvas {
  background: #001022;
}
#myButtons {
  bottom: 20px;
  left: 20px;
  position: absolute;
}
#myButtons button {
  padding: 5px;
}
</style>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script>
$(document).ready(function() {
  var canvas = $('#myCanvas');
  var context = canvas.get(0).getContext('2d');
 
  var canvasWidth = canvas.width();
  var canvasHeight = canvas.height();
 
 
  $(window).resize(resizeCanvas);
 
  function resizeCanvas() {
 
    canvas.attr('width', $(window).get(0).innerWidth);
    canvas.attr('height', $(window).get(0).innerHeight);
 
    canvasWidth = canvas.width();
    canvasHeight = canvas.height();
 
  }
 
  resizeCanvas();
 
  var playAnimation = true;
  var startButton = $('#startAnimation');
  var stopButton = $('#stopAnimation');
 
 
  startButton.click(function() {
    playAnimation = true;
    animate();
  });
  stopButton.click(function() {
    playAnimation = false;
  });
 
 
  /*
   *   座標:x,y
   *   半徑:r,
   *   速度:vx,vy
   *   加速度:ax,ay
   *
   * */
  var Asteroid = function(x, y, r, mass, vx, vy, ax, ay) {
    this.x = x;
    this.y = y;
    this.radius = r;
    this.mass = mass;
 
    this.vx = vx;
    this.vy = vy;
    this.ax = ax;
    this.ay = ay;
 
  }
 
  var asteroids = [];
 
  for (var i = 0; i < 10; i++) {
    var x = 20 + (Math.random() * (canvasWidth - 40));
    var y = 20 + (Math.random() * (canvasHeight - 40));
 
    var randius = 5 + Math.random() * 10;
    var mass = randius / 2;
 
    var vx = Math.random() * 4 - 2;
    var vy = Math.random() * 4 - 2;
 
    var ax = Math.random() * 0.2 - 0.1;
    var ay = Math.random() * 0.2 - 0.1;
    //var ax =0;
    //var ay =0;
 
    asteroids.push(new Asteroid(x, y, randius, mass, vx, vy, ax, ay));
  }
 
  function animate() {
 
    context.clearRect(0, 0, canvasWidth, canvasHeight);
    context.fillStyle = 'rgb(255,255,255)';
 
    var asteroidsLength = asteroids.length;
 
    for (var i = 0; i < asteroidsLength; i++) {
      var tmpAsteroid = asteroids[i];
      // 速度,改變位置的
      tmpAsteroid.x += tmpAsteroid.vx;
      tmpAsteroid.y += tmpAsteroid.vy;
 
      // 加速度
      if (Math.abs(tmpAsteroid.vx) < 10) {
        tmpAsteroid.vx += tmpAsteroid.ax;
      }
      if (Math.abs(tmpAsteroid.vy) < 10) {
        tmpAsteroid.vy += tmpAsteroid.ay;
      }
 
      // 摩擦力
      if (Math.abs(tmpAsteroid.vx) > 0.1) {
        //tmpAsteroid.vx *= 0.9;
      } else {
        //tmpAsteroid.vx = 0;
      }
 
      if (Math.abs(tmpAsteroid.vy) > 0.1) {
        //tmpAsteroid.vy *= 0.9;
      } else {
        //tmpAsteroid.vy = 0;
      }
      // 判斷邊界
      if (tmpAsteroid.x - tmpAsteroid.radius < 0) {
        tmpAsteroid.x = tmpAsteroid.radius;
        tmpAsteroid.vx *= -1;
        tmpAsteroid.ax *= -1;
      } else if (tmpAsteroid.x + tmpAsteroid.radius > canvasWidth) {
        tmpAsteroid.x = canvasWidth - tmpAsteroid.radius;
        tmpAsteroid.vx *= -1;
        tmpAsteroid.ax *= -1;
      }
 
      if (tmpAsteroid.y - tmpAsteroid.radius < 0) {
        tmpAsteroid.y = tmpAsteroid.radius;
        tmpAsteroid.vy *= -1;
        tmpAsteroid.ay *= -1;
      } else if (tmpAsteroid.y + tmpAsteroid.radius > canvasHeight) {
        tmpAsteroid.y = canvasHeight - tmpAsteroid.radius;
        tmpAsteroid.vy *= -1;
        tmpAsteroid.ay *= -1;
      }
      // 判斷碰撞
      for (var j = i + 1; j < asteroidsLength; j++) {
        var tmpAsteroidB = asteroids[j];
 
        var dx = tmpAsteroidB.x - tmpAsteroid.x;
        var dy = tmpAsteroidB.y - tmpAsteroid.y;
 
        var dis = Math.sqrt((dx * dx) + (dy * dy));
 
        if (dis < tmpAsteroid.radius + tmpAsteroidB.radius) {
          // 彈開物體
          var angle = Math.atan2(dy, dx);
          var sine = Math.sin(angle);
          var cosine = Math.cos(angle);
 
          var x = 0;
          var y = 0;
 
          var xb = dx * cosine + dy * sine;
          var yb = dy * cosine - dx * sine;
 
          var vx = tmpAsteroid.vx * cosine + tmpAsteroid.vy * sine;
          var vy = tmpAsteroid.vy * cosine + tmpAsteroid.vx * sine;
 
          var vxb = tmpAsteroidB.vx * cosine + tmpAsteroidB.vy * sine;
          var vyb = tmpAsteroidB.vy * cosine - tmpAsteroidB.vx * sine;
 
          vx *= -1;
          vxb *= -1;
 
          xb = x + (tmpAsteroid.radius + tmpAsteroidB.radius);
 
 
          tmpAsteroid.x = tmpAsteroid.x + (x * cosine - y * sine);
          tmpAsteroid.y = tmpAsteroid.y + (y * cosine + x * sine);
 
 
          tmpAsteroidB.x = tmpAsteroid.x + (xb * cosine - yb * sine);
          tmpAsteroidB.y = tmpAsteroid.y + (yb * cosine + xb * sine);
 
 
          tmpAsteroid.vx = vx * cosine - vy * sine;
          tmpAsteroid.vy = vy * cosine + vx * sine;
 
          tmpAsteroidB.vx = vxb * cosine - vyb * sine;
          tmpAsteroidB.vy = vyb * cosine + vyb * sine;
 
          /*var vTotal= vx-vxb;
          vx = ((tmpAsteroid.mass-tmpAsteroidB.mass)*vx+2*tmpAsteroidB.mass*vxb)/(tmpAsteroid.mass+tmpAsteroidB.mass);
          vxb = vTotal+vx;*/
 
        }
      }
 
      context.beginPath();
      context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI * 2, false);
      context.closePath();
      context.fill();
 
    }
    if (playAnimation) {
      setTimeout(animate, 33);
    }
 
  }
});
</script>
</head>
<body>
<canvas id="myCanvas" width="500" height="500"></canvas>
<div id="myButtons">
  <button id="startAnimation">開始</button>
  <button id="stopAnimation">結束</button>
</div>
</body>
</html>

相關文章