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 に答える