Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

Newton

Die Bewegung mehrerer Körper im Raum gemäss der Newton'sche Gravitationstheorie lässt sich mit JGameGrid sehr gut simulieren.

In unserem Beispiel werden drei Körper als Instanzen der Klasse Body erzeugt. In der Methode act() der Klasse Body wird nach physikalischen Formeln für jede Simulationsperiode die neue Position der drei Körper unter der Brücksichtigung der gegenseitigen Anziehungskräfte, berechnet



 
Programmcode
// Newton.java
// Simulation of many-body movement in space

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.util.*;

public class Newton extends GameGrid
{
  public Newton()
  {
    super(8006001nulltrue);
    setSimulationPeriod(50);
    Body body1 = new Body(11E26new GGVector(01E4));
    addActor(body1, new Location(200150));
    Body body2 = new Body(21E27new GGVector(00));
    addActor(body2, new Location(600150));
    Body body3 = new Body(31E25new GGVector(-1E31E4));
    addActor(body3, new Location(40050));
    show();
  }

  public static void main(String[] args)
  {
    new Newton();
  }
}

// -------------------- class Body ---------------------------
class Body extends Actor
{
  private final double scaleFactor = 1E6;
  private final double G = 6.67E-11// Gravitational constant
  private final double mass;
  private double timeFactor = 500;
  private Location oldLocation = new Location(-1-1);
  private GGVector startVelocity;
  private GGVector position;
  private GGVector velocity;
  private GGVector acceleration;
  private boolean drawTrace = true;
  private int id;

  public Body(int id, double mass, GGVector startVelocity)
  {
    super("sprites/body" + id + ".gif");
    this.id = id;
    this.mass = mass;
    this.startVelocity = startVelocity;
  }

  public void reset()
  {
    position = toPosition(getLocationStart());
    velocity = startVelocity.clone();
    oldLocation.x = -1;
    oldLocation.y = -1;
  }

  public GGVector getPosition()
  {
    return position.clone();
  }

  public GGVector getVelocity()
  {
    return velocity.clone();
  }

  public double getMass()
  {
    return mass;
  }

  private GGVector toPosition(Location location)
  {
    return new GGVector(location.x * scaleFactor, location.y * scaleFactor);
  }

  private Location toLocation(GGVector position)
  {
    return new Location((int)(position.x / scaleFactor)(int)(position.y / scaleFactor));
  }

  public void act()
  {
    ArrayList<Actor> neighbours = gameGrid.getActors(Body.class);
    neighbours.remove(this);  // Remove self
    GGVector totalForce = new GGVector();
    for (Actor neighbour : neighbours)
    {
      Body body = (Body)neighbour;
      GGVector r = body.getPosition().sub(position);
      double rmag = r.magnitude();
      GGVector force = r.mult(* mass * body.getMass() / (rmag * rmag * rmag));
      totalForce = totalForce.add(force);
    }
    acceleration = totalForce.mult(1 / mass);
    velocity = velocity.add(acceleration.mult(timeFactor));
    position = position.add(velocity.mult(timeFactor));
    Location location = toLocation(position);
    setLocation(location);

    if (drawTrace)
    {
      switch (id)
      {
        case 1:
          getBackground().setPaintColor(Color.yellow);
          break;
        case 2:
          getBackground().setPaintColor(Color.red);
          break;
        case 3:
          getBackground().setPaintColor(Color.green);
          break;
      }
      if (oldLocation.x != -1)
        getBackground().drawLine(oldLocation.x, oldLocation.y, location.x, location.y);
      oldLocation.x = location.x;
      oldLocation.y = location.y;
    }
  }
}