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

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

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

這個平面地圖的製作方式,可以使用於俯視、斜角地圖,下面這個程式是個實作的例子,您可以先看看 效果 程式中使用了事件處理,程式碼長了一些,有興趣的就耐心看完吧!
- Maze1.java
package cc.openhome;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JApplet;
public class Maze1 extends JApplet implements KeyListener {
    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 blockWidth, blockHeight;
    private Image character, floor, block1, block2;
    private Image backGround, offScreen;
    private Graphics gOffScreen;
    private Sprite sprite;
    private int characterStartX, characterStartY;
    private int characterWidth, characterHeight;
    public void init() {
        addKeyListener(this);
        setBackground(Color.white);
        //取得影像
        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();
        }
        sprite = new Sprite(0, 1, maze);
        blockWidth = getWidth() / maze[0].length;
        blockHeight = getHeight() / maze.length;
        characterWidth = character.getWidth(this) / 3;
        characterHeight = character.getHeight(this) / 4;
        characterStartY = characterHeight;
        //建立次畫面
        offScreen = createImage(getWidth(), getHeight());
        gOffScreen = offScreen.getGraphics();
        // 建立地圖
        backGround = createImage(getWidth(), getHeight());
        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) {
        // 在背後繪地圖
        gOffScreen.drawImage(backGround, 0, 0, this);
        // 貼人物
        gOffScreen.drawImage(character,
                sprite.getX() * blockWidth,
                sprite.getY() * blockHeight,
                (sprite.getX() + 1) * blockWidth,
                (sprite.getY() + 1) * blockHeight,
                characterStartX, characterStartY,
                characterStartX + characterWidth,
                characterStartY + characterHeight,
                this);
        //將次畫面貼到主畫面中
        g.drawImage(offScreen, 0, 0, this);
    }
    public void update(Graphics g) {
        paint(g);
    }
    //=====實作KeyListener介面 =====
    public void keyPressed(KeyEvent e) {
        characterStartX = characterStartX + characterWidth;
        switch (e.getKeyCode()) {
            case KeyEvent.VK_RIGHT:
                sprite.moveRight();
                characterStartY = characterHeight;
                break;
            case KeyEvent.VK_LEFT:
                sprite.moveLeft();
                characterStartY = characterHeight * 3;
                break;
            case KeyEvent.VK_UP:
                sprite.moveUp();
                characterStartY = 0;
                break;
            case KeyEvent.VK_DOWN:
                sprite.moveDown();
                characterStartY = characterHeight * 2;
                break;
        }
        if (characterStartX >= character.getWidth(null)) {
            characterStartX = 0;
        }
        repaint();
    }
    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}
}
class Sprite {
    private int i, j;
    private int maze[][];
    Sprite(int x, int y, int[][] maze) {
        this.i = y;
        this.j = x;
        this.maze = maze;
    }
    void moveUp() {
        if (isMovable(i - 1, j)) {
            i--;
        }
    }
    void moveDown() {
        if (isMovable(i + 1, j)) {
            i++;
        }
    }
    void moveRight() {
        if (isMovable(i, j + 1)) {
            j++;
        }
    }
    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;
        }
        return false;
    }
    int getX() { return j; }
    int getY() { return i; }
}
以下是使用HTML5 Canvas的方式(如果瀏覽器支援HTML5 Canvas,例如最新版的Firexfox、Chrome、IE9等,可以直接將下面的內容存為HTML或按下檔名連結,直接載入瀏覽器執行觀看結果:
<!DOCTYPE html>
<html>
    <head>
        <meta content="text/html; charset=Big5" http-equiv="content-type">
        <script type="text/javascript">
            window.onload = function() {
                function Sprite(x, y, maze) {
                    var i = y;
                    var j = x;
                    
                    function isMovable(i, j) {
                        if (i < 0 || j < 0 ||
                            j >= maze[0].length || i >= maze.length) {
                            return false;
                        }
                        if (maze[i][j] === 0) {
                            return true;
                        }
                        
                        return false;
                    }
                    
                    this.moveUp = function() {
                        if(isMovable(i - 1, j)) {
                            i--;
                        }
                    };
                    
                    this.moveDown = function() {
                        if(isMovable(i + 1, j)) {
                            i++;
                        }
                    };
                    
                    this.moveRight = function() {
                        if(isMovable(i, j + 1)) {
                            j++;
                        }
                    };
                    
                    this.moveLeft = function() {
                        if(isMovable(i, j - 1)) {
                            j--;
                        }
                    };
                    
                    this.getX = function() {
                        return j;
                    };
                    
                    this.getY = function() {
                        return i;
                    };
                }
                
                var 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]];
            
                var sprite = new Sprite(0, 1, maze);
                
                var character = document.getElementById('character');
                var floor = document.getElementById('floor');
                var block1 = document.getElementById('block1');
                var block2 = document.getElementById('block2');
                document.body.removeChild(character);
                document.body.removeChild(floor);
                document.body.removeChild(block1);
                document.body.removeChild(block2);
                
                var canvas1 = document.getElementById('canvas1');
                var canvas2 = document.getElementById('canvas2');
                var context1 = canvas1.getContext('2d');
                var context2 = canvas2.getContext('2d');
                
                document.body.removeChild(canvas2);
                
                var blockWidth = canvas1.width / maze[0].length;
                var blockHeight = canvas1.height / maze.length;
                var characterWidth = 108 / 3;  // 人物圖片寬
                var characterHeight = 186 / 4; // 人物圖片高
                var characterStartX = 0;
                var characterStartY = characterHeight;
                
                var context = context1;
                
                // 繪地版
                function drawFloor() {
                    for(var i = 0; i < maze.length; i++) {
                        for(var j = 0; j < maze[0].length; j++) {
                            context.drawImage(
                             floor, j * blockWidth, i * blockHeight, 
                             blockWidth, blockHeight);
                        }
                    }
                }
                
                // 繪障礙物
                function drawBlock() {
                    for(var i = 0; i < maze.length; i++) {
                        for(var j = 0; j < maze[0].length; j++) {
                            switch (maze[i][j]) {
                                case 1:
                                    context.drawImage(
                                     block1, j * blockWidth, i * blockHeight,
                                     blockWidth, blockHeight);
                                    break;
                                case 2:
                                    context.drawImage(
                                     block2, j * blockWidth, i * blockHeight,
                                     blockWidth, blockHeight);
                                    break;
                                default:
                                     context.drawImage(
                                      floor, j * blockWidth, i * blockHeight,
                                      blockWidth, blockHeight);
                            }
                        }
                    }                
                }
      
                // 繪人物
                function drawCharacter() {
                    context.drawImage(character, 
                            characterStartX, 
                            characterStartY,
                            characterWidth,
                            characterHeight,
                            sprite.getX() * blockWidth,
                            sprite.getY() * blockHeight,
                            blockWidth,
                            blockHeight);
                }
                
                drawFloor();
                drawBlock();
                drawCharacter();
                
                context = context2;
                drawFloor();
                drawBlock();
                
                document.onkeydown = function(event) {
                    characterStartX = characterStartX + characterWidth;
                    switch (event.which) {
                        case 39: // 右
                            sprite.moveRight();
                            characterStartY = characterHeight;
                            break;
                        case 37: // 左    
                            sprite.moveLeft();
                            characterStartY = characterHeight * 3;
                            break;
                       case 38: // 上
                            sprite.moveUp();
                            characterStartY = 0;
                            break;
                       case 40: // 下
                            sprite.moveDown();
                            characterStartY = characterHeight * 2;
                            break;
                    }
                    if (characterStartX >= character.width) {
                        characterStartX = 0;
                    }
                    
                    drawCharacter();
                    
                    if(context === context2) {
                        document.body.replaceChild(canvas2, canvas1);
                        context = context1;
                    }
                    else {
                        document.body.replaceChild(canvas1, canvas2);
                        context = context2;
                    }
                    
                    context.clearRect(0, 0, canvas1.width, canvas1.height);
                    drawFloor();
                    drawBlock();
                };
            };
        </script>
    </head>
    <body>       
        <canvas id="canvas1" width="900" height="600"></canvas>
        <canvas id="canvas2" width="900" height="600"></canvas>
        <img id="character" src="images/character.gif" 
                            style="visibility: hidden"/>
        <img id="floor" src="images/floor.jpg" 
                            style="visibility: hidden"/>
        <img id="block1" src="images/block1.gif" 
                            style="visibility: hidden"/>
        <img id="block2" src="images/block2.gif" 
                            style="visibility: hidden"/>
    </body>
</html>

