public class Simulation implements Runnable{
private New_Box app;
private double var[],new_var[];
private int M=4;
private double XMIN=-1.0,XMAX=1.0,YMIN=-1.0,YMAX=1.0;

// Constructor method saves name of applet

Simulation(New_Box box){
app=box;
var = new double[M];
new_var = new double[M];
}

// Simulation must supply a run method if it implements the Runnable Interface

public void run(){

// setup infinite loop

while(true){

// update position of ball
 
update();

// wait 5 millisecs between calls to paint

try{Thread.sleep(10);}
catch(InterruptedException e){}
app.repaint();
}

}

private void update(){
double t,dt;

// allow balls to interact via a repulsive force
// use Runge Kutta to integrate eqns

var[0]=app.ball1.x;
var[1]=app.ball1.vx;
var[2]=app.ball1.y;
var[3]=app.ball1.vy;

t=0.0;
dt=0.01;

rk4(var,new_var,t,dt);

app.ball1.x=new_var[0];
app.ball1.vx=new_var[1];
app.ball1.y=new_var[2];
app.ball1.vy=new_var[3];


// collisions with edges handled by reversing component of velocity
// perpendicular to wall

if(app.ball1.x>XMAX) app.ball1.vx=-app.ball1.vx;
if(app.ball1.y>YMAX) app.ball1.vy=-app.ball1.vy;
if(app.ball1.x<XMIN) app.ball1.vx=-app.ball1.vx;
if(app.ball1.y<YMIN) app.ball1.vy=-app.ball1.vy;


}


// RK method

private void rk4(double y[], double yout[], double x, double dx){
double k1[],k2[],k3[],k4[];
double yt[],dy[],ch[];
int i;

k1 = new double[M];
k2 = new double[M];
k3 = new double[M];
k4 = new double[M];
yt = new double[M];
dy = new double[M];
ch = new double[M];

f(x,y,dy);
for(i=0;i<M;i++){
k1[i]=dx*dy[i];
yt[i]=y[i]+0.5*k1[i];}

f(x+dx*0.5,yt,dy);
for(i=0;i<M;i++){
k2[i]=dx*dy[i];
yt[i]=y[i]+0.5*k2[i];}

f(x+dx*0.5,yt,dy);
for(i=0;i<M;i++){
k3[i]=dx*dy[i];
yt[i]=y[i]+k3[i];}

f(x+dx,yt,dy);
for(i=0;i<M;i++){
k4[i]=dx*dy[i];}

for(i=0;i<M;i++)
ch[i]=(1.0/6.0)*(k1[i]+2*k2[i]+2*k3[i]+k4[i]);

for(i=0;i<M;i++)
yout[i]=y[i]+ch[i];

return;
}

private void f(double x, double y[], double dy[]){
dy[0]=y[1];
dy[1]=0.0;
dy[2]=y[3];
dy[3]=0.0;
return;
}


}

