我正试图让一个物体围绕另一个物体。我想,并不太难。但事实证明这个圆圈是螺旋式的...我可能使用了错误的公式,但我不确定应该选择哪一个......
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;
执行此代码时,它似乎可以正常工作。对象围绕其父对象以弧形移动的每个帧。
但是,弧越来越大,越来越远。
我犯了什么错误?
答案 0 :(得分:5)
您的浮点值中没有无限精度,并且没有无限小的角度步长。所以这个迭代计算不可能是精确的。
没有确切的迭代解决方案:如果您尝试使用初始方法提高精度,您仍然会出现分歧。
解决方案就是完全从角度计算每一步,这对于一个圆圈很容易:
// 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);
答案 1 :(得分: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;
您也可以在更新位置后应用约束。