2d gravity simulator – smaller object orbiting towards center of bigger object

In my libgdx test game, I have initially created 2 circle objects (stellar) about which I will say more in details below. However, my goal is to simulate gravity in 2d, where smaller object orbits towards center of bigger object (just like earth orbits sun) but closer and closer to the center of bigger.

So, I have created the following:

  • stellar1: smaller, 10px radius, 10 mass, dynamic (can move), initial position -160×90, velocity (0,0), accelerator (0,0)
  • stellar2: bigger, 30px radius, 30 mass, static (cannot move), initial position 0x0, velocity (0,0), accelerator (0,0)

Here is also a screenshot, just to have a picture: enter image description here

I will give the full code below of what I did so far, before that I want to mention I have 2 approaches, StellarTest1 and StellarTest2.

First StellarTest1, I’ve tried to add some extra values like 1000f to both x and y just to see something in action like:

velocity.x += 1000f * acceleration.x * deltaTime; velocity.y += 1000f * acceleration.x * deltaTime; 

Resulting in – smaller object gets towards the center of the bigger object, but once it reaches the center of bigger, the smaller object gets evicted to the opposite side. Not to mention how 1000f is not the correct value in the size of this coordinate system, but I am concerned about following computation:

acceleration.x = gravityForce * (diffX / distance) acceleration.y = gravityForce * (diffY / distance) 

Code StellarTest1:

public class StellarTest1 extends AbstractTest {      private Stellar stellar2, stellar1;      public StellarTest1(Game game) {         super(game);     }      @Override     public void create() {         game.getCartesianGrid().setEnabled(true);          // smaller  stellar         float startX = -160;         float startY = 90;         float radius = 10;         float mass = 10;         stellar1 = new Stellar(                 startX, startY,                 radius, mass,                 new Color(102, 188, 217, 100f)         );          // bigger stellar         startX = 0;         startY = 0;         radius = 30;         mass = 30;         stellar2 = new Stellar(                 startX, startY,                 radius, mass,                 new Color(252, 236, 3, 100f)         );         stellar2.updatable = false; // bigger object will not update, in other words no motion          stellar2.setOther(stellar1);         stellar1.setOther(stellar2);     }      @Override     public void update(float deltaTime) {         if (!updatable) {             return;         }         stellar2.update(deltaTime);         stellar1.update(deltaTime);     }      @Override     public void draw() {         if (!drawable) {             return;         }         stellar2.draw();         stellar1.draw();     }      private class Stellar {          Circle circle;         Vector2 velocity;         Vector2 direction;         Vector2 acceleration;         float mass, radius;         boolean updatable;         Stellar other;          public Stellar(                 float startX, float startY,                 float radius, float mass,                 Color color) {             this.radius = radius;             this.velocity = new Vector2(0, 0);             this.acceleration = new Vector2(0, 0);             this.mass = mass;             this.radius = radius;              circle = new Circle(game,                     color,                     startX, startY,                     radius);              this.updatable = true;         }          public void update(float deltaTime) {             if (!updatable) {                 return;             }             float diffX = other.circle.x - circle.x;             float diffY = other.circle.y - circle.y;              float G = 2f;             float mass = G * (other.mass - this.mass);             float distance = (float) Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));             float gravityForce = (float) (mass / Math.pow(distance, 2));              acceleration.x = gravityForce * (diffX / distance);             acceleration.y = gravityForce * (diffY / distance);              velocity.x += 1000f * acceleration.x * deltaTime;             velocity.y += 1000f * acceleration.y * deltaTime;              circle.x += velocity.x * deltaTime;             circle.y += velocity.y * deltaTime;         }          public void draw() {             game.getShapeRenderer().begin(ShapeRenderer.ShapeType.Filled);             circle.draw();             game.getShapeRenderer().end();         }          public void setOther(Stellar other) {             this.other = other;         }     }  } 

Second StellarTest2, in this example, you will see same code, except I am using here angle in degrees:

float angleInDegrees = MathUtils.atan2(diffY, diffX) * MathUtils.radiansToDegrees; ... acceleration.x = gravityForce * MathUtils.cos(angleInDegrees * deltaTime); acceleration.y = gravityForce * MathUtils.sin(angleInDegrees * deltaTime); 

In this test, I did not have to add some extra velocity to move smaller object. Also I achieved that smaller object will make a solid curve, but will not get dragger in the center. Instead, after some time it will evict out. However, still I face the issue that smaller object keeps curving in and out and towards center. Yet, I am curious if cos and sin is necessary here, and perhaps StellarTest1 is right approach.

Code StellarTest2:

public class Stellar2Test extends AbstractTest {      private Stellar stellar1, stellar2;      public Stellar2Test(Game game) {         super(game);     }      @Override     public void create() {         game.getCartesianGrid().setEnabled(true);          float startX = -160;         float startY = -90;         float radius = 10;         float mass = 30;         stellar2 = new Stellar(                 startX, startY,                 radius, mass,                 new Color(102, 188, 217, 100f)         );          startX = 0;         startY = 0;         radius = 30;         mass = 30;         stellar1 = new Stellar(                 startX, startY,                 radius, mass,                 new Color(252, 236, 3, 100f)         );         stellar1.updatable = false;          stellar1.setOther(stellar2);         stellar2.setOther(stellar1);     }      @Override     public void update(float deltaTime) {         if (!updatable) {             return;         }         stellar1.update(deltaTime);         stellar2.update(deltaTime);     }      @Override     public void draw() {         if (!drawable) {             return;         }         stellar1.draw();         stellar2.draw();     }      private class Stellar {          Circle circle;         Vector2 velocity;         Vector2 acceleration;         float mass, radius;         boolean updatable;         Stellar other;          public Stellar(                 float startX, float startY,                 float radius, float mass,                 Color color) {             this.radius = radius;             this.velocity = new Vector2(0, 0);             this.acceleration = new Vector2(0, 0);             this.mass = mass;             this.radius = radius;              circle = new Circle(game,                     color,                     startX, startY,                     radius);              this.updatable = true;         }          public void update(float deltaTime) {             if (!updatable) {                 return;             }             float diffX = other.circle.x - circle.x;             float diffY = other.circle.y - circle.y;             float angleInDegrees = MathUtils.atan2(diffY, diffX) * MathUtils.radiansToDegrees;              float G = 2;             float mass = (G * (other.mass * this.mass));             float distance = (float) Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));             float gravityForce = mass / distance;              acceleration.x = gravityForce * MathUtils.cos(angleInDegrees * deltaTime);             acceleration.y = gravityForce * MathUtils.sin(angleInDegrees * deltaTime);              velocity.x += acceleration.x * deltaTime;             velocity.y += acceleration.y * deltaTime;              circle.x += velocity.x * deltaTime;             circle.y += velocity.y * deltaTime;         }          public void draw() {             game.getShapeRenderer().begin(ShapeRenderer.ShapeType.Filled);             circle.draw();             game.getShapeRenderer().end();         }          public void setOther(Stellar other) {             this.other = other;         }     }  }