我正在创建类似于2D重力模拟器的东西,只是为了好玩,并注意到我在数学方面是一个完全白痴。我无法让重力发挥作用。
我已经尝试按照发现here的说明进行操作,但看起来很奇怪,当距离达到零时,它会完全失灵。如果我按照问题中的建议将1
添加到距离,则所有对象都会左上角。当距离达到零时,我甚至尝试不修改重力,但这并没有改变行为。
以下是我用来应用重力的算法:
var distX = obj1.x - obj2.x,
distY = obj1.y - obj2.y;
if (obj1 != obj2) {
if (distY != 0) {
obj1.vy += -(1 / (distY));
}
if (distX != 0) {
obj1.vx += -(1 / (distX));
}
}
我也尝试过使用其他算法,但大多数算法并不关心对象之间的距离。
请注意,我希望重力影响远距离物体而不是更近的物体。
答案 0 :(得分:3)
我们可以使用近似值而不是求解任何方程式。 dv/dt = G*M*m/r^2
,但是对于小t,我们可以使用近似值Δv = (G*M*m/r^2)*Δt
。
当物体碰撞时,我实现了完全非弹性碰撞(见Wikipedia)。这可以防止两个物体之间的距离变小,因此最大力是有限的。
我还将对象位置更改的代码部分移动到单独的循环中,因此为obj1和obj2计算的力大小相等。
function tick() {
allObjs.forEach(function (obj1) {
allObjs.forEach(function (obj2) {
var diffX = obj2.x - obj1.x,
var diffY = obj2.y - obj1.y;
var distSquare = diffX*diffX + diffY*diffY
var dist = Math.sqrt(distSquare);
if (obj1 != obj2) {
if (dist > obj1.w/2 + obj2.w/2) {
//If you add mass to the objects change to obj2.mass
//instead of 50
var totalForce = 50/distSquare;
obj1.vx += totalForce * diffX / dist;
obj1.vy += totalForce * diffY / dist;
} else {
//Collision has occurred
//If you add mass to the objects change to
//tempX = (obj1.mass*obj1.vx + obj2.mass*obj2.vx)/(obj1.mass+
//obj2.mass);
//tempY = (obj1.mass*obj1.vy + obj2.mass*obj2.vy)/(obj1.mass+
//obj2.mass);
var tempX = (obj1.vx + obj2.vx)/2;
var tempY = (obj1.vy + obj2.vy)/2;
obj1.vx = tempX; obj2.vx = tempX;
obj1.vy = tempY; obj2.vy = tempY;
}
}
});
});
allObjs.forEach(function (obj1) {
obj1.x += obj1.vx / 25;
obj1.y += obj1.vy / 25;
});
stage.update();
}
答案 1 :(得分:0)
牛顿的运动方程F = ma
需要在这里解决。您在代码中没有做过类似的事情。难怪它与你的直觉不符。
这将有助于理解物理学。
这是 vector 等式。力是重力,遵循反距离平方定律。
您还知道加速度,速度和位移是如何相关的。你必须知道微积分。
对于您的2D世界,这意味着问题中每个身体的六个方程式。两个物体意味着12个耦合方程。
求解这些方程意味着及时积分所有耦合的常微分方程。您需要了解一些有关数值方法的知识(例如Runga-Kutta 5阶积分与纠错)。
你自己要学会写这样的东西有很多东西。我建议您查看像Box2D这样的JavaScript物理库或Google可能find的其他内容。
答案 2 :(得分:0)
尝试
var distX = obj1.x - obj2.x,
distY = obj1.y - obj2.y;
var rsq = distX *distX + distY * distY;
var r = Math.sqrt(rsq);
var F = 50 / rsq; // constant chosen to be pleasing
var rhat_x = distX / r;
var rhat_y = distY / r;
var Fx = F * rhat_x;
var Fy = F * rhat_y;
obj1.vx += -Fx;
obj1.vy += -Fy;
obj2.vx += Fx;
obj2.vy += Fy;
这是非常基本的,它没有考虑到质量,它使用最简单的方法求解方程式,你应该真正使用像5阶Runga-Kutta w /纠错的东西。但它确实使用了引力公式
F = - G m1 m2 / r^2
其中G是万有引力常数,m1 m2是两个质量(我所有这些都是1!)r ^ 2是物体之间距离的平方。力是朝向另一个物体的方向,让它成为单位向量rhat
所以力的向量版本,使用1作为常量
F = - ( 1 / r^2 ) rhat
上面给出了合理的结果,你开始用
createPlanet(50, 200, 2, 0, 1);
createPlanet(400, 200, 2, 0, -1);
你必须注意两颗行星不要太靠近,否则加速度会变得无穷大,速度会变得太大。
在玩的时候我试过
var distX = obj1.x - obj2.x,
distY = obj1.y - obj2.y;
var rsq = distX *distX + distY * distY; // square of the distance
var r = Math.sqrt(rsq);
var Fx = distX / r;
var Fy = distY / r;
obj1.vx += -Fx;
obj1.vy += -Fy;
obj2.vx += Fx;
obj2.vy += Fy;
给出令人愉悦但物理上不正确的结果。