import java.util.*; import java.awt.*; import java.awt.image.*; import java.applet.*; class Ball implements ImageObserver { static final double slowdown = .75; static final double getout = 1; double x,y,vx,vy,vlen,r; int w,h; Image itsImage = null; AudioClip itsBoink; Ball(double tx,double ty) { x=tx; y=ty; vx=0; vy=0; vlen=0; } void SetBoinkSound(AudioClip aClip) { itsBoink=aClip; } void Move() { x += vx; y += vy; } void Accelerate(double ax,double ay) { vx += ax; vy += ay; vlen=Math.sqrt(vx*vx+vy*vy); } boolean Boink(int pinx,int piny,double pinr) { double dx,dy,dist; dx=x-(double)pinx; dy=y-(double)piny; dist=Math.sqrt(dx*dx+dy*dy); if(dist<=pinr+r) { double tvx,tvy,proj; if(itsBoink != null) { itsBoink.stop(); itsBoink.play(); } tvx = vx/vlen; tvy = vy/vlen; dx /= dist; dy /= dist; proj=tvx*dx+tvy*dy; tvx -= 2.0*proj*dx; tvy -= 2.0*proj*dy; vx = tvx*vlen; vy = tvy*vlen; do { x += vx; y += vy; dx=x-(double)pinx; dy=y-(double)piny; dist=Math.sqrt(dx*dx+dy*dy); } while(dist<=pinr+r); vx *= slowdown; vy *= slowdown; vlen=Math.sqrt(vx*vx+vy*vy); return true; } else return false; } void SetImage(Image aImage) { itsImage=aImage; w=itsImage.getWidth(this); h=itsImage.getHeight(this); r=w/2.0; } void Draw(Graphics g) { if(itsImage != null) g.drawImage(itsImage,(int)x-w/2,(int)y-h/2, this); } public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { if((infoflags & (WIDTH | HEIGHT)) == (WIDTH | HEIGHT)) { if(img == itsImage) { w=width; h=height; r=w/2; } return false; } return true; } } public class BallDrop extends Applet implements Runnable { Thread itsThread = null; MediaTracker itsTracker = null; AudioClip itsBoink = null; Vector itsBalls; Dimension offDimension,backDimension; Image offImage,backImage; static final int numrows=8,numcolumns=20,numballs=10,delay=10, topspace=30,sidespace=20; Image pin,ball; double pinr; int ballw,ballh,pinw,pinh,numracks,rackheight[],rackdel[]; public void init() { Dimension d = size(); Ball aBall; itsTracker=new MediaTracker(this); ball = getImage(getDocumentBase(), "smallball.gif"); pin = getImage(getDocumentBase(), "smallpin.gif"); itsTracker.addImage(ball,0); itsTracker.addImage(pin,0); try { itsTracker.waitForAll(); } catch (InterruptedException e) { return; } // itsBoink = getAudioClip(getDocumentBase(),"boink.au"); itsBalls=new Vector(); for(int i=0;i0) g.drawLine((int)((i-1)*scale),(int)oy,(int)(i*scale),(int)y); oy=y; } // Draw 'racks' for(i=0;i0) { ++rackheight[i]; pinx=i*ballw; piny=d.height-rackheight[i]*ballh; g.drawImage(ball,pinx,piny, this); --rackdel[i]; } /* num += rackheight[i]; sumr += rackheight[i]*i; sumrr += rackheight[i]*i*i; */ } /* if(num>0) { mean=sumr/num; stdev=Math.sqrt(sumrr/num - mean*mean); System.out.println(mean + " " + stdev); } */ } void UpdateBalls() { int i,j,k,pinx,piny,rack,bottomy,fr,lr,fc,lc; double scale; Ball aBall; Dimension d = size(); bottomy=d.height; for(Enumeration e = itsBalls.elements();e.hasMoreElements();) { aBall=(Ball)e.nextElement(); aBall.Move(); if(aBall.y>bottomy-aBall.r) { if(itsBoink != null) { itsBoink.stop(); itsBoink.play(); } if(aBall.vlen>.25) { aBall.vx = 0; aBall.vy = -aBall.vy*.25; aBall.y = bottomy-aBall.r; } else { rack=(int)(aBall.x/ballw); if(rack>=0 && rack=numrows-1 ? numrows-1 : k+1; for(i=fr;i<=lr;++i) { // Rows piny=i*(d.height-2*topspace)/(2*numrows)+topspace; scale=(double)(d.width-2*sidespace)/(double)numcolumns; k=(int)((aBall.x-sidespace)/scale-(i%2)/2.0); fc= k<=0 ? 0 : k-1; lc= k>=numcolumns-1 ? numcolumns-1 : k+1; for(j=fc;j<=lc;++j) { // Columns pinx=(int)((j+(i%2)/2.0)*scale+sidespace); aBall.Boink(pinx,piny,pinr); } } } aBall.Accelerate(0,.075); } } }