2011年12月27日火曜日

HTML5 - Canvas 円同士の衝突アニメーション

<canvas id="hoge" width="400" height="400"></canvas>

<script type="text/javascript">
var canvas = document.getElementById("hoge");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;

var g = 0.1;
var circles = [];
var time = 0;
var colorList = ['0','1','2','3','4','5','6','7',
                 '8','9','a','b','c','d','e','f'];

var tm;
tm = setInterval(main,10);

function main(){
 ctx.clearRect(0,0,cw,ch);
 if(time>100 || time==0){
  time = 0;
  circles.push(new Circle());
  circles[circles.length-1].init(circles.length%2);
 }
 for(i=0;i<circles.length;i++){
  for(j=i+1;j<circles.length;j++){
   collisionCircleCircle(circles[i],circles[j]);
  }
 }
 for(i=0;i<circles.length;i++){
  circles[i].move();
  circles[i].collisionWall();
  circles[i].view();
 }
 time++;
}

function Circle(){
 this.h = 0.9; this.x = 0; this.y = 100;
 this.vx = 0; this.vy = 0; this.r = 0;
 this.color = '#';
 
 this.init = function(vec){
  this.vx = Math.random()*9+1;
  this.r = Math.random()*25+5;
  if(vec){
   this.x = cw+100;
   this.vx *= -1;
  }else{
   this.x = -100;
  }
  this.color += colorList[Math.floor(Math.random()*3)+3];
  this.color += colorList[Math.floor(Math.random()*5)+5];
  this.color += colorList[Math.floor(Math.random()*7)+9];
 }
 
 this.move = function(){
  this.x += this.vx;
  this.y += this.vy;
  this.vy += g;
 }
 
 this.view = function(){
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.r, 0, 360,false);
  ctx.fill();
 }
 
 this.collisionWall = function(){
  if(this.x+this.r > cw && this.vx > 0 || 
    this.x-this.r < 0 && this.vx < 0){
   this.vx *= -this.h;
  }else if(this.y+this.r > ch && this.vy > 0 || 
    this.y-this.r < 0 && this.vy < 0){
   this.vy *= -this.h;
  }
 }
}

function collisionCircleCircle(a,b){
 if((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y) < (a.r+b.r)*(a.r+b.r)){
  var vx = a.x-b.x;
  var vy = a.y-b.y;
  var len = Math.sqrt(vx*vx+vy*vy);
  var d = a.r+b.r-len;
  if(len>0) len =1/len;
  
  vx *= len;
  vy *= len;
  
  d /= 2.0;
  a.x += vx*d;
  a.y += vy*d;
  b.x -= vx*d;
  b.y -= vy*d;
  
  var t;
  t = -(vx*a.vx+vy*a.vy)/(vx*vx+vy*vy);
  var arx = a.vx+vx*t;
  var ary = a.vy+vy*t;

  t = -(-vy*a.vx+vx*a.vy)/(vy*vy+vx*vx);
  var amx = a.vx-vy*t;
  var amy = a.vy+vx*t;

  t = -(vx*b.vx+vy*b.vy)/(vx*vx+vy*vy);
  var brx = b.vx+vx*t;
  var bry = b.vy+vy*t;

  t = -(-vy*b.vx+vx*b.vy)/(vy*vy+vx*vx);
  var bmx = b.vx-vy*t;
  var bmy = b.vy+vx*t;
  
  var e = 0.8;
  var adx = (a.r*amx+b.r*bmx+bmx*e*b.r-amx*e*b.r)/(a.r+b.r);
  var bdx = -e*(bmx-amx)+adx;
  var ady = (a.r*amy+b.r*bmy+bmy*e*b.r-amy*e*b.r)/(a.r+b.r);
  var bdy = -e*(bmy-amy)+ady;
  
  a.vx = adx+arx;
  a.vy = ady+ary;
  b.vx = bdx+brx;
  b.vy = bdy+bry;
 }
}
</script>

0 件のコメント:

コメントを投稿