MIDP 2.0 javax.microedition.lcdui.game.TiledLayer 專為 2D 遊戲地圖設計:將一張「素材圖集」切割成等大小 Tile,以二維網格(Cell)組合成大地圖。本文詳細講解構造函數、貼磚流程、二維陣列地圖數據組織、繪製與視窗截取。
public TiledLayer(int columns, int rows, Image image, int tileWidth, int tileHeight)
columns, rows:地圖尺寸(格子數)image:素材圖集(包含所有 Tile 的單張圖)tileWidth, tileHeight:單個 Tile 尺寸,圖集寬高必須是其整數倍
// 素材圖:9x9 格子,每格 16x16,圖集寬 144、高 16(單行排列 9 個 Tile)
Image tileset = Image.createImage("/tiles.png"); // 假設 144x16
TiledLayer map = new TiledLayer(9, 9, tileset, 16, 16);
通常用二維陣列描述地圖佈局,雙重迴圈批量貼磚:
// 地圖數據:9x9,數字對應 Tile 索引(1-based)
final static int[][] MAP_DATA = {
{4,4,4,4,4,4,4,4,4},
{4,1,2,3,1,3,2,1,4},
{4,1,5,1,1,2,4,3,4},
{4,3,5,6,4,3,7,8,4},
{4,3,6,7,7,7,3,2,4},
{4,7,2,1,1,1,6,2,4},
{4,3,6,7,7,7,3,2,4},
{4,7,2,1,1,1,6,2,4},
{4,4,4,4,4,4,4,4,4}
};
// 貼磚
for (int y = 0; y < MAP_DATA.length; y++) {
for (int x = 0; x < MAP_DATA[y].length; x++) {
map.setCell(x, y, MAP_DATA[y][x]);
}
}
paint(Graphics g):繪製整張地圖(或可見區域)setViewWindow(int x, int y, int width, int height):設定可見視窗,配合角色座標實現地圖滾動getViewWindowX/Y/Width/Height():取得視窗參數
// 遊戲中炸開牆壁:將 (3,3) 從 Tile 5(磚牆)改為 Tile 1(地板)
map.setCell(3, 3, 1);
建立多個 TiledLayer:背景層、前景層、碰撞層(不繪製,只用邏輯判斷)。繪製順序:背景 → 精靈 → 前景。
setViewWindow 僅繪製可見區,避免全圖繪製開銷。TiledLayer 實例。byte[][] 或 BitSet 存儲碰撞資訊,比查詢 Tile 索引快。tileWidth/Height 整除,否則構造拋異常。setCell(x, y, ...) 參數順序是 列、行(x, y),與二維陣列 [row][col] 相反,易寫反。
public class MapDemo extends GameCanvas implements Runnable {
private TiledLayer map;
private int viewX = 0, viewY = 0;
public MapDemo() {
super(false);
try {
Image tiles = Image.createImage("/tiles.png"); // 144x16, 9 tiles
map = new TiledLayer(9, 9, tiles, 16, 16);
// 貼磚...
for (int y=0;y<9;y++) for (int x=0;x<9;x++) map.setCell(x,y, MAP_DATA[y][x]);
} catch (IOException e) { e.printStackTrace(); }
new Thread(this).start();
}
public void run() {
Graphics g = getGraphics();
while (true) {
// 更新視窗跟隨角色...
map.setViewWindow(viewX, viewY, getWidth(), getHeight());
map.paint(g);
flushGraphics();
try { Thread.sleep(50); } catch (InterruptedException ignored) {}
}
}
}