Javascript JS,圆后的对象

Javascript JS,圆后的对象,javascript,math,animation,canvas,geometry,Javascript,Math,Animation,Canvas,Geometry,我想让一个物体绕着另一个物体转。不太难,我想。但事实证明这个圆是一个螺旋形的。。。我可能使用了错误的公式,但我不确定应该用哪一个来代替 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) +

我想让一个物体绕着另一个物体转。不太难,我想。但事实证明这个圆是一个螺旋形的。。。我可能使用了错误的公式,但我不确定应该用哪一个来代替

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;
当您执行此代码时,它似乎可以工作。对象围绕其父对象以弧形移动的每一帧

然而,弧越来越大,距离越来越远


我犯了什么错误?

您的浮点值没有无限精度,也没有无限小的角度步长。所以这个迭代计算是不精确的

没有精确的迭代解:如果您试图用初始方法提高精度,您仍然会得到发散

解决方案是完全从角度计算每个步骤,这对于圆来说很容易:

// 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);

@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;

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

这解释了为什么我所做的每一次更改都会让情况变得更糟。。。代码是正确的,但不够精确。。。但是,你的变量和我的变量如何匹配?a是以度为单位的角度,我猜?r是半径,da是速度?用这种迭代计算,在数学上不可能精确到足够的程度。a是以弧度表示的角度,r是半径,da是角速度。你仍然会对总的角位置产生发散。基本规则是,只有当你做不到的时候,你才应该用求和的近似值来代替积分。但我还是不理解这种迭代方法背后的数学原理。你有什么联系吗?@dystroy是的,如果要得到一个确切的答案,人们可能应该使用一个确切的公式。是的,相对于精确的圆周运动,角度将关闭。是的,除非在速度更新后应用约束,否则在速度更新后,该点将始终远离中心sqrt(R^2+this.speed ^2)。我只是认为通过显式约束强制执行不变量是解决问题的另一种有趣的方法。@Raffaele的想法是在当前位置添加一个位移(想想速度乘以时间步长)。在圆中移动的物体的速度始终与圆相切;这里的触发函数和符号的特殊组合强制了这一点。但是,速度乘以时间是一个近似值,它会立即将对象引离一个圆。但是,您可以强制它再次位于圆上;这就是中间4行代码的作用。@ellis:是的,这很有趣,我不否认这一点。