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;

当您执行此代码时,它似乎可以工作。对象在其父对象周围以弧线移动的每一帧。

然而,弧线越来越大,距离也越来越大。

我犯了什么错误?

4

2 回答 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);
于 2012-04-27T11:15:06.977 回答
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;

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

于 2012-04-27T14:36:39.520 回答