建议全屏或者新页面运行、首次运行需要冷启动,时间要一点,不如倒杯茶去~白屏也是需要等一下即可
已经实现的游戏一览:
- 俄罗斯方块
游戏界面
游戏实现解析
代码参考Inscode - 查看文件即可,在本节,我将分步解析一个使用HTML5 Canvas和JavaScript实现的经典打砖块游戏。通过拆解游戏的各个模块,你将了解如何通过代码实现碰撞检测、动画循环和用户交互等核心功能。
页面布局与交互元素
在index.html
文件中,我们主要设置了游戏的基本界面,包括画布区域、得分显示、速度选择、控制按钮和开始按钮。
<div class="game-container">
<div style="display:flex;width:100%;justify-content:space-between;">
<div id="score">得分: 0</div>
<div class="settings">
<select id="speedSelect" class="speed-select">
<option value="1">慢速</option>
<option value="2" selected>中速</option>
<option value="3">快速</option>
</select>
</div>
</div>
<canvas id="gameCanvas"></canvas>
<div class="controls">
<button class="btn" id="leftBtn">←</button>
<button class="btn" id="rightBtn">→</button>
</div>
<button id="startBtn">开始游戏</button>
</div>
<canvas id="gameCanvas">
:用于绘制游戏元素(小球、砖块和挡板),游戏的主要区域。- 得分和速度选择:实时更新得分,速度选择允许玩家选择游戏的难度。
- 控制按钮:使用左右箭头按钮(适用于触屏设备)控制挡板的移动。
- 开始按钮:用于控制游戏的开始、暂停和重置。
JavaScript游戏逻辑与渲染
JavaScript部分实现了整个游戏的核心逻辑和绘图。
画布初始化与参数设置
javascript">const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = Math.min(400, window.innerWidth - 40);
canvas.height = 500;
我们创建画布并获取绘图上下文 (ctx
)。接着,设定画布尺寸,使其在较小的屏幕上自适应宽度(限制最大宽度为400像素)。
游戏参数配置
javascript">const paddleHeight = 10, paddleWidth = 75;
const brickRowCount = 5, brickColumnCount = 5, brickWidth = 60, brickHeight = 20;
const brickPadding = 8, brickOffsetTop = 30;
- 挡板:宽75高10,用于控制小球的反弹。
- 砖块:5行5列,每个砖块宽60高20,行列之间有8像素的间距。
这些参数定义了游戏的布局,确保砖块和挡板的尺寸适合画布。
速度配置与选择事件
javascript">const speedConfigs = {
1: { dx: 2, dy: -2, paddleSpeed: 5 },
2: { dx: 3, dy: -3, paddleSpeed: 7 },
3: { dx: 4, dy: -4, paddleSpeed: 9 }
};
let currentSpeed = speedConfigs[2];
游戏的难度通过speedConfigs
配置。dx
和dy
是小球在X和Y轴上的移动速度,paddleSpeed
表示挡板的移动速度。玩家可以通过速度选择菜单 (speedSelect
) 改变这些配置。
游戏初始化 (initGame
)
initGame
函数用于重置游戏状态,包括小球位置、挡板位置、砖块状态和得分。
javascript">function initGame() {
// 初始化挡板位置
paddleX = (canvas.width - paddleWidth) / 2;
// 初始化小球位置与速度
x = canvas.width / 2;
y = canvas.height - 30;
dx = currentSpeed.dx;
dy = currentSpeed.dy;
// 初始化砖块数组
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
// 重置得分
score = 0;
scoreElement.textContent = `得分: ${score}`;
draw();
}
- 挡板和小球初始位置:使小球位于画布下方中心,挡板位于画布底部中心。
- 砖块数组:砖块存储在二维数组
bricks
中。status
属性表示砖块是否存在(1表示存在,0表示已被打掉)。 - 重置分数:得分清零并更新显示。
控制事件
我们为触摸按钮和键盘添加事件监听,使玩家能够通过左右方向键或按钮移动挡板。
javascript">document.addEventListener('keydown', (e) => { /*...*/ });
document.addEventListener('keyup', (e) => { /*...*/ });
通过这些事件,leftPressed
和 rightPressed
控制挡板的移动方向。
碰撞检测 (collisionDetection
)
collisionDetection
函数实现小球与砖块的碰撞检测,破坏被碰撞的砖块并更新得分。
javascript">function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const b = bricks[c][r];
if (b.status === 1) {
if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
dy = -dy;
b.status = 0;
score++;
scoreElement.textContent = `得分: ${score}`;
if (score === brickRowCount * brickColumnCount) {
alert('恭喜你赢了!');
initGame();
return;
}
}
}
}
}
}
- 碰撞检测:检查小球是否在砖块范围内,若是则反转
dy
方向,破坏砖块(将其status
设为0)。 - 游戏胜利检测:如果破坏的砖块数等于总砖块数,显示胜利信息并重置游戏。
绘制函数
- 小球:使用
arc
绘制圆形小球。 - 挡板:使用
rect
绘制矩形挡板。 - 砖块:遍历
bricks
数组,绘制每个未被破坏的砖块。
javascript">function drawBall() { /*...*/ }
function drawPaddle() { /*...*/ }
function drawBricks() { /*...*/ }
游戏主循环 (draw
)
draw
函数作为主循环,不断更新游戏状态和画布绘制。
javascript">function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
if (gameStarted) {
collisionDetection();
// 小球碰到左右边界时反弹
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) dx = -dx;
// 小球碰到顶部时反弹,碰到底部未击中挡板时游戏结束
if (y + dy < ballRadius) dy = -dy;
else if (y + dy > canvas.height - ballRadius) { /*...*/ }
// 挡板移动
if (rightPressed && paddleX < canvas.width - paddleWidth) paddleX += currentSpeed.paddleSpeed;
else if (leftPressed && paddleX > 0) paddleX -= currentSpeed.paddleSpeed;
// 更新小球位置
x += dx;
y += dy;
}
animationId = requestAnimationFrame(draw);
}
- 清除画布:在每帧绘制前清除画布,避免前一帧图像残留。
- 碰撞检测:调用
collisionDetection
,更新小球的移动方向和砖块状态。 - 边界反弹:小球到达边界时反弹,若未击中挡板则游戏结束。
- 挡板移动:根据按键更新挡板位置。
- 位置更新:将小球的新位置传递给
draw
以绘制下一帧。
开始和重新开始
startBtn
按钮控制游戏开始和重置。点击“开始游戏”将启动draw
函数动画循环,再次点击会重置游戏状态。
总结
通过阅读本文,相信你不只是成功摸鱼(运行了前面的代码),还通过阅读代码解析,看到了HTML5 Canvas的强大绘图能力与JavaScript结合可实现流畅的动画和交互功能。
游戏的核心流程了解的差不多了,记得事件下哈~