最後一週了,我們來點進階的!一起進到童年的遊戲世界,試著利用 Canvas 做個 RPG 遊戲,相信很多人都有經歷過寶可夢遊戲的時代,每次看到畫面總會想起那時候的童年回憶,下面附上一張遊戲畫面來讓大家回憶一下:
這就是我們今天的目標, Canvas 技術就可以讓我們完成類似寶可夢的遊戲介面與簡單的操作行為。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="canvas.js"></script>
<title>珊迪 Canvas Game</title>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>
window.onload = () => {
// 初始Canvas與遊戲參數
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const {offsetWidth: CanvasWidth, offsetHeight: CanvasHeight}
= document.getElementById("canvas");
let gameMapLoad = false;
// 初始地圖物件
const gameMap = new Image();
gameMap.onload = () => {
gameMapLoad = true;
if (gameMapLoad) assetsLoaded();
}
gameMap.src = "images/gamemap.jpg";
// 初始事件
function assetsLoaded() {
ctx.drawImage(gameMap, 0, 0);
}
}
window.onload = () => {
// 初始Canvas、遊戲相關參數
...
let gameMapLoad = false, playerImageLoaded = false;
let zoom = 20;
let speed = 1;
// 動作參數
const moveConfig = {
"LEFT": "left",
"RIGHT": "right",
"UP": "up",
"DOWN": "down",
"STAND": "stand",
"DEFAULT": "default"
}
let moveMappingImage = {};
for (const [, value] of Object.entries(moveConfig)) {
moveMappingImage[value] = {
[moveConfig.DEFAULT]: `${value}-1`,
[moveConfig.STAND]: `${value}-1`,
[`${value}-1`]: `${value}-2`,
[`${value}-2`]: `${value}-1`,
}
}
...
// 初始人物物件
const playerImage = new Image();
playerImage.onload = () => {
playerImageLoaded = true;
if (playerImageLoaded) assetsLoaded();
};
playerImage.src = "images/player.png";
// 定義人物相關屬性
let player = {
x: Math.round((CanvasWidth/2)/zoom),
y: Math.round((CanvasHeight/2)/zoom),
currentDirection: moveConfig.STAND,
direction: {
[moveConfig.STAND] : {
x: 0,
y: 0
},
[`${moveConfig.DOWN}-1`] : {
x: 17,
y: 0
},
[`${moveConfig.DOWN}-2`] : {
x: 34,
y: 0
},
[`${moveConfig.UP}-1`] : {
x: 125,
y: 0
},
[`${moveConfig.UP}-2`] : {
x: 142,
y: 0
},
[`${moveConfig.LEFT}-1`] : {
x: 69,
y: 0
},
[`${moveConfig.LEFT}-2`] : {
x: 87,
y: 0
},
[`${moveConfig.RIGHT}-1`] : {
x: 160,
y: 0
},
[`${moveConfig.RIGHT}-2`] : {
x: 178,
y: 0
}
}
};
// 人物動作事件
player.move = (direction) => {
player.currentDirection =
moveMappingImage[direction][player.currentDirection]
?? moveMappingImage[direction][moveConfig.DEFAULT]
if (direction === moveConfig.LEFT
|| direction === moveConfig.RIGHT) {
player.x += (direction === moveConfig.LEFT
? -speed: speed);
}
if (direction === moveConfig.UP
|| direction === moveConfig.DOWN) {
player.y += (direction === moveConfig.UP
? -speed: speed);
}
assetsLoaded();
};
// 初始事件
function assetsLoaded() {
...
ctx.drawImage(playerImage,
player.direction[player.currentDirection].x,
player.direction[player.currentDirection].y,
zoom-2,
zoom,
player.x * zoom,
player.y * zoom,
zoom,
zoom
);
}
}
window.onload = () => {
...
// 鍵盤監聽事件-人物走路
document.onkeydown = (e) => {
const actionList = {
"ArrowLeft": () => player.move(moveConfig.LEFT),
"ArrowUp": () => player.move(moveConfig.UP),
"ArrowRight": () => player.move(moveConfig.RIGHT),
"ArrowDown": () => player.move(moveConfig.DOWN)
}
const action = actionList[e.key]
if (action) {
action();
}
};
}
按照以上四個步驟就能完成 RPG 小遊戲的基礎設定,包含地圖樣式、人物走動的方向、位置以及人物的角度樣式等等!恭喜你~如果跟著完成到這邊已經走進了遊戲的世界,明天讓我們繼續完成剩下的遊戲互動,例如走著走著吃到經驗值或是遇到別的人物。