admin管理员组

文章数量:1318766

I'm trying to get an object to circle around another object. Not too hard, I figured. But it turns out the circle is a spiral... I'm probably using the wrong formula but I am not sure which one I should take instead...

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;

When you execute this code, it would appear to work. Each frame the object moves in an arc around it's parent object.

However, the arc gets bigger and bigger, increasing it's distance more and more.

What mistake am I making?

I'm trying to get an object to circle around another object. Not too hard, I figured. But it turns out the circle is a spiral... I'm probably using the wrong formula but I am not sure which one I should take instead...

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;

When you execute this code, it would appear to work. Each frame the object moves in an arc around it's parent object.

However, the arc gets bigger and bigger, increasing it's distance more and more.

What mistake am I making?

Share Improve this question asked Apr 27, 2012 at 9:50 JohanJohan 1,5571 gold badge11 silver badges17 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

You simply don't have infinite precision in your float values, and you don't have infinitely small angular steps. So this iterative calculum cannot be exact.

There is no exact iterative solution : if you try to improve the precision with your initial approach, you'll still get a divergence.

The solution is simply to pute each step pletely from the angulum, which is easy for a circle :

// 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's solution is totally legit, but there is a way to constrain your iterative approach so that it doesn't spiral out of control.

Introduce a new variable, R, which is the fixed radius at which you want your object to circle its parent.

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

Then you can add the constraint that the radius of the circle is fixed:

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

You could also apply the constraint after updating the position.

本文标签: javascriptJSObject following a circleStack Overflow