// // // ANIMALMATCH // // // // M.E. 2011,2012 // // // 4k proof of concept drawing polygons // // // // To build: install proguard, pack200, jarg.jar, kzip, zip2gzip.java // // javac -target 1.5 a.java // jar cvfM a.normal.jar a.class // java -jar jarg.jar -nobco a.normal.jar // java -jar proguard.jar -injars a.normal_s.jar -outjars a.proguard.jar -libraryjars rt.jar -keep public class a -optimizationpasses 9 -overloadaggressively // pack200 --effort=9 --strip-debug --no-keep-file-order -O --no-gzip a.proguard.pack a.proguard.jar // kzip /b96 /y a.proguard.kz.pack a.proguard.pack // java Zip2Gzip a.proguard.kz.pack a.proguard.kz.pack.gz // import java.applet.Applet; // duh import java.awt.image.*; // bufferedimage import java.awt.*; // graphics stuff import java.awt.AWTEvent; // enableEvents import java.awt.event.MouseEvent; // MouseActions import java.util.*; // StringTokenizer // Sound import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; public class a extends Applet implements Runnable { //public : mousecoordinates + state int x=0; int y=0; int m=0; public void start() { new Thread(this).start(); } public void run(){ // public void init(){ // For keyboard: //enableEvents(AWTEvent.KEY_EVENT_MASK); enableEvents(AWTEvent.MOUSE_EVENT_MASK); setVisible(true); requestFocus(); int level=0; // used for demo-levels int score=0; boolean ok=true; final int GRID=8; // only 16 by 16 objects allowed final int TILESIZE=64; //final int TILESIZE=48; final int EXTRA_X=60; // Drawing offsets final int EXTRA_Y=20; final int FISH=2; // objects final int LAND=1; final int BIRD=3; final int BACKGROUND=5; final int BLOCK=4; // // Game States // final int DRAW=102; final int NEXTLEVEL=103; final int LEVELMENU=104; final int LOAD=105; // Start action int action=LEVELMENU; // One large string : poly // Number of points for each object (used to advance throug the poly string) // int[] POLYPOINTS={1,38,57,74,63,61,49,51,84,25,34,32,29,53,27,36}; int objects=POLYPOINTS.length; String poly="+A"; // pig = land5.gif poly+="71-5%:!=%>'=&@'D(C)E,D.C3B4G2J0M1O6N5K6I;K>I8G;CDBEEBIEJIDJ@NAQGRNVMU>V8X:J1"; //poly+="963201..-2*5)8(:)<+=//91:5?6D8F6K5S4V6U8M9K:JV?U@R=K+E,G0D5<6@3F1O;V@UFT@R?Q@M6J:B=?CBKCNJPNLQGUFWBYE[LZPUUJOAQ>TDWHXIZOYFWAQ=U;Z<]?_H\\(=1>:F=K:N9T;YB\\FZLPKLGIFHJ>W:_9N.K/I0E5D;B7A5>7=;83"; poly+="3*857:-;#:(<\"=.?:==@DGKRNYO[RRTIPDE=R?O=J 0){ if(y > 250 && y < 320)level=5; action=NEXTLEVEL; } break; case NEXTLEVEL: level++; action=LOAD; break; case LOAD: coor[0]=coor[1]=0; // empty tiles for(int i=0; i < GRID*GRID; i++)map[i]=BACKGROUND*5; // demo level or random levels? if(level < 6){ // Parse level data int sc=0; int ms=0; int lc=1; boolean msok=false; while(!msok){ if(lc==level){ // format: , [number of tiles, tile] for(int k=1; k < leveldata[sc]; k+=2){ int ws=leveldata[sc+k]; // number of objects [1 = one tile] for(int ks=0; ks < ws; ks++)map[ms++]=leveldata[sc+k+1]; } msok=true; }else{ lc++; sc+=leveldata[sc]+1; } } }else{ // Make pile Random generator = new Random(); int[] pile=new int[64*4]; int index=0; int counter=0; for(int t=0; t < 4; t++){ for(int i=0; i < 4; i++){ for(int k=0; k < 6; k++){ boolean oki=false; while(!oki && counter < 4*15){ index=(generator.nextInt(5*3*4)); if(pile[index]==0){ pile[index]=((counter++)%15)+1; oki=true; } } } } } // map from pile for(int i=0; i < GRID*GRID; i++){ map[i]=pile[i]; } } // MIDDLE PIECEs int move=(GRID*4)+4; map[(GRID*GRID)-4]=map[move];map[move]=16; move=(GRID*3)+4; map[(GRID*GRID)-3]=map[move];map[move]=16; move=(GRID*3)+3; map[(GRID*GRID)-2]=map[move];map[move]=16; move=(GRID*4)+3; map[(GRID*GRID)-1]=map[move];map[move]=16; // ready with load so draw action=DRAW; coor[0]=coor[1]=0; break; } // Switch action // // DRAW // // Do we need to draw the board? if(action == DRAW){ // Draw each grid item for(int i=0; i < GRID*GRID; i++){ int xx=EXTRA_X+((i%GRID)*TILESIZE); int yy=EXTRA_Y+((i>0?i/GRID:0)*TILESIZE); // Middle pieces g.setColor(new Color(250,50,50)); if( map[i]==0 || map[i]==BACKGROUND*5){ g.setColor(new Color(0,0,0)); } else switch(((map[i]-1)/5)+1){ case 1: //land g.setColor(new Color(55,55,0)); break; case 2: // water g.setColor(new Color(0,0,100)); break; case 3: // air g.setColor(new Color(0,0,200)); break; } g.fillRect(xx,yy,TILESIZE,TILESIZE); // Object drawing if(map[i] > 0 && (map[i] < objects || map[i]==16)){ int[] XArray=new int[100];; int[] YArray=new int[100]; if(map[i] < 16){ XArray=new int[POLYPOINTS[map[i]]+1]; YArray=new int[POLYPOINTS[map[i]]+1]; for(int pp=0; pp < POLYPOINTS[map[i]]; pp++){ XArray[pp]=tempXArray[map[i]][pp]+xx; YArray[pp]=tempYArray[map[i]][pp]+yy; } } // clicked? if(i==coor[0]){ g.setColor(new Color(0,0,0)); } else{ switch(((map[i]-1)/5)+1){ case 1: // land g.setColor(new Color(215,155,120)); break; case 2: // fish g.setColor(new Color(0,225,255)); //g.setColor(new Color(0,0,80)); break; case 3: // bird g.setColor(new Color(120,120,160)); break; default: g.setColor(new Color(0,0,0)); break; } // switch } if(map[i]==16){ if(i!=coor[0])g.setColor(new Color(100,0,0)); g.drawRect(xx+3,yy+3, TILESIZE-6, TILESIZE-6); g.fillRect(xx+15,yy+15, 30,30); }else{g.fillPolygon(XArray, YArray,POLYPOINTS[map[i]]);} } // if object } // for all grid items // if demo levels show help text if(level < 6){ g.setColor(new Color(155,155,155)); g.drawString(leveltext[level-1],350-((leveltext[level-1].length()*12))/2 ,120); if(level==5) g.drawString(leveltext[5],350-((leveltext[level-1].length()*12))/2 ,150); } g.setColor(new Color(255,255,255)); // "score; "+score takes 6 bytes extra!! g.drawString("SCORE: ", 632,32); g.drawString(String.valueOf(score), 720,32); g.drawString("RightMouse Click = MENU", 64,560); int sound=-1; int sounditem=0; if(m > 0){ if(m > 1024){ // right mouse = menu action=LEVELMENU; }else{ int calci=((y-EXTRA_Y>0?(y-EXTRA_Y)/TILESIZE:0)*GRID)+(x-EXTRA_X>0?(x-EXTRA_X)/TILESIZE:0); coor[clicktime++]=calci; if(clicktime > 1){ // Are clicked object the same? if(map[coor[0]] == map[coor[1]] && coor[0] != coor[1]){ // make coor[0] the smallest if(coor[0] > coor[1]){int tt=coor[0]; coor[0]=coor[1]; coor[1]=tt;} // Check the coordinates if we can match them boolean check=false; int checktype=((map[coor[0]]-1)/5)+1; int dir=0; int pos=coor[0]; int add=0; while (dir < 2 && !check){ if(pos == coor[1]){ // penalty when you remove the middle pieces if(checktype == BLOCK){ score-=100; sound=1; }else{ score+=((10-checktype)*2); sounditem=map[coor[0]]; sound=0; } map[coor[0]]=BACKGROUND*5; map[coor[1]]=BACKGROUND*5; check=true; }else{ if(dir == 0){ // vertical aligned? // option add = ? : with another ? : if(pos%GRID == coor[1]%GRID){ add=GRID; }else{ // option add= ? : if(pos%GRID > coor[1]%GRID){ add=-1; }else{ add=1; } } // pos%GRID }else{ // coor[1] is always larger than 0 if( (pos > 0?pos/GRID:0) == coor[1]/GRID){ if(pos%GRID > coor[1]%GRID){ add=-1; }else{ add=1; } }else{ add=GRID; } // pos / grid } // dir == 0 || =1 } // match? int type=((map[pos]-1)/5)+1; if( pos == coor[0] || (checktype == FISH && (checktype == type || type == BACKGROUND) && type != BLOCK) || (checktype == BIRD && (checktype != type || type == BACKGROUND) && type != BLOCK) || (checktype == LAND && type == BACKGROUND && type != BLOCK) ){ pos=pos+add; }else{ // Show incorrect int bxx=EXTRA_X+((pos%GRID)*TILESIZE); int byy=EXTRA_Y+((pos>0?pos/GRID:0)*TILESIZE); g.setColor(new Color(255,0,0)); g.drawRect(bxx,byy,TILESIZE,TILESIZE); pos=coor[0]; dir++; sound=1; score-=10; // twice this amount reduction! } } } // equal tiles clicked? else{ // not equal sound=1; score-=2; } boolean notready=false; for(int i=0; i < GRID*GRID; i++){ if(map[i] != BACKGROUND && map[i] != BLOCK && map[i] != 16 && map[i] != 25){ notready=true; } } if(!notready){ score+=100; sound=2; action=NEXTLEVEL; } // // Adapted from swpalmer : http://www.java-gaming.org/index.php/topic,12024.0 // int as = 18000; // note amplitude double zs = Math.PI / 44000; // I'm using a frequency table for the notes here // algorithmic note generation is likely better // 0 = ok, 1=bad, 2 = win double[][] f={{ 261.63, 294.33, 327.03, 348.83, 392.44, 436.05, 490.55 },{ 61.63, 94.33, 61.63, 48.83, 61.63, 36.05, 61.63 },{ 261.63, // C4 1261.63, // C4 261.63, // C4 1261.63, // C4 261.63, // C4 1261.63, // C4 261.63, // C4 1261.63, // C4 261.63, // C4 1261.63, // C4 } }; try{ SourceDataLine L=null; AudioFormat af=new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44000, 16,1,2,44000, true); DataLine.Info dl=new DataLine.Info(SourceDataLine.class,af); //DataLine.Info dl=null; L = (SourceDataLine) AudioSystem.getLine(dl); L.open(); L.start(); byte[] b = new byte[88000]; // here you would read the notes to play from a string or array for(int index=0; index < f.length; index++){ double n=f[sound][index]+(sounditem*20); for (int t = 0; t < 8000*(sound+1);) { short s = (short) (as * Math.sin(t * n * Math.PI / 44000)); b[t++] = (byte) (s >>> 8); b[t++] = (byte) (s & 0xFF); } // bytes L.write(b, 0, 8000*(sound+1)); } L.drain(); L.close(); // Some browsers didn't like this :( // while((System.currentTimeMillis()-t_) < 30){} Thread.sleep(30); } catch (Exception e) {} // EOF SOUND coor[0]=coor[1]=0; // Calculate path clicktime=0; } // clicktime } // right or left click m = 0; // mouseclick reset } } // action == DRAW // // draw buffer to screen (avoid flicker) getGraphics().drawImage(screen,0,0,this); // sleep try{ Thread.sleep(60);}catch(Exception eg){} } // while true } // paint function protected void processMouseEvent(MouseEvent e) { x=e.getX(); y=e.getY(); m=e.getModifiersEx(); // click } }