/ball-collision/script.js
http://tmlife-storage.googlecode.com/ · JavaScript · 234 lines · 125 code · 56 blank · 53 comment · 12 complexity · 09d1e1ab903ea32bf675e9dcc98a0c55 MD5 · raw file
- /**
- * @author phi
- */
- var COLOR_LIST = [
- // "rgba( 0, 0, 0, 1)", // black
- // "rgba(255, 255, 255, 1)", // white
- "rgba(255, 0, 0, 1)", // red
- "rgba( 0, 255, 0, 1)", // green
- "rgba( 0, 0, 255, 1)", // blue
- "rgba(255, 255, 0, 1)", // yellow
- "rgba( 0, 255, 255, 1)", // cyan
- "rgba(255, 0, 255, 1)", // magenta
- ];
- var GRAVITY = Vector3();
- GRAVITY.set(-Math.cos(Math.PI*0.5)*2.0, Math.sin(Math.PI*0.5)*2.0);
- var BALL_MAX_NUM = 16;
- var FPS = 1000/30;
- var ballList = [];
- var canvas;
- var context;
- /**
- * ロード
- */
- window.onload = function()
- {
- // キャンバス取得
- canvas = document.getElementById("my-canvas");
- context = canvas.getContext("2d");
-
- // ボールを生成
- for (var i=0; i<BALL_MAX_NUM; ++i) {
- var temp = ballList[i] = Ball();
- temp.init();
- temp.pos.set( Math.random()*640, Math.random()*480 );
- }
-
- // 更新関数を登録
- var run = function() {
- update();
- draw();
- setTimeout(run, FPS);
- }
- setTimeout(run, FPS)
- };
- /**
- * 更新
- */
- var update = function()
- {
- for (var i=0; i<ballList.length; ++i) {
- ballList[i].update();
- }
-
- return ;
- }
- /**
- * 描画
- */
- var draw = function()
- {
- // 画面クリア
- context.fillStyle = "rgba(0, 0, 0, 1)";
- context.fillRect(0, 0, canvas.width, canvas.height);
- // 描画
- for (var i=0; i<ballList.length; ++i) {
- ballList[i].draw();
- }
- }
- /**
- *
- */
- var Ball = (function(member) {
-
- var TempClass = function(){
- return new TempClass.prototype.creator();
- };
-
- TempClass.prototype = member;
- TempClass.prototype.creator = function(){ return this; };
- TempClass.prototype.creator.prototype = TempClass.prototype;
-
- return TempClass;
- })({
- pos : undefined,
- velocity: undefined,
- radius : undefined,
- color : 0,
-
- /**
- * 初期化
- */
- init: function() {
- // 初期値をセット
- this.pos = Vector3();
- this.pos.x = this.pos.y = this.pos.z = 0;
- this.velocity = Vector3();
- // ランダムな報告に加速度を設定
- var angle = Math.random()*6.28;
- this.velocity.x = Math.cos(angle)*8;
- this.velocity.y = Math.sin(angle)*8;
- this.velocity.z = 0;
- // 半径
- this.radius = 32;
-
- // 色をランダムにセット
- this.setRandomColor();
- },
-
- /**
- * 更新
- */
- update: function(){
- this.pos.add(this.velocity);
- this.velocity.add(GRAVITY);
- // this.velocity.y += 2.0;
-
- var left = 0 + this.radius;
- var right = 640 - this.radius;
- var top = 0 + this.radius;
- var bottom = 480 - this.radius;
- if (this.pos.x < left) { this.pos.x = left; this.velocity.x *= -0.8; }
- if (this.pos.x > right) { this.pos.x = right; this.velocity.x *= -0.8; }
- if (this.pos.y < top) { this.pos.y = top; this.velocity.y *= -0.8; }
- if (this.pos.y > bottom) { this.pos.y = bottom; this.velocity.y *= -0.8; }
-
- for (var i=0; i<ballList.length; ++i) {
- var other = ballList[i];
-
- if (other == this) { continue ; }
-
- if (Ball.collision(this, other)) { this.reflect(other); }
- }
- },
-
- /**
- * 反射
- */
- reflect : function(other)
- {
- // 球同士でできる面の法線
- var ndp = Vector3.sub(this.pos, other.pos);
- ndp.normalize();
- // 押し出す
- var temp = Vector3.mul(ndp, this.radius + other.radius);
- temp.add(other.pos);
- this.pos = temp;
-
- // 速度の向きを変更
- var new_velocity = Vector3.reflect(this.velocity, ndp);
- new_velocity.mul(0.8);
- this.velocity = new_velocity;
-
- // 相手側の向きも変更
- var new_velocity2 = Vector3.reflect(other.velocity, Vector3.negative(ndp))
- new_velocity2.mul(0.8)
- other.veloctity = new_velocity2;
-
- return this;
- },
- /**
- * 描画
- */
- draw: function()
- {
- context.fillStyle = this.color;
- // 円描画
- context.beginPath();
- context.arc( this.pos.x, this.pos.y, this.radius, 0, Math.PI*2, false );
- context.fill();
-
- return this;
- },
-
- /**
- * 色をランダムにセット
- */
- setRandomColor : function()
- {
- this.color = COLOR_LIST[ Math.floor(Math.random()*COLOR_LIST.length) ];
-
- return this;
- }
-
- });
- /**
- * ボール同士の衝突判定
- */
- Ball.collision = function(ball0, ball1)
- {
- // ball1 から ball0 へのベクトル
- var v = Vector3.sub(ball0.pos, ball1.pos);
- // ボールの実際の距離の二乗
- var len = (ball0.radius+ball1.radius) * (ball0.radius+ball1.radius);
-
- // 衝突判定
- if (v.lengthSquare() < len) {
- return true;
- }
-
- return false;
- };