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?
JavaScript: Area and circumference of a circle In geometry, the area enclosed by a circle of radius r is πr2. Here the Greek letter π represents a constant, approximately equal to 3.14159, which is equal to the ratio of the circumference of any circle to its diameter. The circumference of a circle is the linear distance around its edge.
JavaScript objects are containers for named values called properties or methods. Spaces and line breaks are not important. An object definition can span multiple lines: The name:values pairs in JavaScript objects are called properties: Objects can also have methods.
The circumference of a circle is the linear distance around its edge. Why is the area of a circle of a circle pi times the square of the radius? Previous: Write a JavaScript program to create a Clock. Next: Write a JavaScript program to sort an array of JavaScript objects.
The name:values pairs in JavaScript objects are called properties: Objects can also have methods. Methods are actions that can be performed on objects. Methods are stored in properties as function definitions. A method is a function stored as a property. In a function definition, this refers to the "owner" of the function.
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 compute each step completely 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With