地圖並非手寫陣列,而是由地圖編輯器(如 Mappy、自製工具)產出,再匯出為二進位或文字格式嵌入程式。常見視角:俯視(RPG、SLG)、側視(動作)、45 度斜視。本文以俯視角為例。
// 24×10 地圖,0=地板,1=牆壁
public static final byte[][] MAP_DATA = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0}
};
TILE_W, TILE_H。mapX, mapY(左上角在螢幕位置,負值表示向左/上捲動)。SCR_W, SCR_H。MAX_COL = SCR_W/TILE_W + 2, MAX_ROW = SCR_H/TILE_H + 2(+2 保證邊緣完整)。int drawnRows = 0;
for (int r = startRow; r < MAP_DATA.length; r++) {
boolean any = false;
for (int c = startCol; c < MAP_DATA[r].length; c++) {
int x = mapX + c * TILE_W;
int y = mapY + r * TILE_H;
if (x <= SCR_W && y <= SCR_H && x >= -TILE_W && y >= -TILE_H) {
g.drawImage(tiles[MAP_DATA[r][c]], x, y, Graphics.TOP|Graphics.LEFT);
any = true;
if (++drawnCols > MAX_COL) break;
}
}
if (any) if (++drawnRows > MAX_ROW) break;
}
缺點:地圖越大、迴圈越長,FPS 隨地圖尺寸線性下降。
// 計算左上角對應的地圖陣列索引
int startCol = (-TILE_W - mapX) / TILE_W;
int startRow = (-TILE_H - mapY) / TILE_H;
if (startCol < 0) startCol = 0;
if (startRow < 0) startRow = 0;
for (int r = startRow; r < startRow + MAX_ROW; r++) {
for (int c = startCol; c < startCol + MAX_COL; c++) {
if (r < 0 || c < 0 || r >= MAP_DATA.length || c >= MAP_DATA[0].length) continue;
int x = mapX + c * TILE_W;
int y = mapY + r * TILE_H;
g.drawImage(tiles[MAP_DATA[r][c]], x, y, Graphics.TOP|Graphics.LEFT);
}
}
優點:迴圈次數固定 = 可視塊數,與地圖總大小無關,FPS 恆定。
tiles[] 可存放 AnimatedTile 物件,paint() 內部自動播放幀。MAP_DATA[r][c] 判斷可通行性,無需額外結構。核心繪製邏輯僅依賴 mapX/mapY,遊戲主迴圈只需更新這兩值(跟隨主角、鏡頭震動、過場移動),即可復用於 RPG、SLG、解謎等多類型專案。