import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.util.Calendar; import java.io.*; import java.applet.AudioClip; // import sun.audio.*; public final class palmulator extends java.applet.Applet implements MouseListener, Runnable { int i,j,k,l,di,dj,dk,mx,my,mi,mj,mk,ml; int counter,mode=0,nextMode,selected,playing=-1; int sPos,sBot,sUp,sLow; final int pX[]={0,60,60,60,60,0}; final int pY[]={0,10,14,18,22,10}; final int pW[]={34,8,7,7,3,60}; final int pH[]={10,4,4,4,30,60}; final String iconNames[]={"Address","Calc","Date Book","Expense","Graffiti", "HotSync","Iceblox","KVM","KVMutil","Mail","Memo Pad","Prefs","Security", "To Do List","Warp"}; final String various[]={"KVM","Loading & verifying class files..."}, soundNames[]={"click.au","beep.au"}; final int appNums[]={0,0,0, 0,0,0, 1,0,0, 0,0,0, 0,0,2}; Image icons[],pieces[],background; Graphics bg; Color bright=new Color(123,140,90); Calendar ca; StringBuffer tempSB=new StringBuffer(10); String tempS; MediaTracker mt; Font f,fb; FontMetrics fm,fbm; Thread timer; long nextTime,nowTime; AudioClip beep,click; // InputStream sounds[]=new AudioDataStream[2]; bloxCanvas Iceblox; warpCanvas Warp; public void init() { ImageProducer improd; Image collection; InputStream imgstrm,sndstrm; byte sndData[][]=new byte[2][],headerBuf[]=new byte[28]; setBackground(bright); background=createImage(163,160); bg=background.getGraphics(); pieces=new Image[pX.length]; mt = new MediaTracker(this); // collection = getImage (getDocumentBase(),"palmdata.gif"); imgstrm = getClass().getResourceAsStream("palmdata.gif"); try { k=imgstrm.available(); byte imageBytes[] = new byte[k]; i=0; while (i=0) AudioPlayer.player.stop(sounds[playing]); try{ sounds[s].reset(); } catch(IOException ioe){} AudioPlayer.player.start(sounds[s]); playing=s; }*/ public void delayMode(int m) { nextMode=m; mode=1; counter=0; } public void initiateScreen() { bg.setColor(bright); bg.fillRect(0,0,160,160); for (i=0;i<6;i++) bg.drawImage(pieces[4],160,30*i,this); bg.setColor(Color.black); bg.fillRect(0,13,160,2); bg.drawImage(pieces[1],137,5,this); bg.drawImage(pieces[0],53,1,this); bg.setFont(f); bg.drawString("All",149,9); drawTime(); drawScrollbar(); drawIcons(); mode=0; } public void drawTime() { ca=Calendar.getInstance(); tempSB.setLength(0); tempSB.append(ca.get(Calendar.HOUR)); tempSB.append(':'); di=ca.get(Calendar.MINUTE); tempSB.append(di/10); tempSB.append(di%10); tempSB.append(' '); if (ca.get(Calendar.AM_PM)==0) tempSB.append('a'); else tempSB.append('p'); tempSB.append('m'); tempS=tempSB.toString(); bg.setColor(Color.black); bg.fillRoundRect(0,0,47,15,5,5); bg.setColor(bright); bg.setFont(fb); bg.drawString(tempS,23-fbm.stringWidth(tempS)/2,10); } public void drawScrollbar() { if (sPos>0 || sPos0) { bg.copyArea(160,24,3,(128*sPos)/sBot,-5,0); sUp=25+(128*sPos)/sBot; } if (sPos0) { Component c=getComponent(0); remove(c); } } public void mouseEntered(MouseEvent me){} // Interface implementation public void mouseExited(MouseEvent me){} public void mouseReleased(MouseEvent me){} public void mouseClicked(MouseEvent me){} public void mousePressed(MouseEvent me) { if (mode==0) { mx=me.getX(); my=me.getY(); if (mx>152 && mx<160 && my>24 && my<152) { if (mysLow) { sPos=Math.min(sBot-4,sPos+4); bg.setColor(bright); bg.fillRect(0,15,160,145); drawScrollbar(); drawIcons(); repaint(); } } else { mj=Math.min(iconNames.length,sPos*3+12); mk=0; ml=-1; for (mi=3*sPos;mi=13+51*(mk%3) && my>=20+35*(mk/3) && mx<36+51*(mk%3) && my<43+35*(mk/3)) { ml=mi; } mk++; } if (ml>=0) { playClick(); selected=appNums[ml]; if (selected>0) delayMode(2); } } } } public void run() { while(true) { counter++; nowTime=System.currentTimeMillis(); try{ timer.sleep(Math.max(20,nextTime-nowTime)); } catch(InterruptedException e){} nextTime=nowTime+100; switch(mode) { case 0: // Normal if (counter>40) { counter=0; drawTime(); repaint(); } break; case 1: // Delay if (counter>4) { mode=nextMode; if (mode==2) drawKVMScreen(); else if (mode==0) initiateScreen(); repaint(); } break; case 2: // Verification sequence if (counter>20) { mode=3; if (selected==1) { add(Iceblox); Iceblox.init(); Iceblox.setVisible(true); } else { add(Warp); Warp.init(); Warp.setVisible(true); } validate(); } break; case 3: // During a game break; default: break; } } } public void start() { if (timer==null) { timer=new Thread(this); timer.start(); } } public void stop() { if ((timer!=null)&&(timer.isAlive())) { timer.stop(); } timer=null; } public void paint(Graphics g) { g.drawImage(background,0,0,this); } public void update(Graphics g) { g.drawImage(background,0,0,this); } } // Game classes class warpCanvas extends Canvas implements Runnable, MouseListener, KeyListener { Image warplogo,pieces[]=new Image[60],background,backbuf,back1,back2,life,flag; Image buildblocks[]=new Image[27]; Graphics bg,bf,bg1,bg2; Color bright=new Color(123,140,90); static final int sX[]={0,19,38,57,73,89, 105,86, 114,126,114,146,142,126, 0,19,38,57,73,89,105,89, 105,105, 124,142, 135,68,89,0,18,35,51,67,113,0,16,30,44,57,81, 50,68,91,0,18,37,55,70,55,70,0,25,138,116, 110,142,124,106,88}; static final int sY[]={0,0,0,0,0,0, 0,103, 0,0,12,18,0,16, 19,20,17,14,16,14,24,30, 16,20, 36,36, 54,47,46,39,39,37,37,32,44,57,57,57,53,53,32, 64,69,66,93,93,92,88,88,104,104,72,72,72,74, 56,88,90,90,85}; static final int sW[]={19,19,19,16,16,16, 9,9, 12,16,12,14,18,20, 19,19,19,16,16,16,19,16, 9,9, 18,18, 25,21,21,18,17,16,15,14,11,16,14,14,13,11,8, 18,19,19,18,19,18,15,16,16,15,25,25,22,22, 18,18,18,18,18}; static final int sH[]={18,19,17,14,16,14, 10,10, 12,16,12,14,18,20, 20,20,20,16,16,16,20,16, 4,4, 18,18, 18,22,20,18,18,16,15,15,12,15,15,13,11,11,9, 19,19,19,21,23,25,16,16,16,16,21,20,16,16, 18,18,18,18,18}; static final int sdX[]={9,9,9,8,8,8, 5,5, 6,8,6,7,9,10, 9,9,9,8,8,8,9,8, 5,5, 9,9, 9,8,8,9,9,8,8,7,6,8,8,7,7,6,5, 9,10,10,9,9,9,8,9,9,8,12,12,11,11, 9,9,9,9,9}; static final int sdY[]={9,9,7,8,8,6, 5,5, 6,8,6,7,9,10, 9,9,9,8,8,8,9,8, 2,2, 9,9, 5,11,10,9,9,8,7,7,6,8,8,7,6,6,5, 9,9,9,9,9,9,8,8,8,8,9,9,8,8, 9,9,9,9,9}; static java.util.Random random = new java.util.Random(); static final String credits1="By Karl",credits2="H\u00f6rnell"; static final String gameOver="GAME OVER"; static final int levBlocks[]={1,3,6, 8,9,10,11,14, 17,18,21,23,24}; static final int levBlockStart[]={0,3,8},levBlockNum[]={3,5,5},levBackground[]={0,7,16}; static final int blockProperty[]={0,2,0,1,0,0,0, 0,0,0,0,1,0,0,2,0, 0,0,1,0,0,2,0,0,0}; static final boolean hasShadow[]={false,true,false,true,false,false,false, false,false,false,false,true,false,false,true,false, false,false,true,false,false,true,false,false,false}; static final int levEnemies[]={0,0,7,10,0,0,14,15,0,0,16,17}; static final int waveTypes[]={0,1,0,0, 1,2,0,0, 2,1,3,0}; static final int toKill[]={5,5,0,0, 6,5,0,0, 5,7,5,0}; static final int waveShipLook[]={24,24,24,25,25,55,56,56,56,57,58,59}; static final int duckLook[]={43,41,42,41,44,45,46,46,46,45,44}; static int map[]=new int[21*16]; static boolean loaded=false,initiated; static Thread game; static StringBuffer scoreBuf=new StringBuffer(14); static long nextTime=System.currentTimeMillis(),nowTime; static int toDraw[]=new int[25],numDraw; static int toMask[]=new int[60],numMask; static int i,j,k,l,m,n,dir,wantDir,fire,lastDir,counter,dsi; static int scX1,scX2,scY,baseX,updateBase,updateScan; static int fBullets,enemies,eBullets; static int wave,killed; static int fBulNum[]=new int[3],fBulCount,blockList[]=new int[10],blockNum,backBlock; static int enNum[]=new int[5],enCount,collNum[]=new int[10],collCount; static int andX[]=new int[20],andY[]=new int[20],andT[]=new int[20],ands; static int orX[]=new int[20],orY[]=new int[20],orT[]=new int[20],ors; static int xorX[]=new int[20],xorY[]=new int[20],xorT[]=new int[20],xors; static int gameMode,lives,score,newscore,level; static int oDir[]=new int[10],oPos[]=new int[10],oX[]=new int[10], oY[]=new int[10],oType[]=new int[10],oExtra[]=new int[10]; static int expPos[]=new int[8],expA,expB; static int blockQ[]=new int[10],blockPos[]=new int[10],blockStore[]=new int[10]; Font f; FontMetrics fm; MediaTracker tracker; palmulator owner; public warpCanvas(palmulator p) { owner=p; } public void init() { if (!loaded) { ImageProducer improd; Image collection; background=createImage(160,160); bg=background.getGraphics(); backbuf=createImage(160,144); bf=backbuf.getGraphics(); back1=createImage(160,144); bg1=back1.getGraphics(); back2=createImage(160,144); bg2=back2.getGraphics(); tracker = new MediaTracker(this); collection = owner.getImage(owner.getDocumentBase(),"warpdata.gif"); tracker.addImage (collection, 0); try{ tracker.waitForID(0); } catch (InterruptedException e){} improd=collection.getSource(); for (i=0;i<60;i++) { pieces[i]=createImage(new FilteredImageSource(improd, new CropImageFilter(sX[i],sY[i],sW[i],sH[i]))); tracker.addImage(pieces[i],1); } for (i=0;i<27;i++) { buildblocks[i]=createImage(new FilteredImageSource(improd, new CropImageFilter(160+16*(i/11),16*(i%11),16,16))); tracker.addImage(buildblocks[i],1); } warplogo=createImage(new FilteredImageSource(improd, new CropImageFilter(0,120,120,61))); tracker.addImage(warplogo,1); life=createImage(new FilteredImageSource(improd, new CropImageFilter(120,120,15,15))); tracker.addImage(life,1); flag=createImage(new FilteredImageSource(improd, new CropImageFilter(120,135,9,13))); tracker.addImage(flag,1); try{ tracker.waitForID(1); } catch (InterruptedException e){} f=owner.f; fm=owner.fm; bg.setFont(f); addMouseListener(this); addKeyListener(this); scoreBuf.append("SCORE: "); } bg.setColor(bright); bg.fillRect(0,0,160,160); initiated=false; gameMode=99; game=new Thread(this); game.start(); } public void prepareIntro() { if (!initiated) { initiated=true; bg.setColor(bright); bg.fillRect(0,144,160,16); bg.setColor(Color.black); bg.fillRect(0,0,160,144); bg.drawRoundRect(137,145,21,14,6,6); bg.drawString("Exit",141,156); requestFocus(); } for (i=0;i<10;i++) { bg1.drawImage(buildblocks[25],16*i,0,this); bg2.drawImage(buildblocks[25],16*i,0,this); } for (j=1;j<9;j++) for (i=0;i<10;i++) { bg1.drawImage(buildblocks[26],16*i,16*j,this); bg2.drawImage(buildblocks[26],16*i,16*j,this); } bf.setColor(Color.black); bf.fillRect(0,0,160,144); bf.drawImage(warplogo,21,2,this); bf.setColor(bright); bf.setFont(f); bf.drawString(credits1,115,44); bf.drawString(credits2,115,54); for (i=0;i<3;i++) bg.drawImage(life,i*16,145,this); bg.drawImage(flag,115,146,this); scX1=0;scX2=160;scY=64; for (i=0;i<10;i++) oType[i]=0; for (i=0;i<320;i++) map[i]=5; fBullets=0;enemies=0; addObject(1,40,104,3);oDir[0]=104; wantDir=0;fire=0; gameMode=1; } public void prepareGame() { lives=3; score=1; newscore=0; eBullets=0; level=1; bg.setColor(bright); bg.fillRect(124,144,12,16); bg.setColor(Color.black); bg.drawString(level+"",126,156); gameMode=2; oExtra[0]=1; oDir[0]=72; counter=0; wantDir=0;fire=0; } public void drawScore() { scoreBuf.setLength(7); scoreBuf.append(newscore); bg.setColor(bright); bg.fillRect(78,145,37,14); bg.setColor(Color.black); bg.drawString(scoreBuf.toString(),49,156); score=newscore; } public void prepareLife() { bg1.setColor(Color.black); bg1.fillRect(0,0,160,144); bg2.setColor(Color.black); bg2.fillRect(0,0,160,144); for (i=0;i<320;i++) map[i]=5; for (i=0;i<10;i++) oType[i]=0; enemies=0; fBullets=0; eBullets=0; blockQ[0]=-1; updateScan=0; baseX=160-scX2; addObject(3,16,72,0); fixLevelVariables(); } public void fixLevelVariables() { if ((level&1)==1) // Background { expA=expB; backBlock=levBackground[level>>1]; blockNum=levBlockNum[level>>1]; for (i=0;i>1]+i]; gameMode=3; } else // Wave { wave=2*level-4; killed=0; gameMode=4; } counter=0; bg.setColor(bright); bg.fillRect(124,144,12,16); bg.setColor(Color.black); bg.drawString(level+"",126,156); } public void start() { if (game==null) { game=new Thread(this); game.start(); } } public void stop() { if ((game!=null)&&(game.isAlive())) { game.stop(); } game=null; } public void run() { while(true) { counter++; nowTime=System.currentTimeMillis(); try{ game.sleep(Math.max(20,nextTime-nowTime)); } catch(InterruptedException e){} nextTime=nowTime+110; ors=0;ands=0;xors=0; switch(gameMode) { case 1: // Introduction scroll(1); handleObjects(); if ((scX1&15)==0 && fire+wantDir>0) prepareGame(); break; case 2: // Leaving intro scroll(2); handleObjects(); if (oType[0]==1) { if (oX[0]>16) oX[0]--; if (oX[0]==16 && oY[0]==72) { oType[0]=0; addObject(3,16,72,0); } } if (scY>0) scY--; if (scX1>=-144 && scX1<16) // Draw on screen 2 { i=(14-scX1)>>4; j=9*(scX1&14); bg2.fillRect(i<<4,j,16,18); } else // Draw on screen 1 { i=(14-scX2)>>4; j=9*(scX2&14); bg1.fillRect(i<<4,j,16,18); } if (counter>63) fixLevelVariables(); break; case 3: scroll(2); handleObjects(); if ((scX1&14)==14) // Time for a map update { updateScan=0; i=((baseX+176)&0xff0)%320; l=i>>4; if (l>=10) l+=2038; map[i]=1; updateBase=i+1; if (counter>56 && counter<450) { for (k=0;k<9;k++) blockStore[k]=backBlock; k=0; while (k<2) { i=random.nextInt()&0xffff; j=i%9; m=blockList[(i>>>4)%blockNum]; if (blockStore[j]==backBlock || (blockProperty[m]>0 && blockProperty[blockStore[j]]==0)) { k++; blockStore[j]=m; if (hasShadow[blockStore[j]] && blockStore[j+1]==backBlock) blockStore[j+1]=blockStore[j]+1; } } j=0; for (k=0;k<9;k++) { if (map[updateBase+k]!=blockStore[k]) { blockPos[j]=l; blockQ[j++]=blockStore[k]; } map[updateBase+k]=blockStore[k]; l+=16; } } else { k=l; j=0; for (i=0;i<9;i++) { if (map[updateBase+i]!=backBlock) { blockPos[j]=k; blockQ[j++]=backBlock; } map[updateBase+i]=backBlock; k+=16; } } while (j<10) blockQ[j++]=-1; map[updateBase+9]=1; if (blockQ[8]>=0) { i=blockQ[8]; blockQ[8]=-1; j=blockPos[8]; if (j<2048) // Screen 1 { bg1.drawImage(buildblocks[i],16*(j&15),j&240,this); } else { bg2.drawImage(buildblocks[i],16*(j&15),j&240,this); } } } else if (expA!=expB) // Handle possible explosions { newscore+=10; i=expPos[expA]; if (blockProperty[map[i]]>0) map[i]+=2; k=map[i]; if (i<160) // On screen 1 { bg1.drawImage(buildblocks[k],i&240,((i-1)&15)<<4,this); } else // On screen 2 { bg2.drawImage(buildblocks[k],(i-160)&240,((i-1)&15)<<4,this); } expA=(expA+1)&7; } else if ((scX1&14)==8) { i=random.nextInt(); j=(i>>>4)%9; if (enemies<2 && (i&4)==0 && counter>32 && blockProperty[blockStore[j]]==0) { addObject(levEnemies[level*2+((i>>>8)&1)],176,8+16*j,0); enemies++; } } if (blockQ[updateScan]<0) { updateScan=0; if (counter>520 && (scX1&14)==0) // Switch to attack wave { level++; fixLevelVariables(); } } else { i=blockQ[updateScan]; blockQ[updateScan]=-1; j=blockPos[updateScan++]; if (j<2048) // Screen 1 { bg1.drawImage(buildblocks[i],16*(j&15),j&240,this); } else { bg2.drawImage(buildblocks[i],16*(j&15),j&240,this); } } break; case 4: scroll(2); if (counter<169) { if (scX1>=-144 && scX1<16) // Draw on screen 2 { i=(14-scX1)&240; j=9*(scX1&14); bg2.fillRect(i,j,16,18); } else // Draw on screen 1 { i=(14-scX2)&240; j=9*(scX2&14); bg1.fillRect(i,j,16,18); } if ((scX1&14)==14) { updateBase=((baseX+176)&0xff0)%320; for (i=1;i<10;i++) map[updateBase+i]=5; } } if ((scX1&14)==0 && toKill[wave]==0) // Switch to background { level++; if (level==7) level=1; fixLevelVariables(); } else if ((scX1&31)==8 && counter>40 && enemies+killed50) gameMode=99; break; default: // Just started prepareIntro(); break; } if (gameMode<9) { bf.drawImage(back1,scX1,scY,this); bf.drawImage(back2,scX2,scY,this); } drawObjects(); bg.drawImage(backbuf,0,0,this); if (newscore!=score) drawScore(); repaint(); } } public void scroll(int s) { scX1-=s; scX2-=s; if (scX1<-159) scX1+=320; if (scX2<-159) scX2+=320; baseX=160-scX2; } public void handleObjects() { fBulCount=0;enCount=0;collCount=0; for (i=0;i<10;i++) switch(oType[i]) { case 1: // Demo ship k=random.nextInt(); if ((k&28)==0 && fBullets<2 && gameMode==1) { addObject(2,oX[i]+8,oY[i],0); fBullets++; } if ((k&112)==0 && gameMode==1) oDir[i]=83+3*(k&15); if (oY[i]oDir[i]) { oY[i]-=oExtra[i]; addAnd(i,5); addOr(i,2); } else { addAnd(i,4); addOr(i,1); } break; case 2: // Demo bullet oX[i]+=8; if ((counter&1)==0) addAnd(i,6); else addAnd(i,7); if (oX[i]>160) { oType[i]=0; fBullets--; } break; case 3: // Main ship oPos[i]=(oPos[i]+2)%320; if (fire>0 && fBullets<2) { fire=0; addObject(4,oX[i]+8,oY[i],0); fBullets++; owner.playClick(); } if (oDir[i]==2) { oY[i]+=4; addAnd(i,3); addOr(i,0); } else if (oDir[i]==1) { oY[i]-=4; addAnd(i,5); addOr(i,2); } else { addAnd(i,4); addOr(i,1); } if ((oY[i]&15)==8) { if (wantDir==1 && oY[i]>8) oDir[i]=1; else if (wantDir==2 && oY[i]<136) oDir[i]=2; else oDir[i]=0; wantDir=0; } if (blockProperty[map[(oPos[i]&0xff0)+1+(oY[i]>>4)]]>0) destroyShip(); break; case 4: // Real bullet oX[i]+=8; oPos[i]=(oPos[i]+10)%320; if ((counter&1)==0) addAnd(i,6); else addAnd(i,7); if (oX[i]>159) { oType[i]=0; fBullets--; } else { k=oPos[i]&0xff0; j=k+1+((oY[i]-6)>>4); k+=1+((oY[i]+6)>>4); m=blockProperty[map[j]]; n=blockProperty[map[k]]; if (m==2 || n==2) { oType[i]=5; oExtra[i]=8; owner.playClick(); } else if (m==1) { oType[i]=6; oExtra[i]=10; expPos[expB]=j; expB=(expB+1)&7; owner.playBeep(); } else if (n==1) { oType[i]=6; oExtra[i]=10; expPos[expB]=k; expB=(expB+1)&7; owner.playBeep(); } else fBulNum[fBulCount++]=i; } break; case 5: // Stopped bullet oX[i]-=2; addAnd(i,oExtra[i]); oExtra[i]++; if (oExtra[i]>9) { oType[i]=0; fBullets--; } break; case 6: // Big explosion oX[i]-=2; addAnd(i,oExtra[i]); oExtra[i]++; if (oExtra[i]>13) { oType[i]=0; fBullets--; } break; case 7: // Rotator oX[i]-=2; if ((oPos[i]&15)==8 && (oY[i]&15)==8) { j=(oPos[i]&0xff0)+1+(oY[i]>>4); k=(j+304)%320; if (blockProperty[map[k]]==0) oDir[i]=3; else if (oDir[i]==0 || oDir[i]==3) oDir[i]=1+((counter&8)>>3); if ((oDir[i]==1 && blockProperty[map[j-1]]>0) || (oDir[i]==2 && blockProperty[map[j+1]]>0)) oDir[i]=0; } if (oDir[i]==3) { oX[i]-=2; oPos[i]=(oPos[i]+318)%320; } else if (oDir[i]==1) oY[i]-=2; else if (oDir[i]==2) oY[i]+=2; addOr(i,14+(counter%3)); addAnd(i,17+(counter%3)); standardEnemyStuff(i); break; case 8: // Part of exploding ship oX[i]+=oDir[i]; oY[i]+=oPos[i]; addAnd(i,oExtra[i]); if ((counter&1)==0) oExtra[i]++; if (oExtra[i]>13) oType[i]=9; break; case 9: // Countdown after death oExtra[i]++; if (oExtra[i]>40) gameMode=9; break; case 10: // Tank oX[i]-=2; if ((oY[i]&15)==8) { j=(oPos[i]&0xff0)+1+(oY[i]>>4); if (oDir[i]==0) oDir[i]=1+((counter&8)>>3); if ((oDir[i]==1 && blockProperty[map[j-1]]>0) || (oDir[i]==2 && blockProperty[map[j+1]]>0)) oDir[i]=0; } if (oDir[i]==1) oY[i]-=2; else if (oDir[i]==2) oY[i]+=2; if (eBullets<1 && oY[0]-oY[i]<16 && oY[i]-oY[0]<16) { eBullets++; addObject(11,oX[i]-8,oY[i],1); owner.playClick(); } addOr(i,20); addAnd(i,21); standardEnemyStuff(i); break; case 11: // Enemy bullet oX[i]-=8; oPos[i]=(oPos[i]+314)%320; if ((counter&1)==0) addAnd(i,22); else addAnd(i,23); if (oX[i]<0) { oType[i]=0; eBullets--; } else { if (blockProperty[map[(oPos[i]&0xff0)+1+(oY[i]>>4)]]>0) { oType[i]=12; oExtra[i]=8; owner.playClick(); } else collNum[collCount++]=i; } break; case 12: // Stopped enemy bullet oX[i]-=2; addAnd(i,oExtra[i]); oExtra[i]++; if (oExtra[i]>9) { oType[i]=0; eBullets--; } break; case 13: // Wave ship oX[i]-=2; switch(oExtra[i]) { case 0: oX[i]--; break; case 1: if (oDir[i]==0) oDir[i]=1+((counter&32)>>5); oY[i]+=(oDir[i]<<3)-12; if (oY[i]<8 || oY[i]>136) oDir[i]=3-oDir[i]; break; case 2: if (eBullets<1 && oY[0]-oY[i]<16 && oY[i]-oY[0]<16) { eBullets++; addObject(11,oX[i]-8,oY[i],1); owner.playClick(); } break; case 3: if ((oY[i]&14)==8) { oDir[i]=0; for (j=0;j<2;j++) { k=fBulNum[j]; if (oType[k]==4 && oX[k]>4)]!=backBlock) oY[i]=8+(((random.nextInt()&0xffff)%9)<<4); else oExtra[i]=1; } else { if (oExtra[i]<6) j=34-oExtra[i]; else if (oExtra[i]>12) j=16+oExtra[i]; else j=29; addOr(i,j); addAnd(i,j+6); oExtra[i]++; if (oExtra[i]>18) { oExtra[i]=0; oY[i]=152; } enNum[enCount++]=i; collNum[collCount++]=i; } if (oX[i]<-12) { oType[i]=0; enemies--; } break; case 16: // Seagull oX[i]-=2; if (oDir[i]==0) { oY[i]-=5; addOr(i,51); addAnd(i,53); if (oY[i]<-10) oDir[i]=1; } else { oY[i]+=5; addOr(i,52); addAnd(i,54); if (oY[i]>154) oDir[i]=0; } standardEnemyStuff(i); break; case 17: // Duck if (oExtra[i]==0) { oX[i]-=4; oPos[i]=(oPos[i]+318)%320; j=duckLook[counter&3]; addOr(i,j); addAnd(i,j+6); } else { oX[i]-=6; oPos[i]=(oPos[i]+316)%320; oExtra[i]--; j=duckLook[oExtra[i]+3]; addOr(i,j); j+=6; if (j>50) j=50; addAnd(i,j); } if ((oPos[i]&15)==8 && oExtra[i]==0) { j=(oPos[i]&0xff0)+1+(oY[i]>>4); k=(j+304)%320; if (blockProperty[map[k]]>0 || blockProperty[map[j]]>0) oExtra[i]=8; } standardEnemyStuff(i); break; default: break; } for (i=0;i>4)&7)-4; } owner.playClick(); } public void addAnd(int n, int look) { andX[ands]=oX[n]; andY[ands]=oY[n]; andT[ands++]=look; } public void addOr(int n, int look) { orX[ors]=oX[n]; orY[ors]=oY[n]; orT[ors++]=look; } public void drawObjects() { i=0; while (i137 && y>145 && x<158 && y<159) { stop(); owner.playClick(); owner.clearUp(); setVisible(false); validate(); } requestFocus(); } public void paint(Graphics g) { g.drawImage(background,0,0,this); } public void update(Graphics g) { g.drawImage(background,0,0,this); } } class bloxCanvas extends Canvas implements Runnable, MouseListener, KeyListener { Image logo,pieces[]=new Image[42],background; Graphics bg; Color bright=new Color(123,140,90); java.util.Random random = new java.util.Random(); final String credits="By Karl H\u00f6rnell"; final String toStart="Press any key to start"; final String gameOver="GAME OVER"; final String infoStrings[]={"Control the penguin","with the bottom keys", "Push blocks of ice","by moving against them","Break blocks between", "you and another block","Beware of the","evil flames","Snuff flames with", "blocks of ice","Free all coins to","get to the next level"}; final int blocknum[]={0,24,5,7}; final int offsets[]={0,-12,12,-1,1}, offsX[]={0,0,0,-1,1},offsY[]={0,-1,1,0,0}, pAnim[]={4,4,4,4,1,2,1,3,4,5,4,6,7,8,9,8,10,11,12,11}, flameSteps[]={3,0,2,2,0,3,0,0,3,0,2,2,0,3,0,0}, flameLook[]={35,36,37,38,37,36},blockNums[]={41,20,27,34}; int map[]=new int[132],stack[]=new int[85]; boolean initiated,loaded=false; Thread game; StringBuffer scoreBuf=new StringBuffer(14); long nextTime=System.currentTimeMillis(),nowTime; int toDraw[]=new int[25],numDraw; int toMask[]=new int[60],numMask; int i,j,k,l,m,n,dir,wantDir,lastDir,pNext,counter,dsi; int gameMode,lives,score,newscore,coins,level; int flames,flameMax; int oDir[]=new int[10],oPos[]=new int[10],oX[]=new int[10], oY[]=new int[10],oType[]=new int[10]; Font f; FontMetrics fm; MediaTracker tracker; palmulator owner; public bloxCanvas(palmulator p) { owner=p; } public void init() { if (!loaded) { ImageProducer improd; Image collection; background=createImage(160,304); bg=background.getGraphics(); tracker = new MediaTracker(this); collection = owner.getImage(owner.getDocumentBase(),"bloxdata.gif"); tracker.addImage (collection, 0); try{ tracker.waitForID(0); } catch (InterruptedException e){} improd=collection.getSource(); for (i=0;i<42;i++) { pieces[i]=createImage(new FilteredImageSource(improd, new CropImageFilter(16*(i/6),36+16*(i%6),16,16))); tracker.addImage(pieces[i],1); } logo=createImage(new FilteredImageSource(improd, new CropImageFilter(0,0,128,36))); tracker.addImage(logo,1); try{ tracker.waitForID(1); } catch (InterruptedException e){} f=owner.f; fm=owner.fm; bg.setFont(f); addMouseListener(this); addKeyListener(this); scoreBuf.append("SCORE: "); loaded=true; } bg.setColor(bright); bg.fillRect(0,0,160,160); initiated=false; gameMode=0; game=new Thread(this); game.start(); } public void prepareIntro() { if (!initiated) { initiated=true; bg.setColor(bright); bg.fillRect(0,144,160,16); bg.setColor(Color.black); bg.fillRect(0,0,160,144); bg.drawRoundRect(137,145,21,14,6,6); bg.drawString("Exit",141,156); requestFocus(); } bg.setColor(Color.black); bg.fillRect(0,0,160,144); bg.drawImage(logo,16,4,this); bg.setColor(bright); j=fm.stringWidth(credits); bg.drawString(credits,80-j/2,51); j=fm.stringWidth(toStart); bg.drawString(toStart,80-j/2,140); for (i=0;i<3;i++) bg.drawImage(pieces[0],15*i,144,this); gameMode=0; setupInstructions(); } public void setupInstructions() { gameMode++; if (gameMode>2) gameMode=1; counter=0; bg.setColor(Color.black); bg.fillRect(0,57,160,72); j=gameMode*6-6; bg.setColor(bright); for (i=0;i<3;i++) { bg.drawString(infoStrings[j++],5,66+i*24); bg.drawString(infoStrings[j++],5,75+i*24); } if (gameMode==1) { bg.drawImage(pieces[10],140,59,this); bg.drawImage(pieces[20],140,83,this); bg.drawImage(pieces[10],110,83,this); bg.drawImage(pieces[10],108,107,this); bg.drawImage(pieces[20],140,107,this); bg.drawImage(pieces[22],124,107,this); bg.drawLine(130,89,139,89); bg.drawLine(128,92,139,92); } else { bg.drawImage(pieces[35],140,59,this); bg.drawImage(pieces[35],140,83,this); bg.drawImage(pieces[20],130,83,this); bg.drawImage(pieces[10],100,83,this); bg.drawLine(120,89,129,89); bg.drawLine(118,92,129,92); bg.drawImage(pieces[30],140,107,this); bg.drawImage(pieces[10],124,107,this); } } public void prepareGame() { lives=3; newscore=0; drawScore(); level=1; for (i=0;i<3;i++) bg.drawImage(pieces[0],i*15,144,this); prepareLevel(); } public void drawScore() { scoreBuf.setLength(7); scoreBuf.append(newscore); bg.setColor(bright); bg.fillRect(78,145,40,14); bg.setColor(Color.black); bg.drawString(scoreBuf.toString(),49,156); score=newscore; } public void prepareLevel() { m=0; while (m<5) { // Randomly place blocks for (i=0;i<11;i++) for (j=0;j<12;j++) { k=i*12+j; if (i>0 && i<10 && j>0 && j<11) map[k]=0; else map[k]=3; } map[13]=3; map[131]=0; for (j=1;j<4;j++) for (i=0;i>>2)%108); if (map[k]!=0) k=0; else { map[k]=j; k=131; } } } // Check whether all coins are reachable -- otherwise the level // cannot be solved and needs to be rebuilt map[13]=8; stack[0]=13; i=0;j=1;m=0; while (i100) setupInstructions(); break; case 10: prepareGame(); break; case 11: // Zooming in if (counter>17) gameMode=12; else bg.copyArea(68-4*counter,160+68-4*counter, 24+8*counter,8+8*counter, 0,-160); break; case 12: // Game if (flames>>2)%9; if (oX[0]<96 && map[k*12+22]==0) { addObject(5,160,16*k,k*12+23,3); flames++; } else if (oX[0]>95 && map[k*12+13]==0) { addObject(5,-16,16*k,k*12+12,4); flames++; } } numDraw=0; numMask=0; for (i=0;i<10;i++) switch(oType[i]) { case -1: // Penguin if ((oX[i]&15)==0 && (oY[i]&15)==0) oDir[i]=0; if (pNext>0 && oDir[i]==0) { oType[i]=pNext; if (pNext==7) owner.playBeep(); for (j=1;j<10;j++) if (oType[j]==5) oType[j]=0; flameMax=0; lastDir=oDir[0]; oDir[0]=0; counter=0; wantDir=0; } if (oDir[i]==0 && wantDir>0) { lastDir=wantDir; if (map[oPos[i]+offsets[wantDir]]==0) { oDir[i]=wantDir; oPos[i]+=offsets[wantDir]; } else if (map[oPos[i]+offsets[wantDir]]<3) { if (map[oPos[i]+2*offsets[wantDir]]>0) // Crush { addObject(map[oPos[i]+offsets[wantDir]], oX[i]+16*offsX[wantDir],oY[i]+16*offsY[wantDir], oPos[i]+offsets[wantDir],13+7*map[oPos[i]+offsets[wantDir]]); map[oPos[i]+offsets[wantDir]]=4; bg.drawImage(pieces[41],oX[i]+16*offsX[wantDir], oY[i]+160+16*offsY[wantDir],this); owner.playClick(); } else // Push { addObject(2+map[oPos[i]+offsets[wantDir]], oX[i]+16*offsX[wantDir],oY[i]+16*offsY[wantDir], oPos[i]+offsets[wantDir],wantDir); map[oPos[i]+offsets[wantDir]]=0; bg.drawImage(pieces[41],oX[i]+16*offsX[wantDir], oY[i]+160+16*offsY[wantDir],this); owner.playClick(); } } } if (oDir[i]>0) toDraw[numDraw++]=pAnim[oDir[i]*4+(counter&3)]; else toDraw[numDraw++]=pAnim[lastDir*4]; toDraw[numDraw++]=oX[i]; toDraw[numDraw++]=oY[i]; oX[i]+=4*offsX[oDir[i]]; oY[i]+=4*offsY[oDir[i]]; break; case 1: // Cracking ice case 2: // Cracking coin toDraw[numDraw++]=++oDir[i]; toDraw[numDraw++]=oX[i]; toDraw[numDraw++]=oY[i]; if (oDir[i]==26) { map[oPos[i]]=0; oType[i]=0; newscore+=5; } else if (oDir[i]==33) { map[oPos[i]]=0; oType[i]=0; coins++; newscore+=25; owner.playBeep(); } break; case 3: // Sliding ice case 4: // Sliding coin oX[i]+=offsX[oDir[i]]*8; oY[i]+=offsY[oDir[i]]*8; if ((oX[i]&15)==0 && (oY[i]&15)==0) oPos[i]+=offsets[oDir[i]]; toDraw[numDraw++]=oType[i]*7-1; toDraw[numDraw++]=oX[i]; toDraw[numDraw++]=oY[i]; if (map[oPos[i]+offsets[oDir[i]]]>0) { map[oPos[i]]=oType[i]-2; bg.drawImage(pieces[blockNums[oType[i]-2]], oX[i],oY[i]+160,this); oType[i]=0; } break; case 5: // Flame oX[i]+=offsX[oDir[i]]*flameSteps[oX[i]&15]; oY[i]+=offsY[oDir[i]]*flameSteps[oY[i]&15]; if ((oX[i]&15)==0 && (oY[i]&15)==0) { oPos[i]+=offsets[oDir[i]]; if (oDir[i]==0 || (counter&14)==0) oDir[i]=1+((random.nextInt()>>>2)&3); if (oX[i]oX[0]-10) { if (oY[0]>oY[i]) oDir[i]=2; else oDir[i]=1; } else if (oY[i]oY[0]-10) { if (oX[0]>oX[i]) oDir[i]=4; else oDir[i]=3; } if (map[oPos[i]+offsets[oDir[i]]]>0) oDir[i]=0; } if (oY[i]oY[0]-8 && oX[i]oX[0]-8) pNext=7; toMask[numMask++]=flameLook[counter%6]; toMask[numMask++]=oX[i]; toMask[numMask++]=oY[i]; for (j=1;j<10;j++) if (oType[j]==3 || oType[j]==4) if (oX[j]45) { gameMode=13; newscore+=500; level++; counter=-1; } break; case 7: // Dying penguin if (counter<18) j=14+counter/3; else j=19; if (counter>40) { lives--; if (lives<0) { gameMode=13; counter=-1; } else prepareLife(); } else { toDraw[numDraw++]=j; toDraw[numDraw++]=oX[i]; toDraw[numDraw++]=oY[i]; } break; case 8: // Bonus points toMask[numMask++]=39+(counter&2)/2; toMask[numMask++]=oX[i]; toMask[numMask++]=oY[i]; oDir[i]++; if (oDir[i]>35) { oType[i]=0; flames--; } break; default: break; } if (coins==5) pNext=6; bg.copyArea(0,160,160,144,0,-160); i=0; while (iscore) drawScore(); break; case 13: // Blacking out, either at end of level or after last life bg.setColor(Color.black); if (counter<18) bg.fillRect(68-4*counter,68-4*counter,24+8*counter, 8+8*counter); else if (counter==18) { bg.setColor(bright); if (lives<0) bg.drawString(gameOver,80-fm.stringWidth(gameOver)/2,73); else prepareLevel(); } else if (counter>80) prepareIntro(); break; default: // Just started prepareIntro(); break; } repaint(); } } public void start() { if (game==null) { game=new Thread(this); game.start(); } } public void stop() { if ((game!=null)&&(game.isAlive())) { game.stop(); } game=null; } public void addObject(int t, int x, int y, int p, int d) { dsi=0; while (oType[dsi]!=0) dsi++; oType[dsi]=t; oX[dsi]=x; oY[dsi]=y; oPos[dsi]=p; oDir[dsi]=d; } public void keyTyped(KeyEvent ke) { } public void keyReleased(KeyEvent ke) { wantDir=0; } public void keyPressed(KeyEvent ke) { // Set the variable "wantDir" according to the pressed key // It will be read by the main game loop switch(ke.getKeyCode()) { case KeyEvent.VK_LEFT: wantDir=3; break; case KeyEvent.VK_RIGHT: wantDir=4; break; case KeyEvent.VK_UP: wantDir=1; break; case KeyEvent.VK_DOWN: wantDir=2; break; default: break; } if (gameMode<10) gameMode=10; } public void mouseDragged(MouseEvent me){} public void mouseMoved(MouseEvent me){} public void mouseEntered(MouseEvent me){} public void mouseExited(MouseEvent me){} public void mouseReleased(MouseEvent me){} public void mouseClicked(MouseEvent me){} public void mousePressed(MouseEvent me) { int x=me.getX(); int y=me.getY(); if (x>137 && y>145 && x<158 && y<159) { stop(); owner.playClick(); owner.clearUp(); setVisible(false); validate(); } requestFocus(); } public void paint(Graphics g) { g.drawImage(background,0,0,this); } public void update(Graphics g) { g.drawImage(background,0,0,this); } }