import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;

class Particle
{
  double x;
  double y;
  double z;
  double vx;
  double vy;
  double vz;
  double m;
  double r;
  Color color;
  boolean fstatic;

  Particle()
  {
    x=0;
    y=0;
    z=0;
    vx=0;
    vy=0;
    vz=0;
    m=1;
    r=1;
    color=new Color(0,0,0);
    fstatic=false;
  }
}

public class TestApplet extends Applet 
                        implements Runnable {

  double G;
  double dtime;
  double time;
  double obsx,obsy,obsz;
  int particles;
  int delay;
  int drawdelay;
  long drawTime;
  boolean frozen;
  int centerx,centery,cwidth,cheight;

  Particle p[];

  Thread simThread;

  public void init()
  {
    G=0.001;
    time=0;
    dtime=0.1;
    delay=2;
    drawdelay=60;
    drawTime=System.currentTimeMillis();
    frozen=false;
    cwidth=getSize().width;
    cheight=getSize().height;
    centerx=cwidth/2;
    centery=cheight/2;

    obsx=0;
    obsy=0;
    obsz=-320;

    int i;

    p=new Particle[10];
    for(i=0;i<10;i++)
    {
      p[i]=new Particle();
    }

    p[0].x=0;
    p[0].y=0;
    p[0].z=0;
    p[0].vx=0;
    p[0].vy=0;
    p[0].vz=0;
    p[0].m=1000;
    p[0].color=new Color(255,255,0);
    p[0].fstatic=true;
    p[1].x=0;
    p[1].y=-60;
    p[1].z=-160;
    p[1].vx=0.3;
    p[1].vy=0;
    p[1].vz=0;
    p[1].m=100;
    p[1].color=new Color(0,0,120);
    p[2].x=0;
    p[2].y=-65;
    p[2].z=-180;
    p[2].vx=1.2;
    p[2].vy=0;
    p[2].vz=0;
    p[2].m=100;
    p[2].color=new Color(60,60,0);
    particles=3;

    for(i=0;i<10;i++)
    {
      p[i].r=Math.pow(p[i].m,1./3.);
    }
  }

  public void start()
  {
    if(frozen)
    {
    }
    else
    {
      if(simThread==null)
      {
        simThread=new Thread(this);
      }
      simThread.start();
    }
  }

  public void stop()
  {
    simThread=null;
  }

  public void run()
  {
    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    Thread currentThread=Thread.currentThread();
    long startTime=System.currentTimeMillis();

    int i1,i2;
    double dx,dy,dz;
    double d;
    while(currentThread==simThread)
    {
      time+=dtime;
      for(i1=0;i1<particles;i1++)
      {
        if(p[i1].fstatic==false)
        {
          for(i2=0;i2<particles;i2++)
          {
            if(i1!=i2)
            {
              dx=p[i1].x-p[i2].x;
              dy=p[i1].y-p[i2].y;
              dz=p[i1].z-p[i2].z;
              d=Math.sqrt(dx*dx+dy*dy+dz*dz);
              if(d!=0)
              {
                p[i1].vx-=dtime*G*p[i1].m*p[i2].m*dx/(d*d*d);
                p[i1].vy-=dtime*G*p[i1].m*p[i2].m*dy/(d*d*d);
                p[i1].vz-=dtime*G*p[i1].m*p[i2].m*dz/(d*d*d);
              }
            }
          }
        }
      }
      for(i1=0;i1<particles;i1++)
      {
        p[i1].x+=dtime*p[i1].vx;
        p[i1].y+=dtime*p[i1].vy;
        p[i1].z+=dtime*p[i1].vz;
      }
      if(System.currentTimeMillis()-drawTime>=drawdelay)
      {
        repaint();
        drawTime=System.currentTimeMillis();
      }
      try
      {
        startTime+=delay;
        Thread.sleep(Math.max(0,startTime-System.currentTimeMillis()));
      }
      catch(InterruptedException e)
      {
        break;
      }
    }
  }

  public void destroy()
  {
  }

  public void paint(Graphics g)
  {
    int i;
    double f;
    int x[];
    int y[];
    int z[];
    int r[];
    Color c[];
    x=new int[particles];
    y=new int[particles];
    z=new int[particles];
    r=new int[particles];
    c=new Color[particles];
    for(i=0;i<particles;i++)
    {
      f=-obsz/(p[i].z-obsz);
      x[i]=(int)(f*(p[i].x-obsx));
      y[i]=(int)(f*(p[i].y-obsy));
      z[i]=(int)(p[i].z);
      r[i]=(int)(f*p[i].r);
      c[i]=p[i].color;
      if(r[i]<1)
        r[i]=1;
    }
    g.drawString("Zeit:"+(int)time, 10, 25);
    Zsort(z,x,y,r,c);
    for(i=particles-1;i>=0;i--)
    {
      g.setColor(c[i]);
      g.fillOval(centerx+x[i],centery-y[i],r[i],r[i]);
    }
  }

  void QuickSort(int z[],int lo0,int hi0, int x[],int y[],int r[],Color c[])
  {
    int lo = lo0;
    int hi = hi0;
    int mid;

    if ( hi0 > lo0)
    {
      mid = z[ ( lo0 + hi0 ) / 2 ];
      while( lo <= hi )
      {
        while( ( lo < hi0 ) && ( z[lo] < mid ))
	  ++lo;
        while( ( hi > lo0 ) && ( z[hi] > mid ))
	  --hi;
        if( lo <= hi )
        {
          swap(z,lo,hi, x,y,r,c);
          ++lo;
          --hi;
        }
      }
      if( lo0 < hi )
        QuickSort(z,lo0,hi, x,y,r,c);
      if( lo < hi0 )
        QuickSort(z,lo,hi0, x,y,r,c);
    }
  }

  private void swap(int z[],int i,int j, int x[],int y[],int r[],Color c[])
  {
    int T;
    T = z[i];
    z[i] = z[j];
    z[j] = T;

    Color Tc;
    T = x[i];
    x[i] = x[j];
    x[j] = T;
    T = y[i];
    y[i] = y[j];
    y[j] = T;
    T = r[i];
    r[i] = r[j];
    r[j] = T;
    Tc = c[i];
    c[i] = c[j];
    c[j] = Tc;
  }

  public void Zsort(int z[], int x[],int y[],int r[],Color c[])
  {
    QuickSort(z, 0, z.length - 1, x,y,r,c);
  }
}
