// Warp MIDlet using the com.nokia.mid libraries // One-level demo version import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import com.nokia.mid.ui.*; import com.nokia.mid.sound.*; import javax.microedition.rms.*; import java.io.*; public class warpdemo extends MIDlet { private final warpCanvas canvas; public warpdemo() { canvas=new warpCanvas(this); } public void startApp() { Display.getDisplay(this).setCurrent(canvas); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } void exitRequested() { destroyApp(false); notifyDestroyed(); } } class warpCanvas extends FullCanvas implements Runnable { private int gameMode=1,counter,introTile; private final warpdemo owner; private Image background,map1,map2; private DirectGraphics bdg,mdg1,mdg2; private Graphics bg,mg1,mg2; Thread runner; private boolean active=true; private java.util.Random rnd=new java.util.Random(); private byte statics[],mobiles[],masks[],chardata[],charmask[]; private byte textbuf[]=new byte[196],maskbuf[]=new byte[196]; private final int charbase[]={80, 0,0,0,0,0,0,0,0,0,0,0,0,0,230,0, 0,8,16,24,32,40,48,56,64,72, 0,0,0,0,0,0,0, 83,89,95,100,106,111,116,122,128,131,137,143,148,155,161,167,173,179,185,191,196,202, 207,214,219,224}; private final int charwidth[]={3, 0,0,0,0,0,0,0,0,0,0,0, 0,0,4,0, 8,8,8,8,8,8,8,8,8,8, 0,0,0,0,0,0,0, 6,6,5,6,5,5,6,6,3,6,6,5,7,6,6,6,6,6,6,5,6,5,7,5,5,6}; private final int mobAdjX[]={7,6,9,7,7, 4,5,7,8,4,6, 7,7,7, 7,8,7,2,2, 8,8, 8,8,7,7,7,7,7,7,7, 8,8, 7,7,7,7,7,7,7,7, 8,8}; private final int mobH[]={15,16,16,6,6, 8,11,14,16,5,5, 14,14,14,15,15,15,6,6, 16,16, 15,15,6,8,9,11,12,13,14, 16,16, 17,17,15,14,15,13,14,15, 16,16}; private final int dX[]={0,0,0,-2,2},dY[]={0,-2,2,0,0},cyclic[]={0,1,2,1}; private final int enemyLook[]={15,12,19,20, 21,23,30,31, 32,34,40,41}, enemyScore[]={15,25,10,15, 15,30,15,20, 25,20,20,25}; private int mobPix[]=new int[mobH.length],mobAdjY[]=new int[mobH.length]; private final int blockpointer[]={0,2880,3888,2736}; private int qualities[]=new int[7],looks[]=new int[7],wrecked[]=new int[7]; private int shadows[][]=new int[7][7]; private int distr[]=new int[32]; private final int levelData[]={4, 1,4,7,8, 21,6,3,2, 0,0,3,1, 9, 2,5,7,8, 3,6,7,8 }; private warpObject objs[]=new warpObject[12]; private char levelChars[]={'E','N','T','E','R','I','N','G',' ','L','E','V','E','L',' ','0'}; private byte scorehold[]=new byte[40],scoremask[]=new byte[40],lifehold[]=new byte[16], lifemask[]=new byte[16]; private int lifeW; private int highscores[]=new int[7],highpos,highx; private boolean acceptKey; private int updateY,updatePos,mapY1,mapY2,tileMap[]=new int[10*12],funcMap[]=new int[10*12]; private char highchars[]=new char[77]; private int bullets,flyCount,step,startOver; private int wave,killed,created; private int score,level,levPos; private int lastKey=0,motionKeys[]={0,KEY_NUM2,KEY_NUM8,KEY_NUM4,KEY_NUM6}; private RecordStore rs; private Sound beep1,beep2,beep3,beep4,beep5; public warpCanvas(warpdemo o) { int i,j,k; owner=o; background=Image.createImage(96,65); bg=background.getGraphics(); bdg=DirectUtils.getDirectGraphics(bg); map1=Image.createImage(96,72); map2=Image.createImage(96,72); mg1=map1.getGraphics(); mg2=map2.getGraphics(); mdg1=DirectUtils.getDirectGraphics(mg1); mdg2=DirectUtils.getDirectGraphics(mg2); // Get bitmap data statics=getBitmap("statics.bit"); mobiles=getBitmap("mobiles.bit"); masks=getBitmap("masks.bit"); chardata=getBitmap("chardata.bit"); charmask=getBitmap("charmask.bit"); rnd.setSeed(System.currentTimeMillis()); loadHighscores(); j=4320; for (i=0;i0) i++; objs[i].x=ox; objs[i].y=oy; objs[i].pos=op; objs[i].dir=od; objs[i].type=ot; objs[i].look=ol; objs[i].var=va; } void prepareIntro() { int i,j,k; introTile=424+144*(rnd.nextInt()&3); for (j=0;j<6;j++) for (k=0;k<8;k++) mdg1.drawPixels(statics,null,introTile,12,k*12,j*12,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); lastKey=0; drawHighscores(mg2,mdg2); gameMode=2; } void prepareGame() { level=0; lifeW=16; clearScore(); mapY2=0;mapY1=-72; objs[0].type=3; mg1.setColor(0); mg1.fillRect(0,0,96,72); for (int i=0;i<120;i++) { tileMap[i]=0; funcMap[i]=0; } updateY=48; updatePos=40; bullets=0; levPos=0; for (int i=1;i<9;i++) { funcMap[updatePos+i]=0; tileMap[updatePos+i]=1000; } prepareNewLevel(); gameMode=4; } void prepareNewLevel() { int i,j,k,n; level++; n=levelData[levPos++]; for (i=0;i0) // Wreckable? wrecked[i]=1000+144*levelData[levPos++]; if ((qualities[i]&1)>0) // Protruding, possible shadow { for (j=1;j<=n;j++) shadows[i][j]=levelData[levPos++]; } else // No shadow { for (j=1;j<=n;j++) shadows[i][j]=looks[j]; } } levelChars[15]=(char)(48+level); drawString(new String(levelChars),0,65,bdg); wave=0; killed=0; created=0; flyCount=0; } void clearScore() { score=0; int i,j=32,k; for (i=0;i<5;i++) { for (k=0;k<8;k++) { scoremask[j]=charmask[k]; scorehold[j++]=chardata[k]; } j-=16; } } void buildScore() { int i,j,k,l,s; s=score; j=32; while (s>0) { k=(s%10)<<3; for (l=0;l<8;l++) { scoremask[j]=charmask[k]; scorehold[j++]=chardata[k++]; } j-=16; s=s/10; } } public void run() { int i,j,k; long startTime,timeTaken; try{ while (active) { startTime=System.currentTimeMillis(); counter++; switch(gameMode) { case 1: // Prepare intro for (i=0;i<12;i++) objs[i].type=0; initiateObject(48,50,0,0,1,0,48); counter=0; prepareIntro(); break; case 2: // During intro, scrolling background bg.drawImage(map1,0,2*(counter%12),Graphics.LEFT | Graphics.TOP); bdg.drawPixels(mobiles,masks,0,96,0,0,96,45,0,DirectGraphics.TYPE_BYTE_1_GRAY); bdg.drawPixels(statics,null,0,24,0,58,24,7,0,DirectGraphics.TYPE_BYTE_1_GRAY); bdg.drawPixels(statics,null,168,16,80,58,16,7,0,DirectGraphics.TYPE_BYTE_1_GRAY); for (i=0;i<3;i++) { processObject(objs[i]); drawObject(objs[i]); } if ((counter&255)==160) { gameMode=3; introTile=424+144*(rnd.nextInt()&3); } if (lastKey==KEY_SOFTKEY1) { mg2.drawImage(map1,0,2*(counter%12),Graphics.LEFT | Graphics.TOP); mdg2.drawPixels(mobiles,masks,0,96,0,0,96,45,0,DirectGraphics.TYPE_BYTE_1_GRAY); prepareGame(); } break; case 3: // Intro, showing highscores bg.drawImage(map2,0,0,Graphics.LEFT | Graphics.TOP); bdg.drawPixels(statics,null,0,24,0,58,24,7,0,DirectGraphics.TYPE_BYTE_1_GRAY); bdg.drawPixels(statics,null,168,16,80,58,16,7,0,DirectGraphics.TYPE_BYTE_1_GRAY); for (i=0;i<3;i++) { processObject(objs[i]); drawObject(objs[i]); } // Gradually redraw tile pattern mdg1.drawPixels(statics,null,introTile,12,12*(counter&7), 12*((counter>>3)%6),12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); if ((counter&255)==255) gameMode=2; if (lastKey==KEY_SOFTKEY1) { prepareGame(); } break; case 4: mapY1+=2; mapY2+=2; if (mapY1>65) mapY1-=144; if (mapY2>65) mapY2-=144; step=(mapY1+120)%12; flyCount++; if (step==0) { updateY-=12; updatePos-=10; if (updatePos<0) { updatePos+=120; updateY+=144; } if (flyCount>45 && flyCount<380) { i=1; for (j=8;j>0;j--) { k=distr[rnd.nextInt()&31]; funcMap[updatePos+j]=k; tileMap[updatePos+j]=1000+144*looks[k]; tileMap[updatePos+j+1]=1000+144*shadows[k][i]; i=k; } } else if (flyCount<25 || flyCount>400) for (i=1;i<9;i++) { funcMap[updatePos+i]=0; tileMap[updatePos+i]=1000; } else for (i=1;i<9;i++) { funcMap[updatePos+i]=0; tileMap[updatePos+i]=1000+144*looks[1]; } } else if (step<10) { j=updatePos+step-1; i=12*(step-2); if (updateY<72) { mdg1.drawPixels(statics,null,tileMap[j],12,i, updateY,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); mdg1.drawPixels(statics,null,tileMap[j+1],12,i+12, updateY,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); } else { mdg2.drawPixels(statics,null,tileMap[j],12,i, updateY-72,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); mdg2.drawPixels(statics,null,tileMap[j+1],12,i+12, updateY-72,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); } } else // Possibly distribute enemies { i=rnd.nextInt()&0xffffff; if (flyCount>45 && flyCount<380) { if ((i&1)==0) { j=3*(i&28)+6; k=updatePos+((i&28)>>2)+1; i=4*(level-1)+((i&32)>>5); if (qualities[funcMap[k]]==0) { initiateObject(j,-10,k,0,10+i,enemyLook[i],0); } } } else if (flyCount>420 && wave<2 && created<5) { if ((counter&4)==0 && objs[0].type>0) { created++; initiateObject(6+3*((counter&56)>>1),-10,0,0,level*4+wave+8, enemyLook[level*4+wave-2],0); } } } bg.drawImage(map1,0,mapY1,Graphics.LEFT | Graphics.TOP); bg.drawImage(map2,0,mapY2,Graphics.LEFT | Graphics.TOP); if (flyCount>20 && flyCount<45) bdg.drawPixels(textbuf,maskbuf,0,80,8,28,80,8,0,DirectGraphics.TYPE_BYTE_1_GRAY_VERTICAL); for (i=0;i<12;i++) { processObject(objs[i]); } for (i=1;i<12;i++) if (objs[i].type>8) { j=mobAdjX[objs[0].look]+mobAdjX[objs[i].look]-3; k=(mobH[objs[0].look]+mobH[objs[i].look])/2-3; if (objs[i].xobjs[0].x-j && objs[i].yobjs[0].y-k) { crashShip(); i=12; } } for (i=0;i<12;i++) { drawObject(objs[i]); } bdg.drawPixels(scorehold,scoremask,0,40,0,0,40,8,0, DirectGraphics.TYPE_BYTE_1_GRAY_VERTICAL); bdg.drawPixels(lifehold,lifemask,0,lifeW,80,0,lifeW,8,0, DirectGraphics.TYPE_BYTE_1_GRAY_VERTICAL); break; case 5: // Game Over pause if (counter>40) { if (score>highscores[5]) { highscores[6]=score; i=6; while (i>0 && score>highscores[i-1]) { highscores[i]=highscores[i-1]; for (j=0;j<11;j++) highchars[i*11+j]=highchars[i*11+j-11]; i--; highscores[i]=score; } highchars[i*11+8]='.'; highchars[i*11+9]='.'; highchars[i*11+10]='.'; for (j=4;j>=0;j--) { highchars[i*11+j]=(char)(48+(score%10)); score=score/10; } drawHighscores(bg,bdg); bdg.drawPixels(statics,null,280,20,0,58,20,7,0,DirectGraphics.TYPE_BYTE_1_GRAY); bdg.drawPixels(mobiles,null,mobPix[0],16,0,6+i*8,16,15,0,DirectGraphics.TYPE_BYTE_1_GRAY); highpos=i; highx=8; gameMode=6; } else gameMode=1; } break; case 6: // Entering name for highscore list if (lastKey==0) acceptKey=true; else { switch(lastKey) { case KEY_NUM2: // Up highchars[highpos*11+highx]++; if (highchars[highpos*11+highx]>'Z') highchars[highpos*11+highx]='.'; else if (highchars[highpos*11+highx]<'A') highchars[highpos*11+highx]='A'; break; case KEY_NUM8: // Down highchars[highpos*11+highx]--; if (highchars[highpos*11+highx]<'.') highchars[highpos*11+highx]='Z'; else if (highchars[highpos*11+highx]<'A') highchars[highpos*11+highx]='.'; break; case KEY_NUM4: // Left if (highx>8 && acceptKey) { highx--; acceptKey=false; } break; case KEY_NUM6: // Right if (highx<10 && acceptKey) { highx++; acceptKey=false; } break; default: break; } if (lastKey==KEY_SOFTKEY1) // Enter { storeHighscores(); gameMode=1; } else { bg.setColor(0xffffff); bg.fillRect(52,10+highpos*8,35,7); drawString(new String(highchars,highpos*11,11),16,10+highpos*8,bdg); } } break; default: break; } repaint(0,0,96,65); serviceRepaints(); timeTaken=System.currentTimeMillis()-startTime; if (timeTaken<70) runner.sleep(70-timeTaken); } } catch(InterruptedException ie){} } void drawObject(warpObject o) { if (o.type>0) bdg.drawPixels(mobiles,masks,mobPix[o.look],16,o.x-mobAdjX[o.look], o.y-mobAdjY[o.look],16,mobH[o.look],0,DirectGraphics.TYPE_BYTE_1_GRAY); } void crashShip() { int i; bullets=0; for (i=1;i<12;i++) objs[i].type=0; for (i=1;i<6;i++) initiateObject(objs[0].x,objs[0].y,1+(rnd.nextInt()&3),(rnd.nextInt()&7)-3,8,4,0); objs[0].type=0; if (flyCount>400) startOver=flyCount; else startOver=0; if (flyCount<380) flyCount=380; beep4.play(1); } void processObject(warpObject o) { int i,op; switch(o.type) { case 1: // Dummy ship i=rnd.nextInt(); if ((i&15)==0) { o.var=16+4*((i>>4)&15); } if (o.xo.var) { o.x-=4; o.look=1; } else { o.look=0; } if ((i&3584)==0 && (objs[1].type==0 || objs[2].type==0)) { initiateObject(o.x,o.y-5,0,0,2,0,0); } break; case 2: // Dummy bullet if (o.y>-10) o.y-=6; else o.type=0; o.look=3+(counter&1); break; case 3: // Adjusting ship if ((o.x%12)!=6) { if (o.x<42) o.x+=2; else if (o.x>42) o.x-=2; } if (o.y<57) o.y++; else { o.type=4; o.var=o.x; } break; case 4: // Normal ship if (o.var==o.x && lastKey==KEY_NUM4 && o.x>6) o.var-=12; else if (o.var==o.x && lastKey==KEY_NUM6 && o.x<90) o.var+=12; if (o.xo.var) { o.x-=4; o.look=1; } else o.look=0; i=o.y+24-step; o.pos=(o.x/12+10*(i/12)+1+updatePos)%120; if (lastKey==KEY_NUM2) { if (bullets<2 && acceptKey) { initiateObject(o.x,o.y-5,0,0,5,0,0); bullets++; acceptKey=false; beep5.play(1); } } else acceptKey=true; if (qualities[funcMap[o.pos]]>0) // Crash crashShip(); break; case 5: // Normal bullet if (o.y>0) { o.y-=6; o.look=3+(counter&1); i=(o.y+24-step)/12; op=(o.x/12+10*i+1+updatePos)%120; if (qualities[funcMap[op]]>0) { o.type=6; if (qualities[funcMap[op]]>1) { o.look=5; i=i*12+updateY; if (i>143) i-=144; if (i<72) { mdg1.drawPixels(statics,null,wrecked[funcMap[op]],12, 12*(o.x/12),i,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); } else { mdg2.drawPixels(statics,null,wrecked[funcMap[op]],12, 12*(o.x/12),i-72,12,12,0,DirectGraphics.TYPE_BYTE_1_GRAY); } tileMap[op]=wrecked[funcMap[op]]; funcMap[op]=0; score+=5; buildScore(); beep2.play(1); } else { o.look=9; beep1.play(1); } } else for (i=1;i<12;i++) if (objs[i].type>9 && objs[i].xo.x-11 && objs[i].yo.y-9) { o.type=6; o.look=5; o.x=objs[i].x; o.y=objs[i].y; score+=enemyScore[objs[i].type-10]; buildScore(); beep3.play(1); objs[i].type=0; i=12; if (flyCount>420) { killed++; if (killed==5) { wave++; killed=0; created=0; if (wave==2) // All done. Go to next level { if (level==1) // Go back to beginning { level=0; levPos=0; } prepareNewLevel(); } } } } } else { o.type=0; bullets--; } break; case 6: // Stopped or exploding bullet case 7: o.y+=2; o.look++; if (o.look==11 || o.look==9) { if (o.type==6) bullets--; o.type=0; } break; case 8: // Exploding ship o.x+=o.dir; o.y-=o.pos; if (o.look<8) o.look++; else { o.var++; if (o.var==6) { for (i=1;i<6;i++) { objs[i].var=8; objs[i].x=-20; objs[i].dir=0; } created=10; flyCount=500; } else if (o.var==50) { for (i=1;i<6;i++) { objs[i].type=0; } if (lifeW>1) { if (lifeW==16) lifeW=9; else lifeW=1; created=0; wave=0; killed=0; flyCount=startOver; objs[0].type=4; } else { counter=0; drawString("GAME OVER",23,28,bdg); gameMode=5; } } } break; case 9: // Enemy bullet o.y+=5; if (o.y>75) o.type=0; else { o.look=17+(counter&1); i=(o.y+24-step)/12; op=(o.x/12+10*i+1+updatePos)%120; if (qualities[funcMap[op]]>0) { o.type=7; o.look=9; beep1.play(1); } } break; case 10: // Orb o.y+=2; o.x+=dX[o.dir]; o.y+=dY[o.dir]; if (o.dir>0) { o.var--; if (o.var<=0) { if (o.dir==3 && o.x>6 && qualities[funcMap[o.pos-1]]==0) { o.var=6; o.pos--; } else if (o.dir==4 && o.x<90 && qualities[funcMap[o.pos+1]]==0) { o.var=6; o.pos++; } else o.dir=0; } } o.look++; if (o.look>16) o.look=14; if (o.y>75) o.type=0; else { if (o.dir==0) { if (qualities[funcMap[(o.pos+10)%120]]==0) { o.dir=2; o.var=6; o.pos=(o.pos+10)%120; } else if (o.x<90 && qualities[funcMap[o.pos+1]]==0) { o.dir=4; o.var=6; o.pos++; } else if (o.x>6 && qualities[funcMap[o.pos-1]]==0) { o.dir=3; o.var=6; o.pos--; } } } break; case 11: // Tank o.y+=2; o.x+=dX[o.dir]; if (o.dir>0) { o.var--; if (o.var<=0) { if (o.dir==3 && o.x>6 && qualities[funcMap[o.pos-1]]==0) { o.var=6; o.pos--; } else if (o.dir==4 && o.x<90 && qualities[funcMap[o.pos+1]]==0) { o.var=6; o.pos++; } else o.dir=0; } } o.look++; if (o.look>13) o.look=11; if (o.y>75) o.type=0; else { if (o.dir==0) { if (o.x<90 && qualities[funcMap[o.pos+1]]==0) { o.dir=4; o.var=6; o.pos++; } else if (o.x>6 && qualities[funcMap[o.pos-1]]==0) { o.dir=3; o.var=6; o.pos--; } } if (o.xobjs[0].x-20 && (counter&15)==(o.y&15)) // Fire! { initiateObject(o.x,o.y+7,0,0,9,17,0); beep5.play(1); } } break; case 12: // Spaceships case 13: case 16: case 17: case 20: case 21: o.y+=3; if (o.type==16 || o.type==17) o.y++; if (o.type==13 || o.type==17 || o.type==21) { if (o.dir==0) if (o.x<90) o.x+=3; else o.dir=1; else if (o.x>6) o.x-=3; else o.dir=0; } if (o.type>19 && o.xobjs[0].x-20 && (counter&15)==(o.y&15)) // Fire! { initiateObject(o.x,o.y+8,0,0,9,17,0); // Fire beep5.play(1); } if (o.y>75) o.y=-15; break; case 14: // Dragonfly o.y+=4; o.look=21+(counter&1); if (o.y>75) o.type=0; break; case 15: // Frog o.y+=2; if (o.var==0) // Up { o.look++; if (o.look==30) { o.look=29; o.var=1; } } else if (o.var==1) // Down { o.look--; if (o.look==22) { o.look=23; o.var=2; o.x=-20; } } else { i=rnd.nextInt()&7; op=10*(o.pos/10)+1+i; if (funcMap[op]==1) { o.pos=op; o.x=6+12*i; o.var=0; } } if (o.y>75) o.type=0; break; case 18: // Seagull o.y+=2; if (o.var==0) { o.x+=5; o.look=32; if (o.x>103) o.var=0; } else { o.x-=5; o.look=33; if (o.x<-7) o.var=1; } if (o.y>75) o.type=0; break; case 19: // Duck o.y+=4; if (o.y>75) o.type=0; else { if (o.var==0) // Walking { o.look=34+cyclic[counter&3]; i=(o.y+32-step)/12; op=(o.x/12+10*i+1+updatePos)%120; if (qualities[funcMap[op]]>0) { o.var=1; o.look=37; } } else if (o.var==1) // Up { o.look++; o.y++; if (o.look==40) { o.look=39; o.var=2; } } else // Down { o.look--; o.y++; if (o.look==36) o.var=0; } } break; default: break; } } void drawHighscores(Graphics g, DirectGraphics dg) { g.setColor(0xffffff); g.fillRect(0,0,96,65); drawString("HIGHSCORES",20,1,dg); for (int j=0;j<6;j++) drawString(new String(highchars,j*11,11),16,10+j*8,dg); } void loadHighscores() { int i,j; // Obtain highscores // Attempt to fetch by way of record stores try{ rs=RecordStore.openRecordStore("warpHigh",true); RecordEnumeration re=rs.enumerateRecords(null,null,false); if (re.hasNextElement()) { byte tempBytes[]=re.nextRecord(); for (i=0;i<66;i++) highchars[i]=(char)tempBytes[i]; for (i=0;i<6;i++) { highscores[i]=0; for (j=0;j<5;j++) highscores[i]=highscores[i]*10+(highchars[i*11+j]-'0'); } } rs.closeRecordStore(); }catch(Exception e){} if (highchars[0]==0) { for (i=0;i<6;i++) { for (j=0;j<5;j++) highchars[i*11+j]='0'; for (j=5;j<8;j++) highchars[i*11+j]=' '; for (j=8;j<11;j++) highchars[i*11+j]='.'; } } } void storeHighscores() { try{ byte tempBytes[]=new byte[88]; for (int i=0;i<66;i++) tempBytes[i]=(byte)highchars[i]; rs=RecordStore.openRecordStore("warpHigh",true); if (rs.getNumRecords()>0) rs.deleteRecord(rs.getNextRecordID()-1); rs.addRecord(tempBytes,0,66); rs.closeRecordStore(); }catch(Exception e){} } public void paint(Graphics g) { g.drawImage(background,0,0,Graphics.LEFT | Graphics.TOP); } public void keyPressed(int k) { if (k==KEY_SOFTKEY2) { active=false; owner.exitRequested(); } else if (k==KEY_UP_ARROW) lastKey=KEY_NUM2; else if (k==KEY_DOWN_ARROW) lastKey=KEY_NUM8; else lastKey=k; } public void keyReleased(int k) { lastKey=0; } } class warpObject { int x,y,pos,dir,look,temp; int type,var; }