<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<!-- 必须强制指定页面编码为 UTF-8 -->
|
|
<meta charset="utf-8">
|
|
|
|
<!-- Demo 的简要说明,必须要填写 -->
|
|
<meta name="description" content="使用 Kity 模拟三体运动">
|
|
|
|
<!-- Demo 的作者,建议填写 -->
|
|
<meta name="author" content="techird@qq.com">
|
|
|
|
<!-- Demo 的标题,必须填写 -->
|
|
<title>三体运动</title>
|
|
|
|
<!-- Demo 开发过程中使用 CMD 引入 Kity 源码,方便调试 -->
|
|
<!-- dev start -->
|
|
<!-- 目录型的 Demo 注意修正源码引用路径 -->
|
|
<script src="../dev-lib/sea.js"></script>
|
|
<script>
|
|
// 设置好 kity 源代码目录
|
|
seajs.config( { base: '../src'} );
|
|
// 定义 Demo 模块
|
|
define('demo', function(require) {
|
|
var kity = require('kity');
|
|
|
|
var Draggable = require('../demo/public/draggable');
|
|
|
|
kity.extendClass( kity.Paper, Draggable );
|
|
});
|
|
</script>
|
|
<script>
|
|
// 启动 Demo 模块
|
|
seajs.use('demo');
|
|
</script>
|
|
<!-- dev end -->
|
|
|
|
<!-- 生产使用中可以直接引用发布压缩的版本 -->
|
|
<!-- production start -->
|
|
<!-- 目录型的 Demo 注意修正源码引用路径 -->
|
|
<!-- <script src="../dist/kity.min.js"></script> -->
|
|
<!-- production end -->
|
|
|
|
<style>
|
|
body, div, html {
|
|
margin: 0;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="clock" style="width: 100%; height: 100%; position: absolute;"></div>
|
|
</body>
|
|
<script>
|
|
|
|
var G = 6.67e-11;
|
|
var SUN_MASS = 1.99e30; // KG
|
|
var EARTH_MASS = 5.97e24; // KG
|
|
var R_SUN_EARTH = 1.52e11; // meter
|
|
|
|
// 绘图画布
|
|
var paper = new kity.Paper('clock').pipe(function() {
|
|
this.setWidth('100%').setHeight('100%');
|
|
this.setViewBox(-500, -500, 1000, 1000);
|
|
this.setStyle('background', 'black');
|
|
}).drag();
|
|
|
|
var Body = kity.createClass('Body', {
|
|
base: kity.Group,
|
|
|
|
constructor: function() {
|
|
this.callBase();
|
|
this.shift = new kity.Vector();
|
|
this.velocity = new kity.Vector();
|
|
this.force = new kity.Vector();
|
|
this.mass = 1;
|
|
this.size = 5;
|
|
this.draw();
|
|
},
|
|
|
|
draw: function() {
|
|
return this.addShape(new kity.Circle(this.size).fill('white'));
|
|
}
|
|
});
|
|
|
|
var ZERO = 1e-3;
|
|
|
|
var bodies;
|
|
|
|
function randomVector(min, max) {
|
|
return new kity.Vector(min + Math.random() * (max - min), min + Math.random() * (max - min));
|
|
}
|
|
|
|
function randomize() {
|
|
bodies.forEach(function(body) {
|
|
body.shift = randomVector(-300, 300);
|
|
body.velocity = randomVector(-100, 100);
|
|
body.mass = 10 * Math.random();
|
|
body.size = 2 + body.mass;
|
|
});
|
|
}
|
|
|
|
function collision(a, b) {
|
|
|
|
if (a.velocity.length() <= ZERO && b.velocity.length() <= ZERO) return false;
|
|
|
|
// a connect from a to b
|
|
var connect = kity.Vector.fromPoints(a.shift, b.shift);
|
|
|
|
// v projection on the connect
|
|
var avc = a.velocity.project(connect),
|
|
bvc = b.velocity.project(connect);
|
|
|
|
// v delta on the connect
|
|
var dvc = avc.minus(bvc);
|
|
|
|
// should check the dcv same direction with the connect
|
|
// and the two ball is close enougth
|
|
if (dvc.dot(connect) > 0 && connect.length() - a.size - b.size <= ZERO) {
|
|
|
|
var normal = connect.vertical();
|
|
|
|
var avn = a.velocity.project(normal),
|
|
bvn = b.velocity.project(normal);
|
|
|
|
// 连线方向速度交换,垂直方向速度不变
|
|
var factor = 1;
|
|
a.velocity = avn.add(bvc).multipy(factor);
|
|
b.velocity = bvn.add(avc).multipy(factor);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
G = 30000;
|
|
|
|
function simulate(frame) {
|
|
var tick = 100;
|
|
while (tick--) {
|
|
bodies.forEach(function(body) {
|
|
body.force = new kity.Vector();
|
|
bodies.forEach(function(body2) {
|
|
if (body2 != body) {
|
|
collision(body, body2);
|
|
var r = kity.Vector.fromPoints(body.shift, body2.shift);
|
|
var f = G * body.mass * body2.mass / (r.square());
|
|
body.force = body.force.add(r.normalize(f));
|
|
}
|
|
});
|
|
body.acceleration = body.force.multipy(1 / body.mass);
|
|
body.velocity = body.velocity.add(body.acceleration.multipy(0.0005));
|
|
body.shift = body.shift.add(body.velocity.multipy(0.0005));
|
|
});
|
|
}
|
|
bodies.forEach(function(body) {
|
|
body.setTranslate(body.shift);
|
|
body.getShape(0).setRadius(body.size);
|
|
});
|
|
frame.next();
|
|
}
|
|
|
|
function init() {
|
|
bodies = [new Body(), new Body(), new Body(), new Body(), new Body(), new Body(), new Body()];
|
|
paper.addShapes(bodies);
|
|
paper.on('dblclick', randomize);
|
|
randomize();
|
|
kity.requestFrame(simulate);
|
|
}
|
|
|
|
function triple() {
|
|
|
|
var a = bodies[0],
|
|
b = bodies[1],
|
|
c = bodies[2];
|
|
a.mass = b.mass = 500;
|
|
a.size = b.size = 5;
|
|
a.shift = new kity.Vector(0, 200);
|
|
b.shift = new kity.Vector(0, -200);
|
|
a.velocity = new kity.Vector(100, 0);
|
|
b.velocity = new kity.Vector(-100, 0);
|
|
|
|
c.mass = 0;
|
|
c.shift = new kity.Vector(10000, 100000);
|
|
}
|
|
|
|
function triangle() {
|
|
var a = bodies[0],
|
|
b = bodies[1],
|
|
c = bodies[2];
|
|
a.mass = b.mass = c.mass = 1050;
|
|
a.size = b.size = c.size = 5;
|
|
a.shift = kity.Vector.fromPolar(200, 0);
|
|
b.shift = kity.Vector.fromPolar(200, 120);
|
|
c.shift = kity.Vector.fromPolar(200, 240);
|
|
a.velocity = kity.Vector.fromPolar(300, 60);
|
|
b.velocity = kity.Vector.fromPolar(300, 180);
|
|
c.velocity = kity.Vector.fromPolar(300, 300);
|
|
}
|
|
|
|
init();
|
|
|
|
</script>
|
|
</html>
|