Search code examples
javasimulationgame-physics

n-Body Simulation Phantom Forces


In my n-Body Simulation I have about 1k particles which fly around. I store the positions as floats. A problem I have is that every time I run the code, when two particles get really close to eachother (essentially the same position), they are extremely accelerated. Normally particles behave smoothly.

if((planet.position.x != otherPlanet.position.x && planet.position.y != otherPlanet.position.y) && !otherPlanet.delete)
        {
            //First we get the x,y and magnitudal distance between the two bodies.
            float xDist = (otherPlanet.position.x - planet.position.x);
            float yDist = (otherPlanet.position.y - planet.position.y);
            float dist = Vector2Math.distance(planet.position, otherPlanet.position);

            //Now we compute first the total and then the component forces
            //Depending on choice, use r or r^2
            float force = Constants.GRAVITATIONAL_CONSTANT * ((planet.mass*otherPlanet.mass)/(dist*dist)); 
            float forceX = force * xDist/dist;
            float forceY = force * yDist/dist;

            //Given the component forces, we construct the force vector and apply it to the body.
            Vector2 forceVec = new Vector2(forceX, forceY);
            planet.force = Vector2Math.add(planet.force, forceVec);
            otherPlanet.force = Vector2Math.subtract(otherPlanet.force, forceVec);
        }

I haven't found anything on this topic, but is this something I'm doin wrong on my part or do I have to implement a max acceleration or a minimum distance between the particles?


Solution

  • Simulated world is a bit different from the real world, and in order to make a good simulation we need to add some restriction.

    Problem:

    When two particles get really close to each other, they just explode outwards at breakneck speeds.

    Cause

    The reason for this is simple force of gravity is inversely proportional to distant squared between two bodies. When the two bodies come too close ,radius (distance between them) becomes very less and the force acting on them become very very large.

    Solution

    Add a virtual limit on how much close two particles can come.By virtual limit i mean that the limit is only on the values but not on the simulation.For ex. if the distance between them is less than 5(a threshold) set the distance to 5.

    Changes in your code

    if((planet.position.x != otherPlanet.position.x && planet.position.y != otherPlanet.position.y) && !otherPlanet.delete)
            {
                //First we get the x,y and magnitudal distance between the two bodies.
                float xDist = (otherPlanet.position.x - planet.position.x);
                float yDist = (otherPlanet.position.y - planet.position.y);
                 // add a limit to xDist and yDist
                 if(xDist<5)
                    xDist=5;
                 if(yDist<5)
                    yDist=5;
                float dist = Vector2Math.distance(planet.position, otherPlanet.position);
    
                //Now we compute first the total and then the component forces
                //Depending on choice, use r or r^2
                float force = Constants.GRAVITATIONAL_CONSTANT * ((planet.mass*otherPlanet.mass)/(dist*dist)); 
                float forceX = force * xDist/dist;
                float forceY = force * yDist/dist;
    
                //Given the component forces, we construct the force vector and apply it to the body.
                Vector2 forceVec = new Vector2(forceX, forceY);
                planet.force = Vector2Math.add(planet.force, forceVec);
                otherPlanet.force = Vector2Math.subtract(otherPlanet.force, forceVec);
            }
    

    Of course you want to change that 5 to a value that suites you simulation.