Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Code by Grey Hugentobler, March 31st, 2011 through April 3rd, 2011
- package GravityApplet;
- import java.awt.*;
- import java.util.*;
- import javax.swing.*;
- public class GravityApplet extends JApplet implements Runnable
- {
- // G is the gravitational constant for the depicted universe
- public final float gravitationalConstant = 10;
- // t is the time since the simulation started
- public float time = 0;
- // dt is the increment of time we will advance the simulation by each step
- public final float deltaTime = .02f;
- // number of particles
- public int numberOfPlanets = 500;
- // total mass of the system
- public float totalMass = 0;
- // inverse total mass of the system
- public float inverseTotalMass = 0;
- // center of mass of the system (mechanism to check that the net momentum is in fact 0)
- public Vector centerOfMass = new Vector(0, 0);
- //scalingfactor is basically zoom
- public double scalingFactor = .1;
- // Mass stores the masses of the particles
- public ArrayList<Float> mass = new ArrayList<Float>();
- // inverseMass stores the inverse mass of each particle
- public ArrayList<Float> inverseMass = new ArrayList<Float>();
- // Position is a collection of the particles position Vectors
- public ArrayList<Vector> position = new ArrayList<Vector>();
- // Velocity is a collection of the particles velocity Vectors
- public ArrayList<Vector> velocity = new ArrayList<Vector>();
- // Acceleration is derived from NetForce using Mass.
- public ArrayList<Vector> acceleration = new ArrayList<Vector>();
- // Color is where the random colors are stored
- public ArrayList<Color> color = new ArrayList<Color>();
- // size stores the radius of each blob determined by mass
- public ArrayList<Float> size = new ArrayList<Float>();
- // bufferGraphics is the Graphics buffer
- public Graphics bufferGraphics;
- // offscreen is the image being put together offscreen
- public Image offscreen;
- // dim is the current dimensions of the applet
- public Dimension dimensions;
- // Show center or not
- public boolean showCenter = true;
- // Show time or not
- public boolean showTime = true;
- //Collide or not
- public boolean collisionOn = true;
- //show number of planets or not
- public boolean showNumberOfPlanets = true;
- // Random number Generator
- public Random randomNumberGenerator = new Random();
- // initiate Applet
- public void init()
- {
- // standard deviation of the radius
- double maxRadius = 4000;
- double minRadius = 3500;
- // standard deviation of the velocity
- double maxVelocity = 0;
- double minVelocity = 0;
- // mass statistics
- float maxMass = 10;
- float minMass = 2;
- // generate our distribution of particles
- for (int i = 0; i < numberOfPlanets; i++)
- {
- mass.add(i, minMass + (maxMass - minMass) * randomNumberGenerator.nextFloat());
- inverseMass.add(i, 1 / mass.get(i));
- double randomRadius = (maxRadius - minRadius) * randomNumberGenerator.nextDouble() + minRadius;
- double randomAngle1 = 2 * Math.PI * randomNumberGenerator.nextDouble();
- position.add( i, new Vector(Math.round(randomRadius * Math.cos(randomAngle1)), Math.round(randomRadius * Math.sin(randomAngle1))));
- double randomVelocity = (maxVelocity - minVelocity) * randomNumberGenerator.nextDouble() + minVelocity;
- double randomAngle2 = 2 * Math.PI * randomNumberGenerator.nextDouble() ;
- velocity.add(i, new Vector(Math.round(randomVelocity * Math.cos(randomAngle2)), Math.round(randomVelocity * Math.sin(randomAngle2))));
- acceleration.add(i, new Vector(0, 0));
- float randomRed = randomNumberGenerator.nextFloat();
- float randomGreen = randomNumberGenerator.nextFloat();
- float randomBlue = randomNumberGenerator.nextFloat();
- color.add(i, new Color(randomRed, randomGreen, randomBlue));
- size.add(i, (float) Math.sqrt(mass.get(i)));
- }
- // correct for net momentum so that the system doesn't go off screen
- // create Vector representing net momentum
- Vector netMomentum = new Vector(0, 0);
- // find total momentum and total mass
- for (int i = 0; i < numberOfPlanets; i++)
- {
- netMomentum = netMomentum.add(velocity.get(i).multiply(mass.get(i)));
- totalMass += mass.get(i);
- }
- inverseTotalMass = 1 / totalMass;
- // create vector representing net velocity
- Vector netVelocity = netMomentum.multiply(inverseTotalMass);
- // modify all the velocities to cancel the net momentum
- for (int i = 0; i < numberOfPlanets; i++)
- {
- velocity.set(i, velocity.get(i).subtract(netVelocity));
- }
- // intermediate between the properties of the particles and the center of mass
- Vector massPosition = new Vector(0, 0);
- // add up the masses multiplied by the positions, the masses
- // have already been added up
- for (int i = 0; i < numberOfPlanets; i++)
- {
- massPosition = massPosition.add(position.get(i).multiply(mass.get(i)));
- }
- // calculate the center of mass
- centerOfMass = massPosition.multiply(inverseTotalMass);
- //shift all the planets so that the center of mass is the center
- for (int i = 0; i < numberOfPlanets; i++)
- {
- position.set(i, position.get(i).subtract(centerOfMass));
- }
- // set the background to black, like space
- setBackground(Color.black);
- // start a new thread to run the simulation
- Thread newThread;
- newThread = new Thread(this);
- newThread.start();
- }
- public void paint(Graphics onscreenGraphics)
- {
- // change dimensions to the current size of the Applet
- dimensions = getSize();
- // change the offscreen image to the dimensions of the Applet
- offscreen = createImage(dimensions.width, dimensions.height);
- bufferGraphics = offscreen.getGraphics();
- // Draw all the little dots
- for (int i = 0; i < numberOfPlanets; i++)
- {
- bufferGraphics.setColor(color.get(i));
- bufferGraphics.fillOval((int) ((position.get(i).x() - size.get(i))*scalingFactor + 0.5*dimensions.width - 1), (int) ((position.get(i).y() - size.get(i))*scalingFactor + 0.5 * dimensions.height - 1), (int) (2 * size.get(i) * scalingFactor + 2), (int) (2 * size.get(i) * scalingFactor + 2));
- }
- // draw the time to the screen in a green serif bold font
- if (showTime)
- {
- bufferGraphics.setFont(new Font("serif", Font.BOLD, 12));
- bufferGraphics.setColor(Color.green);
- bufferGraphics.drawString(((int) time + ""), 0, bufferGraphics.getFont().getSize());
- }
- //draw the number of Planets to the screen
- if (showNumberOfPlanets)
- {
- bufferGraphics.setFont(new Font("serif", Font.BOLD, 12));
- bufferGraphics.setColor(Color.green);
- bufferGraphics.drawString(((int) mass.size() + ""), 0, dimensions.height);
- }
- // draw the center of mass
- if (showCenter)
- {
- bufferGraphics.setColor(Color.white);
- bufferGraphics.fillRect((int) (centerOfMass.x() - 1 + 0.5 * dimensions.width), (int) (centerOfMass.y() - 1 + 0.5 * dimensions.height), 2, 2);
- }
- // draw it all to the applet
- onscreenGraphics.drawImage(offscreen, 0, 0, this);
- }
- public void run()
- {
- while (true)
- {
- // check the system time
- long time1 = System.currentTimeMillis();
- // create some storage variables to make the calculations
- // NetForce is where we store the force of all the particles on each individual particle
- Vector[] netForce = new Vector[numberOfPlanets];
- // Force is where we store the force of each particle on each of the other particles
- Vector[][] force = new Vector[numberOfPlanets][numberOfPlanets];
- // radius is the Vector that will point at the next planet
- Vector radius;
- // divisor is the magnitude of radius squared
- float radiusSquared;
- if(collisionOn)
- {
- // size of the radiuses of the planets added together
- float collisionDistance;
- for (int i = 0; i < numberOfPlanets; i++)
- {
- for (int j = i + 1; j < numberOfPlanets; j++)
- {
- radius = (position.get(j).subtract(position.get(i)));
- radiusSquared = radius.dot(radius);
- collisionDistance = size.get(i) + size.get(j);
- if (radiusSquared <= collisionDistance * collisionDistance)
- {
- velocity.set(i, velocity.get(i).multiply(mass.get(i)).add(velocity.get(j).multiply(mass.get(j))).multiply(1 / (mass.get(i) + mass.get(j))));
- position.set(i, position.get(i).multiply(mass.get(i)).add(position.get(j).multiply(mass.get(j))).multiply(1 / (mass.get(i) + mass.get(j))));
- int red = Math.round((mass.get(i) * color.get(i).getRed() + mass.get(j) * color.get(j).getRed()) / (mass.get(i) + mass.get(j)));
- int green = Math.round((mass.get(i) * color.get(i).getGreen() + mass.get(j) * color.get(j).getGreen()) / (mass.get(i) + mass.get(j)));
- int blue = Math.round((mass.get(i) * color.get(i).getBlue() + mass.get(j) * color.get(j).getBlue()) / (mass.get(i) + mass.get(j)));
- color.set(i, new Color(red, green, blue));
- mass.set(i, mass.get(i) + mass.get(j));
- inverseMass.set(i, 1 / mass.get(i));
- size.set(i, ((float) Math.sqrt(mass.get(i))));
- mass.remove(j);
- inverseMass.remove(j);
- position.remove(j);
- velocity.remove(j);
- acceleration.remove(j);
- color.remove(j);
- size.remove(j);
- numberOfPlanets--;
- j--;
- }
- }
- }
- }
- // find all the forces of each planet on each other planet
- for (int i = 0; i < numberOfPlanets; i++)
- {
- for (int j = numberOfPlanets - 1; j >= i; j--)
- {
- radius = (position.get(i).subtract(position.get(j)));
- radiusSquared = radius.dot(radius);
- if (i == j)
- {
- force[i][j] = new Vector(0, 0);
- }
- else
- {
- force[i][j] = radius.multiply(-gravitationalConstant * mass.get(i) * mass.get(j) / radiusSquared);
- }
- force[j][i] = force[i][j].negative();
- }
- }
- // set the net force to zero
- for (int i = 0; i < numberOfPlanets; i++)
- {
- netForce[i] = new Vector(0, 0);
- }
- // sum up the forces to find the total force
- for (int i = 0; i < numberOfPlanets; i++)
- {
- for (int j = 0; j < numberOfPlanets; j++)
- {
- netForce[i] = netForce[i].add(force[i][j]);
- }
- }
- // convert force to acceleration
- for (int i = 0; i < numberOfPlanets; i++)
- {
- acceleration.set(i, netForce[i].multiply(inverseMass.get(i)));
- }
- // integrate the position and velocity
- for (int i = 0; i < numberOfPlanets; i++)
- {
- position.set(i, position.get(i).add(velocity.get(i).multiply(deltaTime)));
- velocity.set(i, velocity.get(i).add(acceleration.get(i).multiply(deltaTime)));
- }
- // increment the time variable
- if (showTime)
- {
- time += deltaTime;
- }
- if (showCenter)
- {
- // intermediate between the properties of the particles and the center of mass
- Vector massPosition = new Vector(0, 0);
- // add up the masses multiplied by the positions, the masses have already been added up
- for (int i = 0; i < numberOfPlanets; i++)
- {
- massPosition = massPosition.add(position.get(i).multiply(mass.get(i)));
- }
- // calculate the center of mass
- centerOfMass = massPosition.multiply(inverseTotalMass);
- }
- // check the systme time again
- long time2 = System.currentTimeMillis();
- //find out how much time we have used
- int timeUsed = (int) (time2 - time1);
- //figure out how much time is left to use
- int timeRemaining = (int) (1000 * deltaTime) - timeUsed;
- //if we have used up our time just move on
- if (timeRemaining < 0)
- {
- timeRemaining = 0;
- }
- // sleep the thread until we are ready
- try
- {
- Thread.sleep(timeRemaining);
- }
- catch (InterruptedException e)
- {
- }
- repaint();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement