---- Bouncing Ball Applet ----
// **** The Bouncing Ball Applet *****
// ***** This applet by M. Gallant 4/26/96 ******
import java.awt.*;
public class bounce extends java.applet.Applet implements Runnable {
Image offIm;
Graphics offGr;
Thread runner;
Color fgnd = Color.black, bgnd;
Font f = new Font("TimesRoman", Font.PLAIN, 12);
FontMetrics fmet = getFontMetrics(f) ;
int tPause, xBall, ballDiam, ballRad, wApp, hApp;
int x, bounce, vx, tTotal ;
final double G = 9.8 ; // G in m/sec^2
double con, ymax, ymax0, gb2 , g2, vmax ;
double y, t, tb0, dt, tn, hn, tt, scale ;
boolean Multi ;
TextField tf1, tf2;
Label lb1, lb2 ;
public void init() {
setForeground(fgnd);
bgnd=getBackground();
bgnd = new Color(136,187,221) ;
wApp = this.size().width;
hApp = this.size().height -50;
offIm = createImage(wApp, hApp);
offGr = offIm.getGraphics();
offGr.setColor(Color.red) ;
setFont(f);
Multi = false;
ymax0 = 50; // initial real height in meters.
x = 0; // note that y and ymax are measured from top down.
y = 0.0;
gb2 = G/2.0 ;
g2 = 2.0*G ;
dt = 0.10 ; //time between ball updates in seconds.
tPause = (int)(1000*dt) ; // pause in ms.
ballRad = 3;
ballDiam = 2*ballRad; // ball diameter in pixels.
vx = 2; // lateral velocity in pixels per calculate interval.
setLayout(new FlowLayout());
add (new Label("Height (m)")) ;
tf1 = new TextField(String.valueOf(ymax0) ,5) ;
add (tf1) ;
add (new Button("Multi") ) ;
add (new Button("Time")) ;
lb1 = new Label("Time = sec") ;
add (lb1) ;
lb2 = new Label(" ");
add (lb2) ;
}
public Insets insets(){
return new Insets(hApp+5,5,5,5);
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void pause(int time) {
try { Thread.sleep(time);} // wait for time milliseconds.
catch (InterruptedException e) { }
}
public void run() {
con = Math.sqrt(ymax0/G) ;
tt = Math.sqrt(2.0*ymax0/G)*(3 + 2.0*Math.sqrt(2.0) ) ; // time for all bounces.
scale = hApp/ymax0 ; // scale to Applet vertical size.
// System.out.println("Total time : "+tt) ;
lb2.setText("Tf: "+ .1*(int)(10*tt) + " sec") ;
tb0 = Math.sqrt(2*ymax0/G) ;
x=0; y=0 ;
tTotal = 0;
repaint() ;
pause(250) ;
for(t=0; t<=tb0; t+=dt) { // initial going down.
y = gb2*t*t ;
x = x+vx ;
repaint() ;
tTotal++ ;
pause(tPause) ;
}
ymax = hn = ymax0 ; // initialize for loop.
for (bounce=1; bounce<=1000; bounce++) {
tn = con*Math.sqrt(Math.pow(2,1-bounce)) ; // time for one-way bounce.
hn=hn/2 ; // decrease bounce height by two each bounce.
ymax=ymax0 - hn ; // distance from TOP down.
vmax = Math.sqrt(g2*hn) ; // maximum speed at bottom of fall.
for (t=0; t<=tn; t+=dt) { // going up.
y = ymax0 - vmax*t + gb2*t*t ;
x = x + vx ;
repaint() ;
tTotal++ ;
pause(tPause) ;
}
for(t=0; t<=tn; t+=dt) { // going down.
y = ymax + gb2*t*t ;
x = x + vx ;
tTotal++ ;
repaint() ;
pause(tPause) ;
}
} // end bounces.
} // end run
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
if(!Multi || (tTotal==0)) {
offGr.setColor(Color.white) ;
offGr.fillRect(0,0,wApp,hApp) ;
}
offGr.setColor(Color.red) ;
offGr.fillOval(x-ballRad, (int)(scale*y)-ballRad, ballDiam, ballDiam) ;
g.drawImage(offIm,0,0,this) ;
}
public boolean action(Event evt, Object arg) {
if(evt.target instanceof Button)
controls((String)arg) ;
else
if (evt.target instanceof TextField)
valAdjust((TextField)evt.target) ;
return true;
}
void controls(String butt) {
if(butt.equals("Multi")) {
stop() ;
Multi = !Multi ;
start() ;
}
else
if(butt.equals("Time"))
lb1.setText("Time = " + String.valueOf(tTotal*dt)+ " sec") ;
}
void valAdjust(TextField data) {
stop() ;
Multi = false ;
ymax0 = Double.valueOf(tf1.getText()).doubleValue() ;
start() ;
}
public String getAppletInfo() {
return "Copyright 1996 Michel Gallant";
}
}