返回
让 Canvas 妙趣横生:三个引人入胜的小游戏
前端
2023-09-05 04:24:53
前言
欢迎来到 Canvas 的奇妙世界!如果你已经读过我之前的文章,那么你已经对这个强大的绘图库有了基本的了解。今天,我们将更进一步,通过三个引人入胜的小游戏,探索 Canvas 的无限可能性。我们将从一个激烈的射击游戏开始,然后跳到一个考验你逻辑思维的益智游戏,最后用一个令人上瘾的街机游戏来结束这段旅程。在每个游戏中,我们将逐步分解代码,提供清晰易懂的解释,并提供代码示例,让你能够亲身体验 Canvas 的魔力。
游戏 1:太空射击
让我们从一场激烈的太空射击游戏开始。你将驾驶一艘宇宙飞船,抵御一波又一波的外星入侵者。游戏采用简单的物理引擎,让飞船和子弹都能真实地移动和碰撞。
// 设定画布尺寸
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
// 创建飞船
const ship = {
x: canvas.width / 2,
y: canvas.height / 2,
width: 20,
height: 20,
};
// 创建外星人
const aliens = [];
for (let i = 0; i < 10; i++) {
aliens.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
width: 20,
height: 20,
});
}
// 游戏循环
function gameLoop() {
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制飞船
ctx.fillStyle = 'white';
ctx.fillRect(ship.x, ship.y, ship.width, ship.height);
// 绘制外星人
for (let i = 0; i < aliens.length; i++) {
const alien = aliens[i];
ctx.fillStyle = 'red';
ctx.fillRect(alien.x, alien.y, alien.width, alien.height);
}
// 更新飞船和外星人位置
// ...
// 检查碰撞
// ...
// 继续游戏循环
requestAnimationFrame(gameLoop);
}
// 启动游戏循环
gameLoop();
游戏 2:15 拼图
接下来,我们将探索一个经典的益智游戏:15 拼图。你的目标是将被打乱的数字块排列成顺序,从 1 到 15。
// 设定画布尺寸
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 400;
// 创建拼图块
const tiles = [];
for (let i = 0; i < 15; i++) {
tiles.push({
x: i % 4 * 100,
y: Math.floor(i / 4) * 100,
width: 100,
height: 100,
value: i + 1,
});
}
// 当前空白块
let blankTile = tiles[tiles.length - 1];
// 绘制拼图
function drawPuzzle() {
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制拼图块
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i];
ctx.fillStyle = tile.value % 2 ? 'white' : 'black';
ctx.fillRect(tile.x, tile.y, tile.width, tile.height);
// 绘制数字
ctx.fillStyle = 'black';
ctx.font = '32px Arial';
ctx.fillText(tile.value, tile.x + 20, tile.y + 50);
}
}
// 移动拼图块
function moveTile(tile) {
// 检查是否可以移动
if (isMovable(tile)) {
// 交换空白块和当前块的位置
const temp = blankTile;
blankTile = tile;
tile = temp;
// 更新拼图块数组
const index = tiles.indexOf(tile);
tiles[index] = blankTile;
tiles[tiles.length - 1] = tile;
}
}
// 检查拼图是否完成
function isPuzzleSolved() {
// 检查每个拼图块是否在正确位置
for (let i = 0; i < tiles.length; i++) {
if (tiles[i].value !== i + 1) {
return false;
}
}
// 如果所有拼图块都在正确位置,则返回 true
return true;
}
// 添加事件监听器
canvas.addEventListener('click', function(e) {
// 获取点击位置
const x = e.clientX - canvas.offsetLeft;
const y = e.clientY - canvas.offsetTop;
// 检查点击的拼图块
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i];
if (x >= tile.x && x <= tile.x + tile.width && y >= tile.y && y <= tile.y + tile.height) {
// 移动拼图块
moveTile(tile);
// 检查拼图是否完成
if (isPuzzleSolved()) {
alert('恭喜!你完成了拼图!');
}
}
}
});
// 启动绘图循环
drawPuzzle();
游戏 3:打砖块
最后,让我们用一个经典的街机游戏——打砖块来结束这场旅程。你的目标是使用球和球拍来打破屏幕上的所有砖块,同时避免球掉落到底部。
// 设定画布尺寸
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 400;
// 创建球
const ball = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 10,
dx: 2,
dy: -2,
};
// 创建球拍
const paddle = {
x: canvas.width / 2 - 50,
y: canvas.height - 20,
width: 100,
height: 10,
};
// 创建砖块
const bricks = [];
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 10; j++) {
bricks.push({
x: 50 + i * 60,
y: 50 + j * 20,
width: 50,
height: 20,
});
}
}
// 游戏循环
function gameLoop() {
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制球
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fill();
// 绘制球拍
ctx.fillStyle = 'white';
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
// 绘制砖块
for (let i = 0; i < bricks.length; i++) {
const brick = bricks[i];
ctx.fillStyle = 'red';
ctx.fillRect(brick.x, brick.y, brick.width, brick.height);