threebody.html 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- 必须强制指定页面编码为 UTF-8 -->
  5. <meta charset="utf-8">
  6. <!-- Demo 的简要说明,必须要填写 -->
  7. <meta name="description" content="使用 Kity 模拟三体运动">
  8. <!-- Demo 的作者,建议填写 -->
  9. <meta name="author" content="techird@qq.com">
  10. <!-- Demo 的标题,必须填写 -->
  11. <title>三体运动</title>
  12. <!-- Demo 开发过程中使用 CMD 引入 Kity 源码,方便调试 -->
  13. <!-- dev start -->
  14. <!-- 目录型的 Demo 注意修正源码引用路径 -->
  15. <script src="../dev-lib/sea.js"></script>
  16. <script>
  17. // 设置好 kity 源代码目录
  18. seajs.config( { base: '../src'} );
  19. // 定义 Demo 模块
  20. define('demo', function(require) {
  21. var kity = require('kity');
  22. var Draggable = require('../demo/public/draggable');
  23. kity.extendClass( kity.Paper, Draggable );
  24. });
  25. </script>
  26. <script>
  27. // 启动 Demo 模块
  28. seajs.use('demo');
  29. </script>
  30. <!-- dev end -->
  31. <!-- 生产使用中可以直接引用发布压缩的版本 -->
  32. <!-- production start -->
  33. <!-- 目录型的 Demo 注意修正源码引用路径 -->
  34. <!-- <script src="../dist/kity.min.js"></script> -->
  35. <!-- production end -->
  36. <style>
  37. body, div, html {
  38. margin: 0;
  39. padding: 0;
  40. overflow: hidden;
  41. }
  42. </style>
  43. </head>
  44. <body>
  45. <div id="clock" style="width: 100%; height: 100%; position: absolute;"></div>
  46. </body>
  47. <script>
  48. var G = 6.67e-11;
  49. var SUN_MASS = 1.99e30; // KG
  50. var EARTH_MASS = 5.97e24; // KG
  51. var R_SUN_EARTH = 1.52e11; // meter
  52. // 绘图画布
  53. var paper = new kity.Paper('clock').pipe(function() {
  54. this.setWidth('100%').setHeight('100%');
  55. this.setViewBox(-500, -500, 1000, 1000);
  56. this.setStyle('background', 'black');
  57. }).drag();
  58. var Body = kity.createClass('Body', {
  59. base: kity.Group,
  60. constructor: function() {
  61. this.callBase();
  62. this.shift = new kity.Vector();
  63. this.velocity = new kity.Vector();
  64. this.force = new kity.Vector();
  65. this.mass = 1;
  66. this.size = 5;
  67. this.draw();
  68. },
  69. draw: function() {
  70. return this.addShape(new kity.Circle(this.size).fill('white'));
  71. }
  72. });
  73. var ZERO = 1e-3;
  74. var bodies;
  75. function randomVector(min, max) {
  76. return new kity.Vector(min + Math.random() * (max - min), min + Math.random() * (max - min));
  77. }
  78. function randomize() {
  79. bodies.forEach(function(body) {
  80. body.shift = randomVector(-300, 300);
  81. body.velocity = randomVector(-100, 100);
  82. body.mass = 10 * Math.random();
  83. body.size = 2 + body.mass;
  84. });
  85. }
  86. function collision(a, b) {
  87. if (a.velocity.length() <= ZERO && b.velocity.length() <= ZERO) return false;
  88. // a connect from a to b
  89. var connect = kity.Vector.fromPoints(a.shift, b.shift);
  90. // v projection on the connect
  91. var avc = a.velocity.project(connect),
  92. bvc = b.velocity.project(connect);
  93. // v delta on the connect
  94. var dvc = avc.minus(bvc);
  95. // should check the dcv same direction with the connect
  96. // and the two ball is close enougth
  97. if (dvc.dot(connect) > 0 && connect.length() - a.size - b.size <= ZERO) {
  98. var normal = connect.vertical();
  99. var avn = a.velocity.project(normal),
  100. bvn = b.velocity.project(normal);
  101. // 连线方向速度交换,垂直方向速度不变
  102. var factor = 1;
  103. a.velocity = avn.add(bvc).multipy(factor);
  104. b.velocity = bvn.add(avc).multipy(factor);
  105. return true;
  106. }
  107. return false;
  108. }
  109. G = 30000;
  110. function simulate(frame) {
  111. var tick = 100;
  112. while (tick--) {
  113. bodies.forEach(function(body) {
  114. body.force = new kity.Vector();
  115. bodies.forEach(function(body2) {
  116. if (body2 != body) {
  117. collision(body, body2);
  118. var r = kity.Vector.fromPoints(body.shift, body2.shift);
  119. var f = G * body.mass * body2.mass / (r.square());
  120. body.force = body.force.add(r.normalize(f));
  121. }
  122. });
  123. body.acceleration = body.force.multipy(1 / body.mass);
  124. body.velocity = body.velocity.add(body.acceleration.multipy(0.0005));
  125. body.shift = body.shift.add(body.velocity.multipy(0.0005));
  126. });
  127. }
  128. bodies.forEach(function(body) {
  129. body.setTranslate(body.shift);
  130. body.getShape(0).setRadius(body.size);
  131. });
  132. frame.next();
  133. }
  134. function init() {
  135. bodies = [new Body(), new Body(), new Body(), new Body(), new Body(), new Body(), new Body()];
  136. paper.addShapes(bodies);
  137. paper.on('dblclick', randomize);
  138. randomize();
  139. kity.requestFrame(simulate);
  140. }
  141. function triple() {
  142. var a = bodies[0],
  143. b = bodies[1],
  144. c = bodies[2];
  145. a.mass = b.mass = 500;
  146. a.size = b.size = 5;
  147. a.shift = new kity.Vector(0, 200);
  148. b.shift = new kity.Vector(0, -200);
  149. a.velocity = new kity.Vector(100, 0);
  150. b.velocity = new kity.Vector(-100, 0);
  151. c.mass = 0;
  152. c.shift = new kity.Vector(10000, 100000);
  153. }
  154. function triangle() {
  155. var a = bodies[0],
  156. b = bodies[1],
  157. c = bodies[2];
  158. a.mass = b.mass = c.mass = 1050;
  159. a.size = b.size = c.size = 5;
  160. a.shift = kity.Vector.fromPolar(200, 0);
  161. b.shift = kity.Vector.fromPolar(200, 120);
  162. c.shift = kity.Vector.fromPolar(200, 240);
  163. a.velocity = kity.Vector.fromPolar(300, 60);
  164. b.velocity = kity.Vector.fromPolar(300, 180);
  165. c.velocity = kity.Vector.fromPolar(300, 300);
  166. }
  167. init();
  168. </script>
  169. </html>