JS,对象沿着圆形移动

5

我想让一个物体围绕另一个物体旋转。我觉得这不太难。但结果是一个螺旋形的圆圈... 我可能使用了错误的公式,但我不确定应该用哪个公式代替...

var dx = this.x - this.parent.x,
    dy = this.y - this.parent.y,
    r = Math.atan2(dy, dx);

this.x = Math.sin(r) * this.speed + this.x;
this.y = (Math.cos(r) * this.speed * -1) + this.y;

当您执行此代码时,它似乎可以工作。每个帧,对象将在其父对象周围的弧线上移动。
然而,这条弧线变得越来越大,距离也越来越远。
我犯了什么错误?
2个回答

7
你的浮点值没有无限精度,你也没有无限小的角度步长。因此,这个迭代计算不能完全准确。
没有精确的迭代解:如果你试图通过初始方法提高精度,仍然会出现发散。
解决方案很简单,只需从角度完全计算每个步骤,这对于圆形来说很容易:
// init part, set your own values
var a = 0; // in radian
var r = 100; // radius, in pixels for example
var da = 1; // in radian. Compute this (once!) using r if you like to use an absolute speed and not a radial one


// each modification
a += da
x = r*Math.sin(a);
y = r*Math.cos(a);

这就解释了为什么我所做的每一个更改基本上都使情况变得更糟...代码是正确的,但只是不够精确...不过你的变量和我的匹配吗?a是角度(以度为单位),我猜?r是半径,da是速度? - Johan
这种迭代计算方式在数学上要达到足够的精度是不可能的。 - Denys Séguret
1
a是弧度角,r是半径,da是角速度。 - Denys Séguret

2
@dystroy的解决方案完全合法,但有一种方法可以限制您的迭代方法,使其不会失控。

引入一个新变量R,它是您希望对象绕其父级旋转的固定半径。

var hypot = function(x, y) { return Math.sqrt(x*x + y*y); };
//Run this code only once!
var R = hypot(this.x - this.parent.x, this.y - this.parent.y);

然后您可以添加半径固定的约束条件:

//your original code
var dx = this.x - this.parent.x,
    dy = this.y - this.parent.y,
    r = Math.atan2(dy, dx);

//apply constraint:
//calculate what dx and dy should be for the correct radius:
dx = -R * Math.cos(r);
dy = -R * Math.sin(r);

//force this.x, this.y to match that radius.
this.x = this.parent.x + dx;
this.y = this.parent.y + dy;

//the radius will still be off after your update, but
//the amount by which it is off should remain bounded.
this.x = Math.sin(r) * this.speed + this.x;
this.y = (Math.cos(r) * this.speed * -1) + this.y;

您可以在更新位置后应用约束。

你仍然会有总角位置的差异。基本规则是,只有在无法使用其他方法时,才应该用求和逼近来替换积分。 - Denys Séguret
我仍然不理解这种迭代方法背后的数学原理。你有相关链接吗? - Raffaele
@dystroy 如果目的是得到一个精确的答案,那么应该使用精确的公式。是的,相对于精确的圆形运动,角度会有所偏差。是的,在速度更新后,除非您在速度更新后应用约束条件,否则该点始终会与中心点保持sqrt(R^2 + this.speed^2)的距离。我只是认为通过显式约束来强制执行不变量是解决问题的另一种有趣方式。 - ellisbben
1
@Raffaele,这个想法是你将位移(即速度乘以时间步长)添加到当前位置。在圆周运动中,物体的速度始终与圆周切线相切;这里特定的三角函数和符号组合强制执行此操作。然而,速度乘以时间是一种近似值,会立即使物体偏离圆周。但是,你可以强制它再次回到圆周上;这就是代码中间的四行代码所做的事情。 - ellisbben
@ellis:是的,那很有趣,我不否认。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接