N体
显示所有步骤
上一节是三个天体在万有引力作用下运行的现象,下面我们看任意多个天体时怎么处理,如何编程实现。
同样也只需要修改第三部分的代码,对天体的处理方式上做了点点修改,我们用列表存储天体, 这样可以根据需要自己添加任意个天体,变化行数也不多(全屏体验):
var canvasDiv = document.getElementById(parentId);
if (!canvasDiv || !canvasDiv.appendChild) return;
var canvas = document.createElement('canvas');
canvas.setAttribute('id', canvasId);
canvas.setAttribute('style', "margin: 0px 0px 30px 0px;");
canvasDiv.appendChild(canvas);
var imgBg = null;
var img = document.getElementById("spaceBg");
img.onload = function(){ imgBg = img; }
var context = canvas ? canvas.getContext('2d') : null;
var objList = [];
var scaleFactor = 10;
var distUnit = canvas.height / 4;
var sizeUnit = canvas.height / 400;
var scaleX = canvas.width / distUnit / scaleFactor;
var scaleY = canvas.height / distUnit / scaleFactor;
var transX = canvas.width / 2, transY = canvas.height / 2;
var posX = 0, posY = 0;
var obj = makeObject('objA', 1.000 * Math.pow(10, 14), 10 * sizeUnit, posX, posY, {x:0.0,y:0}, 'red');
objList.push(obj);
obj = makeObject('objB', 100.0 * Math.pow(10, 10), 4 * sizeUnit, posX, posY-sizeUnit*220, {x:2.0,y:0}, 'blue');
objList.push(obj);
obj = makeObject('objC', 1.000 * Math.pow(10, 10), 2 * sizeUnit, posX, posY-sizeUnit*120, {x:5.0,y:0}, 'yellow')
objList.push(obj);
obj = makeObject('objD', 1.000 * Math.pow(10, 10), 2 * sizeUnit, posX, posY+sizeUnit*190, {x:3.0,y:0}, 'yellow')
objList.push(obj);
obj = makeObject('objE', 100.0 * Math.pow(10, 10), 4 * sizeUnit, posX-sizeUnit*250, posY, {x:0,y:4}, 'blue');
objList.push(obj);
var limitDraw = 1000/30;
var lastDrawTime = Date.now() - limitDraw;
var limitCalc = 10;
var lastCalcTime = Date.now() - limitCalc;
var calcTimesPerDraw = 3;
function update(){
var now = Date.now();
var deltaDraw = now - lastDrawTime;
if (context && deltaDraw >= limitDraw) {
if (imgBg) context.drawImage(imgBg, 0, 0, imgBg.width, imgBg.height, 0, 0, canvas.width, canvas.height);
for(var obj of objList){
if ( isNaN(obj.x) || isNaN(obj.y) || isNaN(obj.v.x) || isNaN(obj.v.y) ){
console.error('xxx');
continue;
}
drawObject(context, obj, scaleX, scaleY, transX, transY);
}
lastDrawTime = now;
}
var deltaCalc = now - lastCalcTime;
if (deltaCalc >= limitCalc) {
lastCalcTime = now;
for(var tm=0; tm < (calcTimesPerDraw || 10); tm++){
for(var i = 0; i < objList.length; i++){
for(var j = i+1; j < objList.length; j++){
calcUpdate2Object(objList[i], objList[j], limitCalc/1000);
}
}
}
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
有了这套系统,我们可以给天体设置不同的坐标,质量,初始速度,然后观察它们运行起来的规律。甚至可以在网上搜索太阳系里星球的数据,来模拟一个小宇宙... 这个过程必有不少蹊跷现象等待去发现。