TOP   Sample3

Sample3 Code

HTML。div.ms は中央揃え。

<canvas id="Canvas"></canvas>
<br>
<div class="ms" style="color: blue;">クリックして下さい</div>
<form>
<div class="ms"><input type="button" value="消去" onclick="cvsClear();"></div>
</form>
<br>
<div class="ms"><a href="canvas_sample3_code.html">Code</a></div>

JavaScript

var wd, cvs, ctx, r, num;
//円クラス
var Circle = function () {
  this.dist = function (c) {    //円の中心どうしの距離
    return Math.sqrt(this.o.sub(c.o).absl2())
  };
};
//ベクトル・クラス
var Vector = function (x, y) {
  this.x = x; this.y = y;
  this.mul = function (a) {    //a倍
    return new Vector(a * this.x, a * this.y);
  };
  this.innPro = function (v) {    //内積
    return this.x * v.x + this.y * v.y;
  };
  this.add = function (v) {    //和
    return new Vector(this.x + v.x, this.y + v.y);
  };
  this.sub = function (v) {    //差
    return new Vector(this.x - v.x, this.y - v.y);
  };
  this.absl2 = function () {    //絶対値の二乗
    return Math.pow(this.x, 2) + Math.pow(this.y, 2);
  };
};

//開始
var cir = [];    //円を表すインスタンス(配列)
wd = 500; r = 20; num = 0;    //wdはCanvasの縦横, rは円の半径, numは円の個数
onload = function() {
  cvs = document.getElementById("Canvas"); ctx = cvs.getContext("2d");
  cvs.height = wd; cvs.width = wd;
  cvs.onclick = setBall;    //クリックされたら円生成
  setInterval(f, 10);
}
//メインの処理
function f() {
  if (num == 0) {return;}
  ctx.clearRect(0, 0, wd, wd);    //画面クリア
  var fl = geneArray(num);    //円が既に処理されていれば false、まだ処理していないのは true。
  for (var i = 0; i < num; i++) {
    ctx.beginPath();
    ctx.fillStyle = cir[i].cl;
    ctx.arc(cir[i].o.x, cir[i].o.y, r, 0, Math.PI * 2);
    ctx.fill();
    cir[i].o = cir[i].o.add(cir[i].v);    //円の移動計算
    if (cir[i].o.x >= wd - r || cir[i].o.x <= r) {cir[i].v.x = -cir[i].v.x;}    //壁と衝突するか
    else if (cir[i].o.y >= wd - r || cir[i].o.y <= r) {
      cir[i].v.y = -cir[i].v.y;
    }
    for (var j = 0; j < num; j++) {
      if (!fl[i][j]) {continue;}    //処理の終った円はスキップする
      var c1 = cir[i], c2 = cir[j];
      if (c1.dist(c2) <= r * 2) {    //円どうしの衝突判定
        var v1 = c1.v, v2 = c2.v;
        var ra = c1.o.sub(c2.o);
        var tmp = ra.mul(ra.innPro(v1.sub(v2)) / ra.absl2());
        c1.v = v1.sub(tmp);
        c2.v = v2.add(tmp);
        fl[i][j] = false;
      }
    }
  }
}

//Array生成
function geneArray(n) {
  var a = new Array(n);
  for (var i = 0; i < n; i++) {
    a[i] = new Array(n);
    for (var j = 0; j < n; j++) {
      a[i][j] = true;
      if (i <= j) {a[i][j] = false;}
    }
  }
  return a;
}
//円の生成
function setBall(e) {    //eはイベント(マウス・クリック)
  var x1, y1;
  x1 = e.pageX - cvs.offsetLeft; y1 = e.pageY - cvs.offsetTop;
  if (x1 <= r || x1 >= wd - r || y1 <= r || y1 >= wd - r) {return;}
  num++;
  cir[num - 1] = new Circle();    //インスタンス生成
  cir[num - 1].o = new Vector(x1, y1);    //中心
  cir[num - 1].v = new Vector((Math.random() * 2 + 2) * (Math.random() - 0.5) * 2,
                (Math.random() * 2 + 2) * (Math.random() - 0.5) * 2);    //円の速度ベクトルをランダムに生成
  cir[num - 1].cl = "rgb(" + rnd() + "," + rnd() + "," + rnd() + ")";    //円の色
  if (near(num - 1)) {num--; pop(cir); return;}    //円どうしが近すぎれば生成しない
}
//円どうしが近いか
function near(i) {
  if (i == 0) {return false;}
  for (var j = 0; j < i; j++) {
    if (cir[i].dist(cir[j]) <= r * 2) {return true;}
  }
  return false;
}
function rnd() {
  return String(Math.floor(Math.random()*256));
}
//リセット
function cvsClear() {
  ctx.clearRect(0, 0, wd, wd);
  num = 0;
}

inserted by FC2 system