PageRenderTime 27ms CodeModel.GetById 14ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/ball-collision/script.js

http://tmlife-storage.googlecode.com/
JavaScript | 234 lines | 125 code | 56 blank | 53 comment | 12 complexity | 09d1e1ab903ea32bf675e9dcc98a0c55 MD5 | raw file
  1/**
  2 * @author phi
  3 */
  4
  5var COLOR_LIST = [
  6    // "rgba(  0,   0,   0, 1)", // black
  7    // "rgba(255, 255, 255, 1)", // white
  8    "rgba(255,   0,   0, 1)", // red
  9    "rgba(  0, 255,   0, 1)", // green
 10    "rgba(  0,   0, 255, 1)", // blue
 11    "rgba(255, 255,   0, 1)", // yellow
 12    "rgba(  0, 255, 255, 1)", // cyan
 13    "rgba(255,   0, 255, 1)", // magenta
 14];
 15
 16var GRAVITY = Vector3();
 17GRAVITY.set(-Math.cos(Math.PI*0.5)*2.0, Math.sin(Math.PI*0.5)*2.0);
 18var BALL_MAX_NUM = 16;
 19var FPS = 1000/30;
 20
 21var ballList = [];
 22var canvas;
 23var context;
 24
 25/**
 26 * ロード
 27 */
 28window.onload = function()
 29{
 30    // キャンバス取得
 31    canvas = document.getElementById("my-canvas");
 32    context = canvas.getContext("2d");
 33    
 34    // ボールを生成
 35    for (var i=0; i<BALL_MAX_NUM; ++i) {
 36        var temp = ballList[i] = Ball();
 37        temp.init();
 38        temp.pos.set( Math.random()*640, Math.random()*480 );
 39    }
 40    
 41    // 更新関数を登録
 42    var run = function() {
 43        update();
 44        draw();
 45        setTimeout(run, FPS);
 46    }
 47    setTimeout(run, FPS)
 48};
 49
 50/**
 51 * 更新
 52 */
 53var update = function()
 54{
 55    for (var i=0; i<ballList.length; ++i) {
 56        ballList[i].update();
 57    }
 58    
 59    return ;
 60}
 61
 62/**
 63 * 描画
 64 */
 65var draw = function()
 66{
 67    // 画面クリア
 68    context.fillStyle = "rgba(0, 0, 0, 1)";
 69    context.fillRect(0, 0, canvas.width, canvas.height);
 70    // 描画
 71    for (var i=0; i<ballList.length; ++i) {
 72        ballList[i].draw();
 73    }
 74}
 75
 76
 77/**
 78 * 
 79 */
 80var Ball = (function(member) {
 81    
 82    var TempClass = function(){
 83        return new TempClass.prototype.creator();
 84    };
 85    
 86    TempClass.prototype = member;
 87    TempClass.prototype.creator = function(){ return this; };
 88    TempClass.prototype.creator.prototype = TempClass.prototype;
 89    
 90    return TempClass;
 91})({
 92    pos     : undefined,
 93    velocity: undefined,
 94    radius  : undefined,
 95    color   : 0,
 96    
 97    /**
 98     * 初期化
 99     */
100    init: function() {
101        // 初期値をセット
102        this.pos = Vector3();
103        this.pos.x = this.pos.y = this.pos.z = 0;
104        this.velocity = Vector3();
105        // ランダムな報告に加速度を設定
106        var angle = Math.random()*6.28;
107        this.velocity.x = Math.cos(angle)*8;
108        this.velocity.y = Math.sin(angle)*8;
109        this.velocity.z = 0;
110        // 半径
111        this.radius = 32;
112        
113        // 色をランダムにセット
114        this.setRandomColor();
115    },
116    
117    /**
118     * 更新
119     */
120    update: function(){
121        this.pos.add(this.velocity);
122        this.velocity.add(GRAVITY);
123        // this.velocity.y += 2.0;
124        
125        var left    =   0 + this.radius;
126        var right   = 640 - this.radius;
127        var top     =   0 + this.radius;
128        var bottom  = 480 - this.radius;
129        if (this.pos.x <   left) { this.pos.x =   left; this.velocity.x *= -0.8;  }
130        if (this.pos.x >  right) { this.pos.x =  right; this.velocity.x *= -0.8;  }
131        if (this.pos.y <    top) { this.pos.y =    top; this.velocity.y *= -0.8;  }
132        if (this.pos.y > bottom) { this.pos.y = bottom; this.velocity.y *= -0.8;  }
133        
134        for (var i=0; i<ballList.length; ++i) {
135            var other = ballList[i];
136            
137            if (other == this) { continue ; }
138            
139            if (Ball.collision(this, other)) { this.reflect(other); }
140        }
141    },
142    
143    /**
144     * 反射
145     */
146    reflect : function(other)
147    {
148        // 球同士でできる面の法線
149        var ndp = Vector3.sub(this.pos, other.pos);
150        ndp.normalize();
151        // 押し出す
152        var temp = Vector3.mul(ndp, this.radius + other.radius);
153        temp.add(other.pos);
154        this.pos = temp;
155        
156        // 速度の向きを変更
157        var new_velocity = Vector3.reflect(this.velocity, ndp);
158        new_velocity.mul(0.8);
159        this.velocity = new_velocity;
160        
161        // 相手側の向きも変更
162        var new_velocity2 = Vector3.reflect(other.velocity, Vector3.negative(ndp))
163        new_velocity2.mul(0.8)
164        other.veloctity = new_velocity2;
165        
166        return this;
167    },
168
169    /**
170     * 描画
171     */
172    draw: function()
173    {
174        context.fillStyle = this.color;
175        // 円描画
176        context.beginPath();
177        context.arc( this.pos.x, this.pos.y, this.radius, 0, Math.PI*2, false );
178        context.fill();
179        
180        return this;
181    },
182    
183    /**
184     * 色をランダムにセット
185     */
186    setRandomColor : function()
187    {
188        this.color = COLOR_LIST[ Math.floor(Math.random()*COLOR_LIST.length) ];
189        
190        return this;
191    }
192    
193});
194
195/**
196 * ボール同士の衝突判定
197 */
198Ball.collision = function(ball0, ball1)
199{
200    // ball1 から ball0 へのベクトル
201    var v = Vector3.sub(ball0.pos, ball1.pos);
202    // ボールの実際の距離の二乗
203    var len = (ball0.radius+ball1.radius) * (ball0.radius+ball1.radius);
204    
205    // 衝突判定
206    if (v.lengthSquare() < len) {
207        return true;
208    }
209    
210    return false;
211};
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234