import java.awt.*; import java.applet.*; public class billy extends Applet implements Runnable{ Thread moveThread; private static final int MOVEPAUSE = 100; public boolean myGo = false; public boolean inTowR = false; public boolean inTowW = false; public boolean quePull = false; public boolean inHole = false; public boolean pfad = false; public Image offScreenImage; public int it = 0; public int theW = 420; // width of table public int theH = 350; // height of table public int xmin = 40; public int xmax = theW - xmin; public int ymin = 40; public int ymax = theH - ymin; public int r = 12; // ball radius public int d = 2*r+1; public int xQ; public int yQ; public double xW = 100; // initial ball positions public double yW = 50; public double xR = 250; public double yR = 120; public double vxW = 10; // "velocities" public double vyW = 5; public double vxR = 0; public double vyR = 0; public int dxW; public int dyW; public int dxR; public int dyR; public int[] holeX = {xmin, xmax, xmin, xmax,(xmin+xmax)/2,(xmin+xmax)/2}; public int[] holeY = {ymin, ymin, ymax, ymax,ymin-5, ymax+5}; public void start() { if(myGo) { if(moveThread == null){ moveThread = new Thread(this); moveThread.start(); } } } public void stop() { if(moveThread != null){ moveThread.stop(); try { moveThread.join(); } catch (InterruptedException e) { } } moveThread=null; } public void run() { while (true){ try { moveThread.sleep(MOVEPAUSE); }catch(InterruptedException e) { } repaint(); } } public void init() { super.init(); offScreenImage = createImage(500,350); //{{INIT_CONTROLS setLayout(null); resize(500,350); setBackground(new Color(16777215)); //}} repaint(); } //{{DECLARE_CONTROLS //}} public void update(Graphics g){ Graphics offg = offScreenImage.getGraphics(); paint(offg); g.drawImage(offScreenImage, 0, 0, this); } public void paint(Graphics g){ if (!pfad) drawTable(g); if (it == 0) { drawTable(g); drawButtons(g); if (quePull) { g.setColor(Color.yellow); g.drawLine((int)xW+1,(int)yW,xQ+1,yQ); g.drawLine((int)xW-1,(int)yW,xQ-1,yQ); g.drawLine((int)xW,(int)yW+1,xQ,yQ+1); g.drawLine((int)xW,(int)yW-1,xQ,yQ-1); g.drawLine((int)xW,(int)yW,xQ,yQ); } it++; } if (myGo && it < 400 && it > 0) { // moving xW = xW + vxW; yW = yW + vyW; xR = xR + vxR; yR = yR + vyR; if ( (xR > xmax && vxR > 0) || (xR < xmin && vxR < 0)) { xR = xR - vxR; vxR = -vxR; } if ( (yR > ymax && vyR > 0) || (yR < ymin && vyR < 0)) { yR = yR - vyR; vyR = -vyR; } if ( (xW > xmax && vxW > 0) || (xW < xmin && vxW < 0)) { xW = xW - vxW; vxW = -vxW; } if ( (yW > ymax && vyW > 0) || (yW < ymin && vyW < 0)) { yW = yW - vyW; vyW = -vyW; } collideWithWall((int)xW,(int)yW); collideWithWall((int)xR,(int)yR); if (inHole) { g.setColor(Color.red); g.drawString("Ball im Loch",200,200); this.stop(); } // collide the balls double distX = xW - xR; double distY = yW - yR; double distR = Math.sqrt(distX*distX + distY*distY); double relPR = distX*(vxW-vxR) + distY*(vyW-vyR); if (distR < d && relPR < 0) { // collision double vxcm = 0.5*(vxW+vxR); double vycm = 0.5*(vyW+vyR); double vDotrW = (distX*(vxW-vxcm) + distY*(vyW-vycm)) / (distR*distR); double vrxW = distX*vDotrW; double vryW = distY*vDotrW; //System.out.println("Collision, v^2="+(vxR*vxR+vyR*vyR+vxW*vxW+vyW*vyW)); vxR = vxR + 2*vrxW; vyR = vyR + 2*vryW; vxW = vxW - 2*vrxW; vyW = vyW - 2*vryW; //System.out.println(" after, v^2="+(vxR*vxR+vyR*vyR+vxW*vxW+vyW*vyW)); } it++; } g.setColor(Color.white); if (!pfad) { g.fillOval((int)xW-r,(int)yW-r,d,d); } else { g.fillOval((int)xW-1,(int)yW-1,3,3); } g.setColor(Color.red); if (!pfad) { g.fillOval((int)xR-r,(int)yR-r,d,d); } else { g.fillOval((int)xR-1,(int)yR-1,3,3); } if (it == 400) { myGo = false; this.stop(); } // slowing down the balls double vvR = Math.sqrt(vxR*vxR + vyR*vyR); double fR = Math.max(0,(vvR-0.1)/vvR); vxR = vxR*fR; vyR = vyR*fR; double vvW = Math.sqrt(vxW*vxW + vyW*vyW); double fW = Math.max(0,(vvW-0.1)/vvW); vxW = vxW*fW; vyW = vyW*fW; } public void collideWithWall(int x, int y){ for (int i=0; i<6; i++){ if ((int)(Math.abs(x-holeX[i])) < 10 && (int)(Math.abs(y-holeY[i])) < 10){ inHole = true; myGo = false; this.stop(); } } } public void drawButtons(Graphics g){ g.setColor(Color.white); g.fillRect(theW,0,500-theW,350); g.setColor(Color.lightGray); g.fillRect(434,314,62,32); g.fill3DRect(435,315,60,30,true); // stop button g.fillRect(434,4,62,32); g.fill3DRect(435,5,60,30,true); // start button g.setColor(Color.blue); g.setFont(new Font("TimesRoman", Font.PLAIN, 18)); g.drawString("Stop",445,333); g.drawString("Start",445,23); } public void drawTable(Graphics g){ g.setColor(Color.green); g.fillRect(0,0,theW,theH); Color newCol = new Color(0,120,0); g.setColor(newCol); g.fillRect(xmin/2,ymin/2,theW-xmin,theH-ymin); newCol = new Color(0,57,0); g.setColor(newCol); g.fillRect(xmin-r,ymin-r,theW-2*xmin+2*r,theH-2*ymin+2*r); g.setColor(Color.black); // holes g.fillOval(xmin/2-10,ymin/2-10,40,40); g.fillOval(xmin/2-10,theH-ymin/2-30,40,40); g.fillOval(theW-xmin/2-30,ymin/2-10,40,40); g.fillOval(theW-xmin/2-30,theH-ymin/2-30,40,40); g.fillOval(theW/2-20,ymin/2-15,40,40); g.fillOval(theW/2-20,theH-ymin/2-25,40,40); } public boolean handleEvent(Event evt){ if (evt.target == this && evt.id == Event.MOUSE_DOWN) { osc_MouseDown(evt); return true; } if (evt.target == this && evt.id == Event.MOUSE_DRAG) { osc_MouseDrag(evt); return true; } if (evt.target == this && evt.id == Event.MOUSE_UP) { osc_MouseUp(evt); return true; } if (evt.id == Event.KEY_PRESS) { String thePressedKey = ""+(char)evt.key; if (thePressedKey.equalsIgnoreCase("p")) { pfad = !pfad; repaint(); } } return false; } void osc_MouseDrag(Event event) { if (inTowR) { xR = (int)(Math.min(xmax,Math.max(xmin,event.x - dxR))); yR = (int)(Math.min(ymax,Math.max(ymin,event.y - dyR))); it = 0; repaint(); } if (inTowW) { xW = (Math.min(xmax,Math.max(xmin,event.x - dxW))); yW = (Math.min(ymax,Math.max(ymin,event.y - dyW))); it = 0; repaint(); } if (quePull) { xQ = event.x; yQ = event.y; vxW = (double)(xW - xQ) / 10; vyW = (double)(yW - yQ) / 10; it = 0; repaint(); } } void osc_MouseDown(Event event) { vxR = 0; vyR = 0; quePull = false; inHole = false; if (event.x > 425 && event.y > 300) { myGo = false; this.stop(); return; } if (event.x > 425 && event.y < 50) { myGo = true; this.start(); return; } dyR = event.y - (int)yR; dxR = event.x - (int)xR; inTowR = ((int)Math.abs(dxR) < 10 && (int)Math.abs(dyR) < 10); dyW = event.y - (int)yW; dxW = event.x - (int)xW; inTowW = ((int)Math.abs(dxW) < 10 && (int)Math.abs(dyW) < 10); if (inTowR || inTowW) return; // now we need to deal with the que quePull = true; xQ = event.x; yQ = event.y; repaint(); } void osc_MouseUp(Event event) { inTowR = false; inTowW = false; quePull = false; inHole = false; } }