实现弹弹球小游戏
游戏概述
“弹弹球”小游戏通过HTML5 Canvas、CSS7以及JavaScript实现。
玩家使用键盘控制挡板,反弹小球,避免小球掉落。
游戏界面为粉色,小球速度和颜色会随机变化。
使用工具
本篇文章有用到GPT-4o代码纠错,国内可稳定使用,感兴趣的大佬试试363Ai工具箱。
游戏玩法
- 控制挡板:使用键盘上的左右箭头键,移动挡板接住反弹的小球。
- 目标:尽可能长时间地保持小球在画布上方反弹。
- 失败条件:小球未被接住时,屏幕会显示“哈哈!你真笨!”,提示玩家重新尝试。
实现步骤
HTML结构
HTML部分定义了游戏的基本结构,包括画布、按钮和消息显示区。
代码展示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>/* 样式在这里定义 */</style><title>弹弹球游戏</title>
</head>
<body><div id="message">哈哈!你真笨!</div><canvas id="gameCanvas" width="800" height="600"></canvas><button id="startButton">开始</button><button id="endButton">结束</button><script>/* JavaScript代码在这里定义 */</script>
</body>
</html>
运行界面:

解释:HTML页面包含一个canvas元素用于游戏绘制,两个按钮用于控制游戏开始和结束,还有一个显示失败信息的div。
CSS样式
代码展示:
body {margin: 0;overflow: hidden;display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100vh;background-color: pink;
}
canvas {background: pink;display: block;border: 3px solid #fff;
}
#message {position: absolute;color: white;font-size: 48px;display: none;
}
button {margin: 10px;padding: 10px 20px;font-size: 16px;
}
解释:页面使用粉色背景,canvas也为粉色。按钮样式简单,居中显示。
#message在游戏失败时显示信息。
JavaScript实现
JavaScript负责游戏的动态逻辑,包括小球和挡板的运动、碰撞检测和用户交互。
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const message = document.getElementById('message');
const startButton = document.getElementById('startButton');
const endButton = document.getElementById('endButton');function randomSpeed() {return (Math.random() * 4 + 2) * (Math.random() < 0.5 ? 1 : -1);
}let ball = {x: canvas.width / 2,y: canvas.height / 2,dx: randomSpeed(),dy: randomSpeed(),radius: 10,color: '#00FFFF'
};let paddle = {width: 100,height: 10,x: canvas.width / 2 - 50,color: '#FFFFFF', // 白色挡板speed: 10 // 减慢速度
};let rightPressed = false;
let leftPressed = false;
let animationId;
let isRunning = false;
解释:
- 元素获取:获取canvas和按钮元素。
- 随机速度函数:randomSpeed函数为小球生成随机速度。
- 对象初始化:定义ball和paddle对象,包含位置、速度和颜色属性。
绘制函数
负责在Canvas上绘制小球和挡板。
function drawBall() {ctx.beginPath();ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);ctx.fillStyle = ball.color;ctx.fill();ctx.closePath();
}function drawPaddle() {ctx.beginPath();ctx.rect(paddle.x, canvas.height - paddle.height, paddle.width, paddle.height);ctx.fillStyle = paddle.color;ctx.fill();ctx.closePath();
}
解释:drawBall和drawPaddle函数在Canvas上绘制小球和挡板。
运动和碰撞逻辑
处理小球和挡板的运动逻辑及碰撞检测。
function movePaddle() {if (rightPressed && paddle.x < canvas.width - paddle.width) {paddle.x += paddle.speed;}if (leftPressed && paddle.x > 0) {paddle.x -= paddle.speed;}
}function changeBallColor() {const colors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A8', '#F3FF33'];ball.color = colors[Math.floor(Math.random() * colors.length)];
}function updateBall() {ball.x += ball.dx;ball.y += ball.dy;if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {ball.dx = -ball.dx;changeBallColor();}if (ball.y - ball.radius < 0) {ball.dy = -ball.dy;changeBallColor();} else if (ball.y + ball.radius > canvas.height - paddle.height) {if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {ball.dy = -ball.dy;changeBallColor();} else {message.style.display = 'block';cancelAnimationFrame(animationId);isRunning = false;}}
}
解释:
- 挡板移动:movePaddle根据键盘输入移动挡板。
- 颜色变化:changeBallColor在小球碰撞时改变其颜色。
- 更新逻辑:updateBall处理小球的运动和碰撞检测,碰撞后改变方向和颜色。
游戏循环
负责游戏的持续更新和重绘。
负责游戏的持续更新和重绘。function draw() {if (!isRunning) return;ctx.clearRect(0, 0, canvas.width, canvas.height);drawBall();drawPaddle();movePaddle();updateBall();animationId = requestAnimationFrame(draw);
}function resetGame() {ball.x = canvas.width / 2;ball.y = canvas.height / 2;ball.dx = randomSpeed();ball.dy = randomSpeed();message.style.display = 'none';
}
解释:
- 游戏循环:draw函数负责游戏的持续更新和重绘。
- 重置游戏:resetGame重置小球位置和速度,隐藏失败信息。
事件监听
处理用户输入和按钮点击事件。
document.addEventListener('keydown', (e) => {if (e.key === 'ArrowRight') {rightPressed = true;} else if (e.key === 'ArrowLeft') {leftPressed = true;}
});document.addEventListener('keyup', (e) => {if (e.key === 'ArrowRight') {rightPressed = false;} else if (e.key === 'ArrowLeft') {leftPressed = false;}
});startButton.addEventListener('click', () => {if (!isRunning) {resetGame();isRunning = true;draw();}
});endButton.addEventListener('click', () => {isRunning = false;cancelAnimationFrame(animationId);message.style.display = 'none';
});
解释:
- 键盘监听:监听左右箭头按键,控制挡板移动。
- 按钮事件:监听开始和结束按钮,控制游戏状态。
以下是完整的代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>body {margin: 0;overflow: hidden;display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100vh;background-color: pink;}canvas {background: pink;display: block;border: 3px solid #fff;}#message {position: absolute;color: white;font-size: 48px;display: none;}button {margin: 10px;padding: 10px 20px;font-size: 16px;}</style><title>弹弹球游戏</title>
</head>
<body><div id="message">哈哈!你真笨!</div><canvas id="gameCanvas" width="800" height="600"></canvas><button id="startButton">开始</button><button id="endButton">结束</button><script>const canvas = document.getElementById('gameCanvas');const ctx = canvas.getContext('2d');const message = document.getElementById('message');const startButton = document.getElementById('startButton');const endButton = document.getElementById('endButton');function randomSpeed() {return (Math.random() * 4 + 2) * (Math.random() < 0.5 ? 1 : -1);}let ball = {x: canvas.width / 2,y: canvas.height / 2,dx: randomSpeed(),dy: randomSpeed(),radius: 10,color: '#00FFFF'};let paddle = {width: 100,height: 10,x: canvas.width / 2 - 50,color: '#FFFFFF',speed: 10};let rightPressed = false;let leftPressed = false;let animationId;let isRunning = false;function drawBall() {ctx.beginPath();ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);ctx.fillStyle = ball.color;ctx.fill();ctx.closePath();}function drawPaddle() {ctx.beginPath();ctx.rect(paddle.x, canvas.height - paddle.height, paddle.width, paddle.height);ctx.fillStyle = paddle.color;ctx.fill();ctx.closePath();}function movePaddle() {if (rightPressed && paddle.x < canvas.width - paddle.width) {paddle.x += paddle.speed;}if (leftPressed && paddle.x > 0) {paddle.x -= paddle.speed;}}function changeBallColor() {const colors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A8', '#F3FF33'];ball.color = colors[Math.floor(Math.random() * colors.length)];}function updateBall() {ball.x += ball.dx;ball.y += ball.dy;if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {ball.dx = -ball.dx;changeBallColor();}if (ball.y - ball.radius < 0) {ball.dy = -ball.dy;changeBallColor();} else if (ball.y + ball.radius > canvas.height - paddle.height) {if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {ball.dy = -ball.dy;changeBallColor();} else {message.style.display = 'block';cancelAnimationFrame(animationId);isRunning = false;}}}function draw() {if (!isRunning) return;ctx.clearRect(0, 0, canvas.width, canvas.height);drawBall();drawPaddle();movePaddle();updateBall();animationId = requestAnimationFrame(draw);}function resetGame() {ball.x = canvas.width / 2;ball.y = canvas.height / 2;ball.dx = randomSpeed();ball.dy = randomSpeed();message.style.display = 'none';}document.addEventListener('keydown', (e) => {if (e.key === 'ArrowRight') {rightPressed = true;} else if (e.key === 'ArrowLeft') {leftPressed = true;}});document.addEventListener('keyup', (e) => {if (e.key === 'ArrowRight') {rightPressed = false;} else if (e.key === 'ArrowLeft') {leftPressed = false;}});startButton.addEventListener('click', () => {if (!isRunning) {resetGame();isRunning = true;draw();}});endButton.addEventListener('click', () => {isRunning = false;cancelAnimationFrame(animationId);message.style.display = 'none';});</script>
</body>
</html>
代码解析
- HTML:定义了游戏的基本结构,包括画布、按钮和消息显示区。
- CSS:设置了页面样式,粉色背景,居中显示的按钮和消息。
- JavaScript:
- 初始化游戏元素和状态。
- 定义小球和挡板的属性和行为。
- 实现小球的随机速度和颜色变化。
- 处理键盘输入以控制挡板移动。
- 使用requestAnimationFrame实现动画循环。
运行界面:

学习收获
通过这个项目,初学者可以掌握:
- HTML5 Canvas的基本用法
- JavaScript中对象和方法的使用
- 动画循环和用户交互的实现
- 简单的碰撞检测和游戏逻辑
这不仅是一个娱乐项目,也是一个学习和实践编程的好机会。通过不断调整和优化代码,玩家可以深入理解游戏开发的基本概念,为未来更复杂的项目打下坚实基础。
感谢阅读!!!

