import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class test1 extends Applet { MotionCanvas X; TextCanvas XX; Animator A; public void init() { setBackground(Color.black); X=new MotionCanvas(); XX=new TextCanvas(); A=new Animator(); A=A.addMotionCanvas(X); X.resize(300,310); XX.resize(430,310); X.setBackground(Color.black); X=X.addAnimator(A); add(X); add(XX); try {A.start();} catch(Exception e) {} A.suspend(); } } class DBCanvas extends Canvas { public void update(Graphics g) { Graphics g2; Image offscreen = null; offscreen = createImage(size().width, size().height); g2 = offscreen.getGraphics(); paint(g2); g.drawImage(offscreen, 0, 0, this); g2.dispose(); offscreen.flush(); } } class TextCanvas extends Canvas { TextCanvas() {} public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.translate(0,20); g.setFont(new Font("Helvetica",Font.PLAIN,35)); g.setColor(Color.red); g.drawString("Drivin' Me Crazy",65,20); g.setFont(new Font("Helvetica",Font.PLAIN,20)); g.setColor(Color.blue); g.drawString("c 2001 Rich Schwartz",85,50); g.drawOval(82,36,16,16); g.setColor(Color.yellow); g.setFont(new Font("Helvetica",Font.PLAIN,15)); g.translate(0,45); g.drawString("You start/stop the game by clicking on the outer",30,50); g.drawString("hexagon. Once the game starts, the layered inner",30,65); g.drawString("hexagon expands and at the same time adds new",30,80); g.drawString("layers to its inner boundary. You control where the",30,95); g.drawString("layers are added by moving the cursor around the",30,110); g.drawString("outer hexagon without clicking on it. Your goal is", 30,125); g.drawString("to keep the inner boundary of the layered hexagon",30,140); g.drawString("from collapsing or splitting open. (Try the game to",30,155); g.drawString("see what this actually means.) You cannot win; the",30,170); g.drawString("best you can do is stave off losing indefinitely. If you",30,185); g.drawString("click on the layered hexagon, the game speeds up.",30,200); g.drawString("you click outside the outer hexagon the game slows",30,215); g.drawString("down. The small slider keeps track of the speed.",30,230); g.setColor(Color.red); g.drawRect(20,27,405,215); } } class MotionCanvas extends DBCanvas implements MouseListener, MouseMotionListener { Animator A; HexWheel[] H=new HexWheel[130]; ListenQuad[] L=new ListenQuad[30]; ListenTriangle[] T=new ListenTriangle[10]; Color[] C=new Color[20]; int count,state,go,history,fail,sleep,tick; ViewInteger V; MotionCanvas() { addMouseListener(this); addMouseMotionListener(this); count=53; state=1; tick=0; go=0; fail=0; history=1; sleep=300; for(int i=0;i<=3;++i) { C[3*i+0]=Color.red; C[3*i+1]=Color.yellow; C[3*i+2]=Color.blue; } for(int i=0;i<=count;++i) H[i]=new HexWheel(); H[0]=H[0].regular(1.0); for(int i=1;i<=count;++i) H[i]=H[i-1].snip(.055,i-6*(i/6)+1); H[0].C=Color.blue; double ii=0; double jj=0; for(int i=1;i<=6;++i) { ii=i+1; jj=ii+1; L[i]=new ListenQuad(); L[6+i]=new ListenQuad(); T[i]=new ListenTriangle(); L[i].x2=150+150*Math.cos(2*Math.PI*ii/6+.01); L[i].y2=150+150*Math.sin(2*Math.PI*ii/6+.01); L[i].x3=150+150*Math.cos(2*Math.PI*jj/6-.01); L[i].y3=150+150*Math.sin(2*Math.PI*jj/6-.01); L[i].x1=150+118*Math.cos(2*Math.PI*ii/6+.01); L[i].y1=150+118*Math.sin(2*Math.PI*ii/6+.01); L[i].x4=150+118*Math.cos(2*Math.PI*jj/6-.01); L[i].y4=150+118*Math.sin(2*Math.PI*jj/6-.01); L[i].C=C[i-6*(i/6)+2]; T[i].x2=150+110*Math.cos(2*Math.PI*ii/6+.01); T[i].y2=150+110*Math.sin(2*Math.PI*ii/6+.01); T[i].x3=150+110*Math.cos(2*Math.PI*jj/6-.01); T[i].y3=150+110*Math.sin(2*Math.PI*jj/6-.01); T[i].x1=150; T[i].y1=150; T[i].C=Color.black; L[6+i].x2=150+350*Math.cos(2*Math.PI*ii/6); L[6+i].y2=150+350*Math.sin(2*Math.PI*ii/6); L[6+i].x3=150+350*Math.cos(2*Math.PI*jj/6); L[6+i].y3=150+350*Math.sin(2*Math.PI*jj/6); L[6+i].x1=150+110*Math.cos(2*Math.PI*ii/6); L[6+i].y1=150+110*Math.sin(2*Math.PI*ii/6); L[6+i].x4=150+110*Math.cos(2*Math.PI*jj/6); L[6+i].y4=150+110*Math.sin(2*Math.PI*jj/6); L[6+i].C=Color.black; L[6+i].state=1; V=new ViewInteger(0); } L[5].state=1; } MotionCanvas addAnimator (Animator A) { MotionCanvas C=this; C.A=A; return(C); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for(int i=0;i<=count;++i) { H[i].render(g); } H[count].render(g,Color.black); if(fail==1) { g.setColor(Color.blue); for(int i=-6;i<=-2;++i) g.drawLine(0,i,300,300+i); for(int i=-6;i<=-2;++i) g.drawLine(300,i,0,300+i); g.setColor(Color.yellow); for(int i=-2;i<=2;++i) g.drawLine(0,i,300,300+i); for(int i=-2;i<=2;++i) g.drawLine(300,i,0,300+i); g.setColor(Color.red); for(int i=2;i<=6;++i) g.drawLine(0,i,300,300+i); for(int i=2;i<=6;++i) g.drawLine(300,i,0,300+i); } for(int i=7;i<=12;++i) L[i].render(g); for(int i=1;i<=6;++i) L[i].render(g); int x=(int)(6000.0/sleep); g.setColor(Color.blue); g.fillRect(75,290,x,15); g.setColor(Color.yellow); g.drawRect(75,290,x,15); g.setColor(Color.red); g.drawRect(75,290,150,15); V.x=tick; /*V.render(287,290,Color.red,g);*/ } void reset() { tick=0; fail=0; count=53; H[0]=H[0].regular(1.0); for(int i=1;i<=count;++i) H[i]=H[i-1].snip(.055,i-6*(i/6)+1); A.suspend(); go=0; } void evolve() { ++tick; H[count].C=C[state]; H[count+1]=H[count].snip(.055,state); ++count; double dil=H[count-1].area()/H[count].area(); dil=Math.sqrt(dil); int conv=H[count].convex(); int boun=H[count].bounded(); if(boun*conv==0) {fail=1;repaint();A.suspend();} for(int i=1;i<=count;++i) H[i]=H[i].dilate(dil); if(count>120) { for(int j=0;j<=90;++j) H[j]=H[j+30]; count=90; } } public void mouseMoved(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); int test=0; for(int i=1;i<=6;++i) { if(L[i].inside(p)==1) test=i; } if(test>0) { state=test-4; if(state<1) state=state+6; for(int j=1;j<=6;++j) L[j].state=0; L[test].state=1; if(test!=history) {repaint();history=test;} } } public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseDragged(MouseEvent e) {} public void mouseClicked(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); int test=0; for(int i=1;i<=6;++i) { if(L[i].inside(p)==1) test=i; } if(test>0) { if(fail==1) {reset();repaint();go=0;} if(go==0) A.resume(); if(go==1) A.suspend(); go=1-go; } for(int i=1;i<=6;++i) { if(T[i].inside(p)==1) test=6+i; } if((test>6)&&(sleep>40)) { sleep=(int)(.9*sleep); repaint(); } if((test==0)&&(sleep<1000)) { sleep=(int)(sleep/.9); repaint(); } } } class Complex { double x,y; Complex() { this.x=0; this.y=0; } Complex(double x,double y) { this.x=x; this.y=y; } Complex add(Complex z,Complex w) { Complex a=new Complex(); a.x=z.x+w.x; a.y=z.y+w.y; return(a); } Complex subtract(Complex z,Complex w) { Complex a=new Complex(); a.x=z.x-w.x; a.y=z.y-w.y; return(a); } Complex times(Complex z,Complex w) { Complex a=new Complex(); a.x=z.x*w.x-z.y*w.y; a.y=z.x*w.y+z.y*w.x; return(a); } double norm() { double d=x*x+y*y; d=Math.sqrt(d); return(d); } Complex unit() { Complex z=new Complex(); double d=this.norm(); z.x=x/d; z.y=y/d; return(z); } Complex conjugate() { Complex w=new Complex(); w.x=x; w.y=-y; return(w); } void print() { System.out.println(this.x); System.out.println(this.y); } double area(Complex z1,Complex z2) { Complex w1=this.subtract(this,z1); Complex w2=this.subtract(this,z2); w2=w2.conjugate(); w1=w1.times(w1,w2); return(w1.y); } } class HexWheel { Complex[] P=new Complex[10]; Color C; double r; HexWheel() { for(int i=1;i<=7;++i) { this.P[i]=new Complex(); } C=Color.black; } HexWheel regular(double r) { HexWheel H=new HexWheel(); double ii=0; for(int i=1;i<=6;++i) { ii=i; H.P[i].x=r*Math.cos(2*Math.PI*ii/6.0); H.P[i].y=r*Math.sin(2*Math.PI*ii/6.0); } H.C=Color.black; H.r=r; return(H); } void render(Graphics g) { int[] X=new int[10]; int[] Y=new int[10]; for(int i=1;i<=6;++i) { X[i-1]=(int)(150+110*P[i].x); Y[i-1]=(int)(150+110*P[i].y); } g.setColor(C); g.fillPolygon(X,Y,6); g.setColor(Color.black); g.drawPolygon(X,Y,6); } void render(Graphics g,Color CC) { int[] X=new int[10]; int[] Y=new int[10]; for(int i=1;i<=6;++i) { X[i-1]=(int)(150+110*P[i].x); Y[i-1]=(int)(150+110*P[i].y); } g.setColor(CC); g.fillPolygon(X,Y,6); g.setColor(Color.black); g.drawPolygon(X,Y,6); } HexWheel snip(double d,int i) { HexWheel H=new HexWheel(); int j=i-2; int k=i+1; int l=i-1; if(l==0) l=6; if(j<1) j=j+6; if(k==7) k=1; Complex z1=new Complex(); Complex z2=new Complex(); z1=z1.subtract(P[j],P[l]); z1=z1.unit(); z2=z2.subtract(P[k],P[i]); z2=z2.unit(); z1.x=z1.x*d*r; z1.y=z1.y*d*r; z2.x=z2.x*d*r; z2.y=z2.y*d*r; for(int a=1;a<=6;++a) { H.P[a].x=P[a].x; H.P[a].y=P[a].y; } H.P[l]=z1.add(P[l],z1); H.P[i]=z2.add(P[i],z2); if((i==1)||(i==4)) H.C=Color.blue; if((i==2)||(i==5)) H.C=Color.red; if((i==3)||(i==6)) H.C=Color.yellow; H.r=r; return(H); } HexWheel dilate(double d) { HexWheel H=new HexWheel(); for(int i=1;i<=6;++i) { H.P[i].x=P[i].x*d; H.P[i].y=P[i].y*d; } H.r=r; H.C=C; return(H); } double area() { double d=0; for(int i=2;i<=5;++i) { d=d+P[1].area(P[i+1],P[i]); } return(d); } int convex() { int test=1; double d=0; for(int i=2;i<=5;++i) { d=P[1].area(P[i+1],P[i]); if(d<0) test=0; } return(test); } int inside(Complex z) { int test=1; double d=0; for(int i=1;i<=5;++i) { d=z.area(P[i+1],P[i]); if(d<0) test=0; } d=z.area(P[1],P[6]); if(d<0) test=0; return(test); } int bounded() { int test=1; HexWheel H=new HexWheel(); H=H.regular(1.0); for(int i=1;i<=6;++i) { if(H.inside(P[i])==0) test=0; } return(test); } } class ListenTriangle { double x1,x2,x3; double y1,y2,y3; int state; Color C; ListenTriangle() { this.x1=x1; this.x2=x2; this.x3=x3; this.y1=y1; this.y2=y2; this.y3=y3; this.C=C; this.state=0; } int inside(Point p) { double v1x,v1y,v2x,v2y; double A1,A2,A3; int val; v1x=p.x-this.x1; v1y=p.y-this.y1; v2x=p.x-this.x2; v2y=p.y-this.y2; A3=v1x*v2y-v1y*v2x; v1x=p.x-this.x2; v1y=p.y-this.y2; v2x=p.x-this.x3; v2y=p.y-this.y3; A1=v1x*v2y-v1y*v2x; v1x=p.x-this.x3; v1y=p.y-this.y3; v2x=p.x-this.x1; v2y=p.y-this.y1; A2=v1x*v2y-v1y*v2x; val=0; if((A1<0)&&(A2<0)&&(A3<0)) val=1; if((A1>0)&&(A2>0)&&(A3>0)) val=1; return(val); } void render(Graphics g) { g.setColor(this.C); Polygon P=new Polygon(); int x[]={(int)(this.x1),(int)(this.x2),(int)(this.x3)}; int y[]={(int)(this.y1),(int)(this.y2),(int)(this.y3)}; P.xpoints=x; P.ypoints=y; P.npoints=3; if(state==1) g.fillPolygon(P); if(state==0) g.drawPolygon(P); } } class ListenQuad { double x1,x2,x3,x4; double y1,y2,y3,y4; int state; Color C; ListenQuad() { this.x1=x1; this.x2=x2; this.x3=x3; this.y1=y1; this.y2=y2; this.y3=y3; this.x4=x4; this.y4=y4; this.C=C; this.state=0; } void render(Graphics g) { g.setColor(this.C); Polygon P=new Polygon(); int x[]={(int)(x1),(int)(x2),(int)(x3),(int)(x4)}; int y[]={(int)(y1),(int)(y2),(int)(y3),(int)(y4)}; P.xpoints=x; P.ypoints=y; P.npoints=4; if(state==1) g.fillPolygon(P); if(state==0) g.drawPolygon(P); } int inside(Point p) { int test=0; ListenTriangle T1=new ListenTriangle(); ListenTriangle T2=new ListenTriangle(); T1.x1=x1; T1.x2=x2; T1.x3=x3; T1.y1=y1; T1.y2=y2; T1.y3=y3; T2.x1=x3; T2.x2=x4; T2.x3=x1; T2.y1=y3; T2.y2=y4; T2.y3=y1; if(T1.inside(p)==1) test=1; if(T2.inside(p)==1) test=1; return(test); } } class ViewInteger { int x; ViewInteger(int x) { this.x=x; } void render(int u, int v, Color C,Graphics g) { int y=x; int place=0; while(y>0) { int z=y-10*(y/10); g.setColor(C); char ch=(char)(z+48); Character CH1=new Character(ch); g.setFont(new Font("Helvetica",Font.PLAIN,20)); g.drawString(CH1.toString(),u-place,v); place=place+12; y=(y-z)/10; } } } class Animator extends Thread { MotionCanvas X; public void run() { while(true) { X.evolve(); X.repaint(); try {sleep(X.sleep);} catch(Exception e) {} } } Animator addMotionCanvas(MotionCanvas X) { Animator B=this; B.X=X; return(B); } }