Sign in to follow this  
deltaweb

How to create a circular orbit and an angry bird space like orbit ?

Recommended Posts

I am working on a 2D game, and I am working on adding some space physics : I need to find a way to create a circular orbit and an orbit like angry birds space ( the spiral trajectory ) . So there is 2 question 
 
First Porblem :
 
I want to create a circular orbit, to make my game object move on a circular way around a planet, I am using the old famous formula : 
 
   
V = sqrt(G * ((m1 + m2 ) / r))

 

 

 
This formula is the classic real world one, V is the velocity of the game object .
 
Once i code it, it doesn't move on a circular way, it just being attracted by the planet, like normal gravity . Here's my code (i'am using Unity 3D ) :
 
  
  dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y);
r = dist.magnitude;
       rigidbody2D.velocity = dist.normalized * (Mathf.Sqrt (0.5f * ((mBody + mPlanet) / r)));
Dist is a 2D vector and r is a float, The G value is 0.5 ( I used this one because 6.673E-11 is very small and it's not what i want )
 
So the question is is how can i make my gameobject move on a circular orbit like a satellite around earth ?
 
One thing to note, is that my gameobject is kicked by the player, so it get a speed of 12 . (i am using addForce() ) .
 
 
2nd problem :
 
I want also to be able to make the gameObject to be attracted by the planet in the same way of angry birds space or something like that, i need it to be attracted in a spiral way, which i can't find any ressource on the web to do that . I am using a simple code that use the Famous Gravitional law of Newton : 
 
    
dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y);
r = dist.magnitude;
float force =  0.5f * mPlanet * mBody / (r * r);
rigidbody2D.AddForce (dist.normalized * force);
0.5 is the value of G, Actually this is a port of a code in C++ that'ive found on a BOX2D forum .
This work very well with attracting object, but what i want is that the gameObject follow an angry birds space like trajectory once it enter the gravity field of the planet : 
74725_400x300.jpg
 
 
So how can achieve a similar effect ?
 
Please explain in beginner friendly way if you answer , I don't have advanced physics  and math knowledge (I am only a high school student ) .
 
Thank's !

Share this post


Link to post
Share on other sites

Hi there,

 

Regarding your first problem, it seems that you have forgotten to apply the velocity perpendicular to the distance vector. Rather it seems like you are applying it in the direction of the attracting body. You do this by making the normalized vector perpendicular: n(x, y) -> n(y, -x) or n(-y, x) depending on wether you want a clockwise or ccw orbit.

 

Regarding the second problem, angry birds space has very little to do with actual physics, so there can't be a definitive answer. Can you describe the desired effect in a little more detail? (Haven't played the game much).

 

Cheers,

Mike

Edited by h4tt3n

Share this post


Link to post
Share on other sites

Well if youve got it attracting to the planet you just need to go around it now. Simplest way would be to just apply a force to move perpendicular to the vector from the object to the planet.

 

vec2 dirToPlant = normalize(planetPos - objectPos);

side = vec2(-dirToPlant.y, dirToPlant.x);

object.AddForce(side * someForce);            // <-- recalc side and do this each frame while inside the attracting region

Share this post


Link to post
Share on other sites

Thank's for every one on their answers, actually i've forgot to apply a vector prependicular to dist vector, But when i did that, i got another problem :

 

The orbiting body is going to far while moving in a circular way, but i don't know why , here's my code again :

dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y).normalized;
r = dist.magnitude;
Vector2 t = new Vector2 (-dist.x,dist.y);
		
float f = Mathf.Sqrt ((5.00f * (mPlanet + mBody)) / r);
rigidbody2D.velocity = t * f ;

Dist is the normalized distance vector, t is the prependicular vector to the dist one, f is the velocity which is calculated from wikipedia : http://en.wikipedia.org/wiki/Circular_orbit#Velocity

 

Please tell me where i'am wrong ?

 

thank's

Share this post


Link to post
Share on other sites

Maybe you should reform your celestial bodies movement.

 

 

   

Quote

V = sqrt(G * ((m1 + m2 ) / r))

 

 

 
This formula is the classic real world one, V is the velocity of the game object .

There exists no formula for speed upon absolute values in general (speed is a property), this is a deviation of newton formula for force of gravitation between two objects at a moment in space, which is F=G*((m1*m2)/(r*r)), and speed at a time equals V=Vo+(F/m)*t   where Vo is current speed vector (tendence) of attracted object, F is gravity force it is attracted by, m is the object's mass and t is time step that F takes effect - until you compute new F vector again pointing to new direction since it sticks to mass center while object has moved (the same also applies on the other object since gravitational force applies on both of the objects, but you can omit the second object if its mass is extremly larger than of the first object)

If there are also other attractors acting on the object, you simply only add also those other forces to the orginal speed of object, and after time step recompute them (vector variables are italic):

V=Vo+(F1/m)*t+(F2/m)*t.....+(Fi/m)*t

 

I would reform your code like this:

 

dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y)/*.normalized*/;

float rdist=dist.magnitude;

//r = dist.magnitude;   beware, you have normalized previous subtraction, this would be just equal to 1.0, not real distance

dist=dist.normalized;

//Vector2 t = new Vector2 (-dist.x,dist.y); 

Vector2 t = new Vector2 (dist.x,dist.y); 

 

float forcesize=consG*((mPlanet * mBody) / (rdist*rdist));

 

Vector2 theforce=new Vector2 (t.x*forcesize,t.y*forcesize);
        
//float f = Mathf.Sqrt ((5.00f * (mPlanet + mBody)) / r);
//rigidbody2D.velocity = t * f ;

rigidbody2D.velocity = rigidbody2D.velocity + theforce*(1.0/mBody)*fixedtimestep  ;

 

establish original rigidbody2D.velocity vector, choose timestep, and estbalish both(all) attracted objects masses

 

 

 

Share this post


Link to post
Share on other sites

If you will wish for circular orbit, then establish your distance D, masses m1 and m2, and the velocity of circulary orbitting object based upon those values would be  

 

V*t=(unit 2d vector orthogonal to distance)* cos(arcsin( (D-G*m1*m2*1/(r*r)*t) /D ) )*D

 

pick t as a second likely,

Share this post


Link to post
Share on other sites

deltaweb, I'm not certain what you mean, could you make a more detailed description? does the gameobject go into orbit even if it's not a circular one? Can the central planet move by applying force to it, or is it fixed in place?

Edited by h4tt3n

Share this post


Link to post
Share on other sites

Here's a quick attempt to help you define the Earth's initial position and initial velocity vector if it were to have a circular orbit path, where the Sun is fixed in position and has no velocity. Try using these parameters first so you'll know if it works as it should, before you start monkeying around with the value of G.

G = 6.67384e11 // Newton's gravitational constant
M = 1.9891e30 // Mass of Sun in kilograms
r = 149597887500 // Earth's semi-major axis -- its average orbit distance in metres
v = sqrt(GM/r) = 29789 // Earth's average orbit speed in metres per second -- NOTE: THIS DIFFERS FROM THE EQUATION THAT YOU'RE USING IN YOUR INITIAL POST.

 

Sun's fixed position = {0,0,0}
Sun's fixed velocity vector = {0,0,0}
Earth's initial position = {0, 149597887500, 0}
Earth's initial velocity vector = {29789, 0, 0} // orthogonal to the position vector

 

It's that simple.

 

If you want to, you can rotate the Earth's initial position and velocity (make sure you rotate both using the same angle) along the z axis before the simulation begins: http://en.wikipedia.org/wiki/Rotation_matrix If you need help with this, let us know. Hint: you can just use the 2D rotation since the orbit path will lie along the xy plane http://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions

 

If you're still stuck, then you're probably doing something wrong when it comes to how you're using a time step (assuming you're calculating acceleration correctly). Check out gaffer's Fix Your Timestep if you haven't already: http://gafferongames.com/game-physics/fix-your-timestep/ and also see the integration basics tutorital http://gafferongames.com/game-physics/integration-basics/ If you're still stuck after reading those two gaffer articles then upload your code into a zip file and post it here.

 

- Shawn

 

P.S. For more information, the following link discusses elliptical orbits:

http://www.gamedev.net/topic/447624-calculating-an-initial-velocity-for-desired-planetary-orbit/#entry3961958

So we're clear, the eccentricity parameter is set to 0 for circular orbits.

Edited by taby

Share this post


Link to post
Share on other sites

Oh, thank's for everyone who answered, i've found a way to do that by playing with rotation and gameobjects, For anyone who would like to know how i did it :

  1. Create an empty gameobject and set it postions to the planet pos
  2. make your orbited gameobject a child of this empty object .
  3. Rotate the empty game object with a Z angle ( 2D way ) .

This can only be done using unity.

Once again thank's for everyone, i've learned a lot .

Share this post


Link to post
Share on other sites

Oh, thank's for everyone who answered, i've found a way to do that by playing with rotation and gameobjects, For anyone who would like to know how i did it :

  1. Create an empty gameobject and set it postions to the planet pos
  2. make your orbited gameobject a child of this empty object .
  3. Rotate the empty game object with a Z angle ( 2D way ) .

This can only be done using unity.

Once again thank's for everyone, i've learned a lot .

NOt realy, you cane establish excenrtig behaviour upon those values (super acceleratred black hole horizont objects/ or, objects that escape observable universe in microseconds). Simulations of newton (no time) law are interesting. Though, this law seems to truly express tendence of attractions if no time is considered towards functional universe

 

If you are after silly circle orbiting stuff, you can just use sine and cosine relations towards distance.

 

A(z,y)= (sin(x),cos(x))  = position...... what is a unit circle still a demanding analisis explenational group relation

Share this post


Link to post
Share on other sites

Believe me deltaweb, it's a much more rewarding experience to actually learn the theory, implement it yourself and see it work than just hack something toghether that only looks real. I should have seen this coming, but I overlooked the angry birds warning. :-)

Edited by h4tt3n

Share this post


Link to post
Share on other sites

Okay, here's the full code that i'am using to implement the circular orbit from the physics side :

using UnityEngine;
using System.Collections;

public class Orbit : MonoBehaviour {
	
	Vector2 dist = new Vector2 ();
	Vector2 tdist;
	float r;
	float mBody;
	float mPlanet;
	public GameObject Planet;
	public float G;





	void Start () {

		mPlanet = Planet.rigidbody2D.mass;
		mBody = rigidbody2D.mass;

	}

	
	void FixedUpdate () {
		circularOrbit(); 

	}

	void applyGravity(){
		dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y);
		r = dist.magnitude;

		float force =  G * mPlanet * mBody / (r * r);
		rigidbody2D.AddForce (dist.normalized * force);


	}
	void circularOrbit(){
		// Get the distance between the two object centers .
		dist = new Vector2 (Planet.renderer.bounds.center.x - renderer.bounds.center.x, Planet.renderer.bounds.center.y - renderer.bounds.center.y);
		r = dist.magnitude;
		tdist = new Vector2 (dist.x, -dist.y).normalized; // 2D vector prependicular to the dist vector .
		float force = Mathf.Sqrt (G * ((mBody + mPlanet) / r)); // Calculate the velocity .
		rigidbody2D.velocity =  tdist * force;


	}
}

The important part is in the circular Orbit function, and here is a small gif of what's hapenning : 

 

http://makeagif.com/i/-JxBG8

 

As you can see the monster is not orbited by the planet, here are some infos :

 

  • Monster mass : 1 unit;
  • Planet mass : 5 unit ;
  • Gravity of the monster is off ;
  • G is 1, but the probleme stay the same for all value that i've tested : 0.1 , 0.01 , 1 , 5 , 20....

All i want to do is to be able to make the monster get in a circular orbit, for the angry bird part, this is a whole another story, that i will work on once i get the circular orbit working .

Edited by deltaweb

Share this post


Link to post
Share on other sites

I'm not sure why your velocity code works.

 

Normally you would calculate the acceleration (where force F = G*M*m / r^2 = m*acceleration ---> acceleration = F / m = G*M / r^2) and then integrate that into the velocity.

 

ie:

 

velocity' = velocity + acceleration*(unit length vector pointing from gravitated object toward gravitating object)*dt

position' = position + velocity*dt

 

...

 

where dt is your time step size.

 

This was covered in the gaffer Euler integration tutorial... but I get the distinct feeling that you aren't interested. :)

Edited by taby

Share this post


Link to post
Share on other sites

What I don't get is why this works: float force = Mathf.Sqrt (G * ((mBody + mPlanet) / r));

 

Have you read up on the subject of dimensional analysis?

 

http://en.wikipedia.org/wiki/Dimensional_analysis#The_fundamental_physical_constants

http://www.efm.leeds.ac.uk/CIVE/CIVE1400/Section5/dimensional_analysis.htm

 

For instance, let's analyze the equation for circular orbit velocity v = sqrt(GM/r)

 

G has dimensions of Length^3 Mass^-1 Time^-2

 

M has dimensions of Mass^1

 

r has dimensions of Length^1

 

GM has dimensions of Length^3 Mass^-1 Time^-2 Mass^1

 

GM/r has dimensions of Length^3 Mass^-1 Time^-2 Mass^1 Length^-1 which simplifies to Length^2 Time^-2

 

v = sqrt(GM/r) has dimensions of Length^1 Time^-1 (ie. metres per second, which stands to reason).

 

The problem that I have with your equation force = sqrt(G * ((mBody + mPlanet) / r)) is that it has dimensions of Length^2 Time^-2, which is not the dimensions of force (which is Mass Length Time^-2) -- in other words, the equation force = Mathf.Sqrt (G * ((mBody + mPlanet) / r)); makes no physical sense. I invite you to double-check my work, in case I made an error during the analysis of your equation. Plus, the practice wouldn't kill you. :)

Edited by taby

Share this post


Link to post
Share on other sites

What I don't get is why this works: float force = Mathf.Sqrt (G * ((mBody + mPlanet) / r));

 

*stuff*

 

Because its actually applied as velocity even though the variable is named "force"

Edited by Waterlimon

Share this post


Link to post
Share on other sites

That's true; I see now.

 

 

One other question I have is why does he add the masses together like that.

 

Its the equation in the first post, just with "velocity" replaced with "force", and the equation adds them like that, and the equation must be correct because its quoted from elsewhere.

Share this post


Link to post
Share on other sites

Also one more question : for the angry birds like orbital decay, should the drag be constant or it should be dependent on how my gameobject is from the planet ? : closer to the planet---> higher drag value ?

 

the physics engine i'am using take care of air drag calculation, i just have to set a value from the editor or from script ...

 

Also does the velocity of the gameobject affect the drag value ?

Share this post


Link to post
Share on other sites

 

What I don't get is why this works: float force = Mathf.Sqrt (G * ((mBody + mPlanet) / r));

 

*stuff*

 

Because its actually applied as velocity even though the variable is named "force"

 

V=F/m*t=a*t  

 

could you elaborate on how you arrived on that formula for speed, is force derived from the newton law of attraction?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this