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