GAMES TWO: LESSON THREE: Enemy Movement

The version of the game of TMAN from the last lesson isn't very challenging since the enemies don't even move. In this lesson we will concentrate on providing the enemies (the X's) with the ability to navigate through the maze. We could provide them with the ability to track down TMAN, but we won't get into that in this lesson. Rather, the enemies will more or less wonder aimlessly around the maze which still doesn't make a very challenging game, BUT it at least makes it more interesting than is the case with them just sitting in one place!

Play this game for a while and analyze the movement of the enemies. Are there certain places in the maze that the enemies cannot get to? Also is the pace of the enemy movement reasonable or is it too fast or too slow?

The run() method used in the applet is shown below. Keep in mind that this applet implements the Runnable interface.

public void run(){ while(true){ if(lives>0){ moveEnemies(); repaint(); } try{ Thread.sleep(200); }catch(InterruptedException e){}; } }
Note that a method called moveEnemies() is called from within the run() method. From within the moveEnemies() method another method called unblocked() is called. Inspect the code shown below and make sure you understand how these methods work together to control enemy movement.

import java.awt.*; import java.applet.*; import java.awt.event.*; import java.util.*; public class TMAN5 extends Applet implements Runnable{ Dimension d; Thread tm; Random r = new Random(); //wall=0, dot=1, hall=2, tee=3, x=4, torn=5 int[][] map = { { 0,0,0,0,0,0,0,0,0,0,0,0}, { 0,1,1,3,1,1,1,1,1,1,1,0}, { 0,1,0,0,0,1,0,0,0,1,0,0}, { 0,1,0,0,0,1,0,0,0,4,0,0}, { 0,1,0,0,0,1,1,1,1,1,1,0}, { 1,1,1,0,0,0,0,0,0,0,1,1}, { 0,0,1,1,1,5,0,0,0,0,1,0}, { 0,1,1,0,0,1,1,1,1,1,1,0}, { 0,4,0,0,0,1,0,0,0,0,1,0}, { 0,1,0,0,0,1,0,0,0,0,1,0}, { 0,1,1,1,1,1,1,1,3,1,1,0}, { 0,0,0,0,0,0,0,0,0,0,0,0} }; int[][] reset = new int[12][12]; int xtorn=5; int ytorn=6; int score; int currdir[] = { 0, 2 }; // current direction int ex[] = { 1, 9 }; // enemy x-coordinates int ey[] = { 8, 3 }; // enemy y-coordinates Image[] sps = new Image[6]; Image offI; int lives = 3; public void init(){ d = getSize(); offI=createImage(d.width,d.height); sps[0] = getImage(getDocumentBase(), "wall.jpg"); sps[1] = getImage(getDocumentBase(), "dot.jpg"); sps[2] = getImage(getDocumentBase(), "hall.jpg"); sps[4] = getImage(getDocumentBase(), "x.jpg"); sps[3] = getImage(getDocumentBase(), "tee.jpg"); sps[5] = getImage(getDocumentBase(), "torn.jpg"); for(int a = 0; a<12; a++){ for(int b = 0; b<12; b++){ reset[a][b] = map[a][b]; } } tm = new Thread(this); tm.start(); requestFocus(); this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent k) { if(lives>0){ if(k.getKeyCode() == KeyEvent.VK_UP){ if(ytorn>0){ if(map[(ytorn-1)%12][xtorn]==1 || map[(ytorn-1)%12][xtorn]==2 || map[(ytorn-1)%12][xtorn]==4 || map[(ytorn-1)%12][xtorn]==3){ if(check_move((ytorn-1)%12,xtorn)){ map[ytorn][xtorn]=2; ytorn--; ytorn%=12; map[ytorn][xtorn]=5; } } } else{ if(map[11][xtorn]==1 || map[11][xtorn]==2 || map[11][xtorn]==4 || map[11][xtorn]==3){ if(check_move(11,xtorn)){ map[ytorn][xtorn]=2; ytorn=11; map[ytorn][xtorn]=5; } } } } else if(k.getKeyCode() == KeyEvent.VK_DOWN){ if(map[(ytorn+1)%12][xtorn]==1 || map[(ytorn+1)%12][xtorn]==2 || map[(ytorn+1)%12][xtorn]==4 || map[(ytorn+1)%12][xtorn]==3){ if(check_move((ytorn+1)%12,xtorn)){ map[ytorn][xtorn]=2; ytorn++; ytorn%=12; map[ytorn][xtorn]=5; } } } else if(k.getKeyCode() == KeyEvent.VK_LEFT){ if(xtorn>0){ if(map[ytorn][(xtorn-1)%12]==1 || map[ytorn][(xtorn-1)%12]==2 || map[ytorn][(xtorn-1)%12]==4 || map[ytorn][(xtorn-1)%12]==3){ if(check_move(ytorn,(xtorn-1)%12)){ map[ytorn][xtorn]=2; xtorn--; xtorn%=12; map[ytorn][xtorn]=5; } } } else{ if(map[ytorn][11]==1 || map[ytorn][11]==2 || map[ytorn][11]==4 || map[ytorn][11]==3){ if(check_move(ytorn,11)){ map[ytorn][xtorn]=2; xtorn=11; map[ytorn][xtorn]=5; } } } } else if(k.getKeyCode() == KeyEvent.VK_RIGHT){ if(map[ytorn][(xtorn+1)%12]==1 || map[ytorn][(xtorn+1)%12]==2 || map[ytorn][(xtorn+1)%12]==4 || map[ytorn][(xtorn+1)%12]==3){ if(check_move(ytorn,(xtorn+1)%12)){ map[ytorn][xtorn]=2; xtorn++; xtorn%=12; map[ytorn][xtorn]=5; } } } } if(k.getKeyChar() == 'r') resetValues(); repaint(); } }); } public void run(){ while(true){ if(lives>0){ moveEnemies(); repaint(); } try{ Thread.sleep(200); }catch(InterruptedException e){}; } } public void moveEnemies(){ for(int i = 0; i<currdir.length; i++){ if(unblocked(i)){ // do nothing } else { // try new direction do{ currdir[i]=Math.abs(r.nextInt()%4); }while(!unblocked(i)); } if( currdir[i]==0){ // move UP map[ey[i]][ex[i]] = 1; if(ey[i]==0) ey[i]=11; else ey[i]--; map[ey[i]][ex[i]] = 4; } else if(currdir[i]==1){ // move RT map[ey[i]][ex[i]] = 1; ex[i]++; ex[i]%=12; map[ey[i]][ex[i]] = 4; } else if(currdir[i]==2){ // move DN map[ey[i]][ex[i]] = 1; ey[i]++; map[ey[i]][ex[i]] = 4; } else{ // move LT map[ey[i]][ex[i]] = 1; if(ex[i]==0) ex[i]=11; else ex[i]--; map[ey[i]][ex[i]] = 4; } } //check for collisions if(ex[0]==xtorn && ey[0]==ytorn){ lives--; resetPlayer(); } if(ex[1]==xtorn && ey[1]==ytorn){ lives--; resetPlayer(); } } public boolean unblocked(int e){ if(currdir[e]==0){ //up if(map[(ey[e]-1)%12][ex[e]]!=0) return true; } else if(currdir[e]==1){ // right if(map[ey[e]][(ex[e]+1)%12]!=0) return true; } else if(currdir[e]==2){ // down if(map[(ey[e]+1)%12][ex[e]]!=0) return true; } else{ //left if(ex[e]>0){ if (map[ey[e]][(ex[e]-1)%12]!=0) return true; } else { if(map[ey[e]][11]!=0) return true; } } return false; } public boolean check_move(int y, int x){ if(map[y][x]==1) score+=10; else if(map[y][x]==3) score+=100; else if(map[y][x]==4){ lives--; map[ytorn][xtorn]=2; if(lives>0){ resetPlayer(); } return false; } return true; } public void resetPlayer(){ xtorn=5; ytorn=6; map[ytorn][xtorn]=5; } public void resetValues(){ for(int a = 0; a<12; a++){ for(int b = 0; b<12; b++){ map[a][b] = reset[a][b]; } } xtorn=5; ytorn=6; score=0; lives=3; currdir[0] = 0; currdir[1] = 2; ex[0] = 1; ex[1] = 9; ey[0] = 8; ey[1] = 3; } public void update(Graphics g){ paint(g); } public void paint(Graphics g){ Graphics offG = offI.getGraphics(); offG.setColor(Color.white); offG.fillRect(0,0,d.width,d.height); offG.setColor(Color.black); offG.drawString("SCORE: " + score, 10, d.height-10); offG.drawString("LIVES: " + lives, d.width/2-10, d.height-10); for(int y=0; y<map.length; y++) for(int x=0; x<map[y].length; x++) offG.drawImage(sps[map[y][x]],10+30*x,10+30*y,this); if(score>=720 && lives>0) offG.drawString("WIN!!!", d.width-100, d.height-10); if(lives<=0) offG.drawString("LOSS!!!", d.width-100, d.height-10); g.drawImage(offI, 0, 0, this); } }


ASSIGNMENT: