import java.awt.*; import java.applet.AudioClip; public class example2 extends table { double x, y, dx = 8, dy = 16; int w, p; int G = 10; Color glow0[] = new Color[10]; Color glow1[] = new Color[10]; int score0 = 0, score1 = 0; int state0 = 0, state1 = 0; int win0 = 0, win1 = 0; int boing0 = 0, boing1 = 0; final int DRIP2=0,BOINK=1,BONK=2,CORKPOP=3,DRIP=4,POP=5,POP2=6,SWITCH=7,WHIP=8; String soundNames[] = { "drip2","boink","bonk","corkpop","drip","pop","pop2","switch","whip"}; AudioClip sound[] = new AudioClip[soundNames.length]; AudioClip thud; int n = 0; final int C1s= 0,D1= 1,D1s= 2,E1= 3,F1 = 4,F1s= 5,G1= 6,G1s= 7,A2= 8,A2s= 9, B2 =10,C2=11,C2s=12,D2=13,D2s=14,E2 =15,F2=16,F2s=17,G2=18,G2s=19; String noteNames[] = {"C1s","D1","D1s","E1","F1","F1s","G1","G1s","A2","A2s","B","C2","C2s","D2","D2s","E2","F2","F2s","G2","G2s"}; AudioClip note[] = new AudioClip[noteNames.length]; public void initTable() { w = getTableSize(); p = getPuckSize(); x = w/3; y = w/2; for (int i = 0 ; i < 10 ; i++) { glow0[i] = new Color(255, 170, 0, 255 * (i+1) / G); glow1[i] = new Color(160, 240, 0, 255 * (i+1) / G); } loadSounds(); } boolean isLine0 = true, isLine1 = true; public void drawTable(Graphics g) { x += dx; y += dy; // CHECK FOR WHETHER TO DRAW LINES BETWEEN PUCKS boolean wasLine0 = isLine0; boolean wasLine1 = isLine1; isLine0 = ! isUp(0) && ! isUp(3) && distance(0,3) < w/2; isLine1 = ! isUp(1) && ! isUp(2) && distance(1,2) < w/2; if (isLine0 && ! wasLine0) { boing0 = 30; } if (isLine1 && ! wasLine1) { boing1 = 30; } // SEE WHETHER ANYONE HAS INCREASED THEIR SCORE boolean isFlaring0 = false, isFlaring1 = false, isFlaring2 = false, isFlaring3 = false; if (win0 == 0 && win1 == 0) { if (isLine0) { int state = computeState(getPuckX(0), getPuckY(0), getPuckX(3), getPuckY(3)); if (state > 0 && state0 > 0 && state != state0) { note[E1].play(); note[G1].play(); note[C2].play(); score0++; isFlaring0 = true; isFlaring3 = true; } state0 = state; if (score0 == 10) win0 = G; } if (isLine1) { int state = computeState(getPuckX(1), getPuckY(1), getPuckX(2), getPuckY(2)); if (state > 0 && state1 > 0 && state != state1) { note[D1 ].play(); note[F1 ].play(); note[A2s].play(); score1++; isFlaring1 = true; isFlaring2 = true; } state1 = state; if (score1 == 10) win1 = G; } } // BOUNCE OFF PUCKS for (int i = 0 ; i < 4 ; i++) { if (! isUp(i)) { double _x = x - getPuckX(i); double _y = y - getPuckY(i); double _rr = _x * _x + _y * _y; double dx0 = dx, dy0 = dy; dx += 100000 * _x / _rr / _rr; dy += 100000 * _y / _rr / _rr; if (dx * dx0 + dy * dy0 < 0.9 * (dx * dx + dy * dy)) { note[G2-2*i ].play(); note[G2-2*i-4].play(); switch (i) { case 0: isFlaring0 = true; break; case 1: isFlaring1 = true; break; case 2: isFlaring2 = true; break; case 3: isFlaring3 = true; break; } } // DRAW THE GLOW AROUND EACH PUCK boolean isFlaring = i==0 ? isFlaring0 : i==1 ? isFlaring1 : i==2 ? isFlaring2 : isFlaring3; int boing = i==0 || i==3 ? boing0 : boing1; double scale = boing==0 ? 1 : 1 - Math.cos(1.2 * (30-boing)) * Math.exp(.3 * (boing-30)); for (int j = 0 ; j < G ; j++) { g.setColor((i ==0 || i == 3 ? glow0 : glow1)[j]); int r = (int)(scale * (isFlaring ? 1.3 : 1) * (2*G - j) * p / (2*G)); g.fillOval(getPuckX(i) - r, getPuckY(i) - r, 2 * r, 2 * r); } } } // DRAW LINES BETWEEN PUCKS if (isLine0) { g.setColor(glow0[G-1]); drawLine(g,getPuckX(0), getPuckY(0), getPuckX(3), getPuckY(3), isFlaring0 ? 2.3 : 1); } if (isLine1) { g.setColor(glow1[G-1]); drawLine(g,getPuckX(1), getPuckY(1), getPuckX(2), getPuckY(2), isFlaring1 ? 2.3 : 1); } // DRAW THE SCORE for (int i = 0 ; i < score0 ; i++) { double theta = 2 * Math.PI * i / 10; int x = (int)(w/2 + (w/2 - 20) * Math.cos(theta)); int y = (int)(w/2 + (w/2 - 20) * Math.sin(theta)); g.setColor(glow0[G-1]); g.fillOval(x - 10, y - 10, 20, 20); } for (int i = 0 ; i < score1 ; i++) { double theta = 2 * Math.PI * (i + 0.5) / 10; int x = (int)(w/2 + (w/2 - 20) * Math.cos(theta)); int y = (int)(w/2 + (w/2 - 20) * Math.sin(theta)); g.setColor(glow1[G-1]); g.fillOval(x - 10, y - 10, 20, 20); } // MAINTAIN CONSTANT SPEED double d = Math.sqrt(dx * dx + dy * dy); dx *= 20 / d; dy *= 20 / d; // REFLECT OFF OUTER WALL boolean flash = false; double xx = x - w/2; double yy = y - w/2; double rr = xx * xx + yy * yy; if (rr > w*w/4) { thud.play(); flash = true; double dd = dx * xx + dy * yy; dx -= 2 * dd * xx / rr; dy -= 2 * dd * yy / rr; x += dx; y += dy; } // FLASH ON IMPACT g.setColor(flash ? Color.red : Color.blue); int r = flash ? 20 : 10; g.fillOval((int)x - r, (int)y - r, r+r, r+r); // IF SOMEBODY WINS, SHOW THIS AND RESTART GAME if (win0 > 0) { g.setColor(glow0[--win0]); g.fillRect(0,0,w,w); score0 = score1 = 0; } if (win1 > 0) { g.setColor(glow1[--win1]); g.fillRect(0,0,w,w); score0 = score1 = 0; } boing0 = Math.max(0, boing0 - 1); boing1 = Math.max(0, boing1 - 1); } double distance(int a, int b) { double dx = getPuckX(b) - getPuckX(a); double dy = getPuckY(b) - getPuckY(a); return Math.sqrt(dx * dx + dy * dy); } int computeState(double ax, double ay, double bx, double by) { // IF OUTSIDE OF A CIRCLE CENTERED ON THE MIDPOINT OF THE LINE SEGMENT, RETURN 0 double dx = bx - ax, dy = by - ay, dd = dx * dx + dy * dy; double cx = x - (ax + bx) / 2, cy = y - (ay + by) / 2; if (cx * cx + cy * cy > dd / 4) return 0; // OTHERWISE RETURN 1 IF ON LEFT SIDE OF LINE, OR 2 IF ON RIGHT SIDE OF LINE return (x - ax) * dy - (y - ay) * dx > 0 ? 1 : 2; } int QX[] = new int[4], QY[] = new int[4]; void drawLine(Graphics g, int ax, int ay, int bx, int by, double w) { double dx = bx - ax, dy = by - ay; double d = Math.sqrt(dx * dx + dy * dy); dx *= w * 3 / d; dy *= w * 3 / d; fillQuad(g, (int)(ax - dy), (int)(ay + dx), (int)(bx - dy), (int)(by + dx), (int)(bx + dy), (int)(by - dx), (int)(ax + dy), (int)(ay - dx) ); } void fillQuad(Graphics g, int ax,int ay, int bx,int by, int cx,int cy, int dx,int dy) { QX[0] = ax; QX[1] = bx; QX[2] = cx; QX[3] = dx; QY[0] = ay; QY[1] = by; QY[2] = cy; QY[3] = dy; g.fillPolygon(QX, QY, 4); } public boolean onPickup(int i) { return true; } public boolean onDrop(int i) { return true; } public boolean keyUp(Event e, int key) { if (key >= '1' && key <= '9') { note[n].play(); n = (n + 1) % note.length; } return true; } void loadSounds() { //for (int i = 0 ; i < soundNames.length ; i++) //sound[i] = getAudioClip(getCodeBase(), soundNames[i] + ".wav"); thud = getAudioClip(getCodeBase(), "bump.wav"); for (int i = 0 ; i < noteNames.length ; i++) note[i] = getAudioClip(getCodeBase(), "sounds/" + noteNames[i] + ".au"); } }