|
這邊的平面地圖所指的是地形沒有高低,只有障礙物的地圖,人物在遇到障礙物時將無法前進,問題是如何判斷障礙物?
學過資料結構的話,大家應該都知道老鼠走迷宮這個例子,使用陣列,並在當中填入1表示迷宮的牆,0表示可以前進行的格子,而平面地圖也是利用這個方式來製作。
並不是由繪圖區域上的障礙物座標來判斷人物是否能前進,而是在一個陣列中判斷,將陣列元素設定為1表示障礙物,如下所示:

利用兩個變數(i, j)來表示人物於陣列中的位置,當人物上下左右移動前,先判斷下一個位置是否為0,如果是才可以前進(改變i, j的值),否則就停留在原地。
在繪圖時,只要根據陣列將指定的圖片一格格繪製上去就可以了,如下圖所示:

當然障礙物並不一定只有一種,您也可以用其它的元素值表示不同的障礙物,例如2表示樹木、3表示水池等等;如果地圖較大,可以只繪製指定範圍的圖形,這並不難,指定陣列中的起始與終止範圍就可以了,如下圖所示:

這個平面地圖的製作方式,可以使用於俯視、斜角地圖,下面這個程式是個實作的例子,您可以先看看 效果 程式中使用了事件處理,程式碼長了一些,有興趣的就耐心看完吧!
package onlyfun.caterpillar.graphics.animation; import java.awt.*; import java.awt.event.*; import javax.swing.JApplet; public class Maze1 extends JApplet implements KeyListener { private int appletWidth, appletHeight, blockWidth, blockHeight; private Image character, floor, block1, block2; private Image backGround, offScreen; private Graphics drawOffScreen; private SpriteAndMaze spriteAndMaze; private int[][] maze = {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {0,0,0,0,0,1,0,0,2,0,0,1,1,0,0,0,2,2}, {2,0,1,0,1,0,0,0,2,0,1,0,0,1,1,0,2,2}, {2,0,0,0,0,0,1,1,2,0,1,0,1,0,0,0,0,2}, {2,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,2}, {2,1,0,1,0,1,1,0,1,1,0,0,1,0,0,0,0,2}, {2,1,0,0,0,0,1,0,0,2,0,0,0,0,2,0,2,2}, {2,1,0,0,2,0,1,1,1,2,0,1,0,0,2,0,1,2}, {2,1,1,1,1,0,0,0,1,2,0,0,0,0,1,0,0,2}, {2,0,0,0,0,0,0,0,1,0,0,1,1,0,2,1,0,2}, {2,0,2,0,1,0,0,0,1,0,1,0,0,0,0,0,0,2}, {2,1,2,0,0,0,1,1,1,0,1,0,1,1,2,1,0,2}, {2,0,0,0,2,0,0,0,1,1,0,0,0,0,0,0,0,0}, {2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}; private int characterImIndexX, characterImIndexY; private int characterWidth, characterHeight; public void init() { addKeyListener(this); setBackground(Color.white); //取得Applet的高度、寬度 appletWidth = getSize().width; appletHeight = getSize().height; //取得影像 MediaTracker mediaTracker = new MediaTracker(this); character = getImage(getDocumentBase(),"character.gif"); floor = getImage(getDocumentBase(),"floor.jpg"); block1 = getImage(getDocumentBase(),"block1.gif"); block2 = getImage(getDocumentBase(),"block2.gif"); mediaTracker.addImage(character,0); mediaTracker.addImage(floor,0); mediaTracker.addImage(block1,0); mediaTracker.addImage(block2,0); try { showStatus("影像載入中(Loading Images)..."); mediaTracker.waitForAll(); } catch(InterruptedException e){ e.printStackTrace(); } spriteAndMaze = new SpriteAndMaze(0, 1, maze); blockWidth = appletWidth / maze[0].length; blockHeight = appletHeight / maze.length; characterWidth = character.getWidth(this)/3; characterHeight = character.getHeight(this)/4; characterImIndexY = characterHeight; //建立次畫面 offScreen = createImage(appletWidth, appletHeight); drawOffScreen = offScreen.getGraphics(); // 建立地圖 backGround = createImage(appletWidth, appletHeight); Graphics g = backGround.getGraphics(); // 繪地版 for(int i = 0; i < maze.length; i++) { for(int j = 0; j < maze[0].length; j++) { g.drawImage(floor, j*blockWidth, i*blockHeight, blockWidth, blockHeight, this); } } // 繪障礙物 for(int i = 0; i < maze.length; i++) { for(int j = 0; j < maze[0].length; j++) { switch(maze[i][j]) { case 1: g.drawImage(block1, j*blockWidth, i*blockHeight, blockWidth, blockHeight, this); break; case 2: g.drawImage(block2, j*blockWidth, i*blockHeight, blockWidth, blockHeight, this); break; default: g.drawImage(floor, j*blockWidth, i*blockHeight, blockWidth, blockHeight, this); } } } } public void paint(Graphics g) { // 在背後繪地圖 drawOffScreen.drawImage(backGround, 0, 0, this); // 貼人物 drawOffScreen.drawImage(character, spriteAndMaze.getLocationX()*blockWidth, spriteAndMaze.getLocationY()*blockHeight, (spriteAndMaze.getLocationX()+1)*blockWidth, (spriteAndMaze.getLocationY()+1)*blockHeight, characterImIndexX, characterImIndexY, characterImIndexX+characterWidth, characterImIndexY+characterHeight, this); //將次畫面貼到主畫面中 g.drawImage(offScreen, 0, 0,this); } public void update(Graphics g) { paint(g); } //=====實作KeyListener介面 ===== public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); characterImIndexX = characterImIndexX + characterWidth; switch(key) { case KeyEvent.VK_RIGHT: spriteAndMaze.moveRight(); characterImIndexY = characterHeight; break; case KeyEvent.VK_LEFT: spriteAndMaze.moveLeft(); characterImIndexY = characterHeight * 3; break; case KeyEvent.VK_UP: spriteAndMaze.moveUp(); characterImIndexY = 0; break; case KeyEvent.VK_DOWN: spriteAndMaze.moveDown(); characterImIndexY = characterHeight * 2; break; } if(characterImIndexX >= character.getWidth(null)) characterImIndexX = 0; repaint(); } public void keyReleased(KeyEvent e) {} } class SpriteAndMaze { private int i, j; private int maze[][]; public SpriteAndMaze() {} public SpriteAndMaze(int x, int y) { this.i = y; this.j = x; } public SpriteAndMaze(int x, int y, int[][] maze) { this(x, y); this.maze = maze; } public void moveUp() { if(isMovable(i-1, j)) { i--; } } public void moveDown() { if(isMovable(i+1, j)) { i++; } } public void moveRight() { if(isMovable(i, j+1)) { j++; } } public void moveLeft() { if(isMovable(i, j-1)) { j--; } } private boolean isMovable(int i, int j) { if(i < 0 || j < 0 || j >= maze[0].length || i >=maze.length) return false; if(maze[i][j] == 0) return true; else return false; } public int getLocationX() { return j; } public int getLocationY() { return i; } public void setLocationX(int locationX) { this.j = locationX; } public void setLocationY(int locationY) { this.i= locationY; } public int[][] getMaze() { return maze; } public void setMaze(int[][] maze) { this.maze = maze; } }
|