所以我在 JSFiddle 中建立一个小重力模拟只是为了好玩。到目前为止,这是我的脚本:
var elements = [
{
"id": "earth",
"mass": 30,
"left": 30,
"top": 30,
"hSpeed": 300,
"vSpeed": -300
}, {
"id": "sun",
"mass": 5000,
"left": 50,
"top": 50,
"hSpeed": 0,
"vSpeed": 0
}];
var intervalTime = 10;
var intervalID;
var getDistance = function(x1, y1, x2, y2) {
// h^2 = x^2 + y^2
var xD = x1 - x2;
var yD = y1 - y2;
var hSq = xD * xD + yD * yD;
return Math.sqrt(hSq);
};
var getXPortion = function(val, x1, y1, x2, y2) {
var hD = getDistance(x1, y1, x2, y2);
var xD = x2 - x1;
if ((hD == 0) || (xD == 0) || (val == 0)) {
return 0;
}
return val / hD * xD;
};
var getYPortion = function(val, x1, y1, x2, y2) {
var hD = getDistance(x1, y1, x2, y2);
var yD = y2 - y1;
if ((hD == 0) || (yD == 0) || (val == 0)) {
return 0;
}
return val / hD * yD;
};
var animateWorld = function() {
// Calculate the change in speed for each element
// based on the gravity of all the other elements
var i = 0;
var j = 0;
var dist = 0;
var mass = 0;
var grav = 0;
var change = 0;
var chX = 0;
var chY = 0;
for (i in elements) {
for (j in elements) {
if (i != j) {
dist = getDistance(
elements[i].left,
elements[i].top,
elements[j].left,
elements[j].top
);
mass = elements[i].mass * elements[j].mass;
grav = dist == 0 ? 0 : mass / (dist * dist);
change = grav / elements[i].mass;
elements[i].hSpeed += getXPortion(
change,
elements[i].left,
elements[i].top,
elements[j].left,
elements[j].top
);
elements[i].vSpeed += getYPortion(
change,
elements[i].left,
elements[i].top,
elements[j].left,
elements[j].top
);
}
}
}
// Calculate the new position for each element
// based on the speed and move each element to it's new position
for (i in elements) {
elements[i].left += elements[i].hSpeed / 1000;
elements[i].top += elements[i].vSpeed / 1000;
$('#' + elements[i].id).css('left', elements[i].left + '%');
$('#' + elements[i].id).css('top', elements[i].top + '%');
}
};
$(document).ready(function() {
intervalID = window.setInterval(animateWorld, intervalTime);
});
我允许所有物体根据它们各自的质量和距离相互作用。问题是所有物体都在向右缓慢漂移。由于这是一个封闭的系统,我希望只有当另一个基于质量同等地向左移动时才会向右移动,因此它们不可能随着时间的推移而向同一方向漂移。我认为以下情况之一正在发生,但我不确定:
有什么想法吗?有更简单的方法吗?
答案 0 :(得分:2)
我认为这是你的第二种可能性。
您应该避免循环浏览对象并一次施加一个力。这意味着模拟的行为会有所不同,具体取决于数组中对象的顺序,这不应该发生。
我建议为每个对象添加一些字段,包括' hAcceleration'和' vAcceleration'。循环遍历所有对象并计算每个对象的重力加速度。
然后,循环遍历所有物体,将加速度添加到速度上。然后,再次循环,将速度添加到位置。这就是我过去做过的事情,而且它似乎运作良好。
答案 1 :(得分:2)
实际上有一个问题是@kbelder所说的,但另一个问题是我在 JSFiddle 中修复的物理疏忽。问题是我给了一个物体(地球)一个速度(即动量)而另一个物体(太阳)没有补偿动量,因此整个群体的动量很小。请注意" sun"的"hSpeed": -1.8
和"vSpeed": 1.8
值补偿。
var elements = [
{
"id": "earth",
"mass": 30.0,
"left": 30.0,
"top": 30.0,
"hSpeed": 300.0,
"vSpeed": -300.0
}, {
"id": "sun",
"mass": 5000.0,
"left": 50.0,
"top": 50.0,
"hSpeed": -1.8,
"vSpeed": 1.8
}];
答案 2 :(得分:0)
您正在使用整数类型。必须在最后一步完成除分整数。您执行的每个分区都会导致信息丢失,因为结果必须转换为整数。 尝试将所有操作设置为double类型而不是整数,并仅在将新位置设置为元素时强制 。任何其他计算必须保持两倍。
将一个操作数乘以1.0(即将其转换为加倍)将有助于一点点。所以你可以这样做:
return val * 1.0 / hD * xD;
返回未发布的未结算双。