在 AI 编程助手逐渐融入日常的今天,像"打砖块"这种交互小游戏,过去也许要半天才能从零实现;现在借助 Trae 生成基础骨架,再做少量调整与打磨,就能很快产出一个手感顺畅、兼顾键鼠与触控的网页游戏。
本篇文章会带你从 零到可玩,在 HTML 页面里一步步构建游戏,代码和解释紧密穿插,读完就能直接运行。
1. 游戏功能与技术选型
1.1 功能需求
- 画布自适配高清屏(DPR 适配)
- 球拍、弹球、五行九列彩色砖块
- 碰撞检测:墙壁 / 球拍 / 砖块
- 计分与生命值,速度等级随进度提升
- 键盘、鼠标与移动端触控三种操控
- 开始 / 暂停 / 重置控制与提示面板
1.2 技术栈
- HTML5 Canvas:绘制与像素级碰撞
- CSS3:现代化面板、按钮、响应式布局
- JavaScript:游戏循环、状态管理、事件处理
- Trae:生成页面框架、核心对象与事件绑定雏形
2. 页面与样式骨架
Trae 可以快速帮我们生成 HTML 结构和 CSS 样式,我们再在此基础上补充游戏逻辑。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Trae 打砖块</title>
<style>
:root {
--primary-color: #4CAF50;
--secondary-color: #ff9800;
--bg-color: #222;
--text-color: #fff;
}
body {
background: var(--bg-color);
color: var(--text-color);
font-family: Arial, sans-serif;
text-align: center;
margin: 0;
padding: 0;
}
#gameInfo {
display: flex;
justify-content: space-around;
padding: 10px;
background: var(--primary-color);
}
#gameCanvas {
background: #000;
display: block;
margin: 0 auto;
border: 2px solid var(--secondary-color);
}
.btn {
background: var(--secondary-color);
border: none;
padding: 10px 20px;
margin: 5px;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="gameInfo">
<span id="score">分数: 0</span>
<span id="lives">生命: 3</span>
<span id="speed">速度等级: 1</span>
</div>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div>
<button id="startBtn" class="btn">开始</button>
<button id="pauseBtn" class="btn">暂停</button>
<button id="resetBtn" class="btn">重置</button>
</div>
<script src="game.js"></script>
</body>
</html>
💡 说明:
- 顶部
#gameInfo
展示实时分数、生命和速度等级。 <canvas>
作为游戏绘制区域,初始 800×600,稍后用 JavaScript 动态缩放以适配 DPR。- 三个按钮用来控制游戏状态。
3. JavaScript:初始化与 DPR 适配
为了在高清屏幕上保持清晰,我们会获取 window.devicePixelRatio
进行缩放。
js
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
let dpr = window.devicePixelRatio || 1;
// 逻辑尺寸
const WIDTH = 800;
const HEIGHT = 600;
// DPR 适配
canvas.width = WIDTH * dpr;
canvas.height = HEIGHT * dpr;
canvas.style.width = WIDTH + 'px';
canvas.style.height = HEIGHT + 'px';
ctx.scale(dpr, dpr);
📌 关键点:
canvas.width
/canvas.height
是实际像素尺寸 ,要乘上dpr
。canvas.style.width
/style.height
是 CSS 尺寸,保持逻辑大小。ctx.scale(dpr, dpr)
让绘制坐标依然用逻辑尺寸计算。
4. 游戏对象与状态
我们先定义球拍、球、砖块数组等核心对象。
js
let score = 0;
let lives = 3;
let speedLevel = 1;
const paddle = {
width: 100,
height: 15,
x: WIDTH / 2 - 50,
y: HEIGHT - 30,
dx: 7
};
const ball = {
x: WIDTH / 2,
y: HEIGHT - 50,
radius: 10,
speed: 4,
dx: 4,
dy: -4
};
const BRICK_ROWS = 5;
const BRICK_COLS = 9;
const BRICK_WIDTH = 70;
const BRICK_HEIGHT = 20;
const BRICK_PADDING = 10;
const BRICK_OFFSET_TOP = 50;
const BRICK_OFFSET_LEFT = 35;
let bricks = [];
function createBricks() {
bricks = [];
for (let c = 0; c < BRICK_COLS; c++) {
bricks[c] = [];
for (let r = 0; r < BRICK_ROWS; r++) {
const brickX = c * (BRICK_WIDTH + BRICK_PADDING) + BRICK_OFFSET_LEFT;
const brickY = r * (BRICK_HEIGHT + BRICK_PADDING) + BRICK_OFFSET_TOP;
bricks[c][r] = { x: brickX, y: brickY, status: 1 };
}
}
}
createBricks();
💡 解释:
- 球拍位置固定在底部,宽 100,高 15,可左右移动。
- 球初始在球拍上方,速度
dx
/dy
控制方向。 - 砖块是一个二维数组
[列][行]
,每个砖块存储x
/y
坐标和status
(1 = 存活,0 = 已打掉)。
5. 绘制函数
js
function drawPaddle() {
ctx.fillStyle = '#0095DD';
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
function drawBall() {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = '#ff5722';
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for (let c = 0; c < BRICK_COLS; c++) {
for (let r = 0; r < BRICK_ROWS; r++) {
if (bricks[c][r].status === 1) {
ctx.fillStyle = `hsl(${r * 50}, 70%, 50%)`;
ctx.fillRect(bricks[c][r].x, bricks[c][r].y, BRICK_WIDTH, BRICK_HEIGHT);
}
}
}
}
📌 小技巧:
- 用
hsl()
根据行号生成不同颜色,让砖块更有层次感。 - 绘制顺序:砖块 → 球拍 → 球,保证视觉正确。
6. 碰撞检测
js
function collisionDetection() {
for (let c = 0; c < BRICK_COLS; c++) {
for (let r = 0; r < BRICK_ROWS; r++) {
const b = bricks[c][r];
if (b.status === 1) {
if (
ball.x > b.x && ball.x < b.x + BRICK_WIDTH &&
ball.y > b.y && ball.y < b.y + BRICK_HEIGHT
) {
ball.dy = -ball.dy;
b.status = 0;
score += 10;
if (score % 100 === 0) {
speedLevel++;
ball.speed += 0.5;
}
}
}
}
}
}
💡 原理:
- 简单的包围盒检测(AABB),判断球心是否进入砖块矩形区域。
- 命中后反转
dy
,加分,定期提速。
7. 游戏循环
js
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
drawBricks();
drawPaddle();
drawBall();
collisionDetection();
// 移动球
ball.x += ball.dx;
ball.y += ball.dy;
// 左右墙
if (ball.x + ball.radius > WIDTH || ball.x - ball.radius < 0) {
ball.dx = -ball.dx;
}
// 上墙
if (ball.y - ball.radius < 0) {
ball.dy = -ball.dy;
}
// 下边界
if (ball.y + ball.radius > HEIGHT) {
lives--;
if (!lives) {
alert('游戏结束');
document.location.reload();
} else {
resetBall();
}
}
// 球拍碰撞
if (
ball.x > paddle.x &&
ball.x < paddle.x + paddle.width &&
ball.y + ball.radius > paddle.y
) {
ball.dy = -ball.dy;
}
requestAnimationFrame(draw);
}
function resetBall() {
ball.x = WIDTH / 2;
ball.y = HEIGHT - 50;
ball.dx = 4;
ball.dy = -4;
}
draw();
📌 要点:
requestAnimationFrame
保证帧同步与性能。resetBall()
让球回到初始位置,游戏不中断。
8. 输入控制
js
document.addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') paddle.x -= paddle.dx;
if (e.key === 'ArrowRight') paddle.x += paddle.dx;
});
canvas.addEventListener('mousemove', e => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
paddle.x = mouseX - paddle.width / 2;
});
💡 说明:
- 键盘控制适合 PC,鼠标更直观,移动端可以用
touchstart
/touchmove
做。
9. 可选优化
- 球拍反弹角度控制 用击中位置计算反弹方向,让玩家可控。
js
const hit = (ball.x - paddle.x) / paddle.width;
const angle = hit * Math.PI - Math.PI / 2;
ball.dx = ball.speed * Math.cos(angle);
ball.dy = -ball.speed * Math.sin(angle);
-
防穿透 当速度过快时,可分多次小步移动并检测碰撞。
-
粒子特效 命中砖块时生成小粒子,让反馈更爽。

10. 总结
用 Trae 生成骨架,能让我们迅速进入手感调优环节,不用耗时间在 UI 布局和基础事件上。这种"AI 辅助 + 人工优化"的工作方式特别适合入门游戏开发的练习项目,也适合原型验证。
附:完整代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打砖块小游戏</title>
<style>
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--accent-color: #e74c3c;
--text-color: #333;
--bg-color: #f5f5f5;
--panel-color: #fff;
--border-radius: 8px;
--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px;
}
h1 {
margin-bottom: 15px;
color: var(--primary-color);
text-align: center;
}
.game-container {
position: relative;
width: 100%;
max-width: 800px;
display: flex;
flex-direction: column;
align-items: center;
}
.game-info {
display: flex;
justify-content: space-between;
width: 100%;
background-color: var(--panel-color);
padding: 15px 20px;
border-radius: var(--border-radius) var(--border-radius) 0 0;
box-shadow: var(--box-shadow);
font-weight: bold;
font-size: 1.1rem;
}
.canvas-container {
position: relative;
width: 100%;
background-color: #000;
box-shadow: var(--box-shadow);
overflow: hidden;
}
canvas {
display: block;
width: 100%;
height: auto;
}
.game-controls {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 20px;
width: 100%;
flex-wrap: wrap;
}
.control-btn {
padding: 10px 20px;
background-color: var(--primary-color);
color: white;
border: none;
border-radius: var(--border-radius);
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
flex: 1;
min-width: 120px;
max-width: 200px;
}
.control-btn:hover {
background-color: #2980b9;
}
.control-btn.secondary {
background-color: var(--secondary-color);
}
.control-btn.secondary:hover {
background-color: #27ae60;
}
.control-btn.danger {
background-color: var(--accent-color);
}
.control-btn.danger:hover {
background-color: #c0392b;
}
.mobile-controls {
display: none;
width: 100%;
margin-top: 20px;
}
.touch-area {
display: flex;
height: 80px;
}
.touch-left, .touch-right {
flex: 1;
background-color: rgba(52, 152, 219, 0.2);
border-radius: var(--border-radius);
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
cursor: pointer;
touch-action: none;
}
.touch-left {
margin-right: 10px;
}
.game-message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 30px 50px;
border-radius: var(--border-radius);
text-align: center;
font-size: 1.5rem;
display: none;
}
.message-title {
font-size: 2rem;
margin-bottom: 15px;
color: var(--accent-color);
}
@media (max-width: 768px) {
.mobile-controls {
display: block;
}
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<h1>打砖块小游戏</h1>
<div class="game-container">
<div class="game-info">
<div>分数: <span id="score">0</span></div>
<div>生命: <span id="lives">3</span></div>
<div>速度: <span id="speed-level">1</span></div>
</div>
<div class="canvas-container">
<canvas id="gameCanvas"></canvas>
<div class="game-message" id="gameMessage">
<div class="message-title" id="messageTitle">游戏开始</div>
<div id="messageContent">按空格键或点击开始按钮开始游戏</div>
</div>
</div>
<div class="game-controls">
<button class="control-btn" id="startBtn"><i class="fas fa-play"></i> 开始</button>
<button class="control-btn secondary" id="pauseBtn"><i class="fas fa-pause"></i> 暂停</button>
<button class="control-btn danger" id="resetBtn"><i class="fas fa-sync-alt"></i> 重置</button>
</div>
<div class="mobile-controls">
<div class="touch-area">
<div class="touch-left" id="touchLeft"><i class="fas fa-arrow-left"></i></div>
<div class="touch-right" id="touchRight"><i class="fas fa-arrow-right"></i></div>
</div>
</div>
</div>
<script>
// 获取DOM元素
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const livesElement = document.getElementById('lives');
const speedLevelElement = document.getElementById('speed-level');
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const gameMessage = document.getElementById('gameMessage');
const messageTitle = document.getElementById('messageTitle');
const messageContent = document.getElementById('messageContent');
const touchLeft = document.getElementById('touchLeft');
const touchRight = document.getElementById('touchRight');
// 游戏状态
let gameState = 'ready'; // ready, playing, paused, gameOver
let score = 0;
let lives = 3;
let speedLevel = 1;
// 游戏常量
const PADDLE_HEIGHT = 15;
const PADDLE_WIDTH = 100;
const BALL_RADIUS = 10;
const BRICK_ROWS = 5;
const BRICK_COLUMNS = 9;
const BRICK_WIDTH = 75;
const BRICK_HEIGHT = 25;
const BRICK_PADDING = 10;
const BRICK_OFFSET_TOP = 70;
const BRICK_OFFSET_LEFT = 30;
const INITIAL_BALL_SPEED = 5;
const BALL_SPEED_INCREASE = 0.2;
// 游戏对象
const paddle = {
x: 0,
y: 0,
width: PADDLE_WIDTH,
height: PADDLE_HEIGHT,
dx: 8
};
const ball = {
x: 0,
y: 0,
radius: BALL_RADIUS,
dx: 0,
dy: 0,
speed: INITIAL_BALL_SPEED
};
// 砖块数组
let bricks = [];
// 键盘状态
const keys = {
left: false,
right: false
};
// 鼠标状态
let mouseX = 0;
// 触摸状态
let isTouchingLeft = false;
let isTouchingRight = false;
// 初始化游戏
function initGame() {
// 适配高清屏幕
const dpr = window.devicePixelRatio || 1;
canvas.width = 800 * dpr;
canvas.height = 600 * dpr;
canvas.style.width = '800px';
canvas.style.height = '600px';
ctx.scale(dpr, dpr);
// 重置游戏对象位置
resetPaddleAndBall();
// 创建砖块
createBricks();
// 重置游戏状态
score = 0;
lives = 3;
speedLevel = 1;
gameState = 'ready';
// 更新UI
updateScore();
updateLives();
updateSpeedLevel();
showMessage('游戏开始', '按空格键或点击开始按钮开始游戏');
}
// 重置球拍和球的位置
function resetPaddleAndBall() {
paddle.x = (canvas.width / window.devicePixelRatio - paddle.width) / 2;
paddle.y = canvas.height / window.devicePixelRatio - paddle.height - 10;
ball.x = canvas.width / window.devicePixelRatio / 2;
ball.y = paddle.y - ball.radius;
ball.dx = 0;
ball.dy = 0;
ball.speed = INITIAL_BALL_SPEED * (1 + (speedLevel - 1) * BALL_SPEED_INCREASE);
}
// 创建砖块
function createBricks() {
bricks = [];
for (let c = 0; c < BRICK_COLUMNS; c++) {
bricks[c] = [];
for (let r = 0; r < BRICK_ROWS; r++) {
const brickX = c * (BRICK_WIDTH + BRICK_PADDING) + BRICK_OFFSET_LEFT;
const brickY = r * (BRICK_HEIGHT + BRICK_PADDING) + BRICK_OFFSET_TOP;
bricks[c][r] = {
x: brickX,
y: brickY,
status: 1, // 1表示存在,0表示被击碎
color: getBrickColor(r)
};
}
}
}
// 获取砖块颜色
function getBrickColor(row) {
const colors = ['#e74c3c', '#f39c12', '#f1c40f', '#2ecc71', '#3498db'];
return colors[row % colors.length];
}
// 绘制游戏
function drawGame() {
// 清空画布
ctx.clearRect(0, 0, canvas.width / window.devicePixelRatio, canvas.height / window.devicePixelRatio);
// 绘制砖块
drawBricks();
// 绘制球
drawBall();
// 绘制球拍
drawPaddle();
// 检测碰撞
if (gameState === 'playing') {
detectCollisions();
updateBallPosition();
updatePaddlePosition();
}
// 请求下一帧
requestAnimationFrame(drawGame);
}
// 绘制砖块
function drawBricks() {
for (let c = 0; c < BRICK_COLUMNS; c++) {
for (let r = 0; r < BRICK_ROWS; r++) {
const brick = bricks[c][r];
if (brick.status === 1) {
ctx.beginPath();
ctx.rect(brick.x, brick.y, BRICK_WIDTH, BRICK_HEIGHT);
ctx.fillStyle = brick.color;
ctx.fill();
ctx.closePath();
}
}
}
}
// 绘制球
function drawBall() {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.closePath();
}
// 绘制球拍
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddle.x, paddle.y, paddle.width, paddle.height);
ctx.fillStyle = '#3498db';
ctx.fill();
ctx.closePath();
}
// 更新球的位置
function updateBallPosition() {
// 检测墙壁碰撞
if (ball.x + ball.dx > canvas.width / window.devicePixelRatio - ball.radius || ball.x + ball.dx < ball.radius) {
ball.dx = -ball.dx;
}
if (ball.y + ball.dy < ball.radius) {
ball.dy = -ball.dy;
} else if (ball.y + ball.dy > canvas.height / window.devicePixelRatio - ball.radius - paddle.height) {
// 检测球拍碰撞
if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
// 根据碰撞位置调整反弹角度
const hitPosition = (ball.x - paddle.x) / paddle.width;
const angle = hitPosition * Math.PI - Math.PI / 2;
ball.dx = ball.speed * Math.cos(angle);
ball.dy = -ball.speed * Math.sin(angle);
} else if (ball.y + ball.dy > canvas.height / window.devicePixelRatio - ball.radius) {
// 球掉落,减少生命
lives--;
updateLives();
if (lives <= 0) {
gameOver();
} else {
resetPaddleAndBall();
gameState = 'paused';
showMessage('球掉落', '按空格键或点击开始按钮继续');
}
}
}
ball.x += ball.dx;
ball.y += ball.dy;
}
// 更新球拍位置
function updatePaddlePosition() {
// 键盘控制
if (keys.left && paddle.x > 0) {
paddle.x -= paddle.dx;
} else if (keys.right && paddle.x < canvas.width / window.devicePixelRatio - paddle.width) {
paddle.x += paddle.dx;
}
// 鼠标控制
if (mouseX !== 0) {
const relativeX = mouseX * (canvas.width / window.devicePixelRatio) / canvas.clientWidth;
if (relativeX > paddle.width / 2 && relativeX < canvas.width / window.devicePixelRatio - paddle.width / 2) {
paddle.x = relativeX - paddle.width / 2;
}
}
// 触摸控制
if (isTouchingLeft && paddle.x > 0) {
paddle.x -= paddle.dx;
} else if (isTouchingRight && paddle.x < canvas.width / window.devicePixelRatio - paddle.width) {
paddle.x += paddle.dx;
}
}
// 检测碰撞
function detectCollisions() {
let bricksInRow = 0;
let allBricksGone = true;
for (let c = 0; c < BRICK_COLUMNS; c++) {
for (let r = 0; r < BRICK_ROWS; r++) {
const brick = bricks[c][r];
if (brick.status === 1) {
allBricksGone = false;
bricksInRow++;
// 检测球与砖块的碰撞
if (
ball.x + ball.radius > brick.x &&
ball.x - ball.radius < brick.x + BRICK_WIDTH &&
ball.y + ball.radius > brick.y &&
ball.y - ball.radius < brick.y + BRICK_HEIGHT
) {
// 根据碰撞方向调整球的速度
const overlapLeft = ball.x + ball.radius - brick.x;
const overlapRight = brick.x + BRICK_WIDTH - (ball.x - ball.radius);
const overlapTop = ball.y + ball.radius - brick.y;
const overlapBottom = brick.y + BRICK_HEIGHT - (ball.y - ball.radius);
const minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
if (minOverlap === overlapLeft || minOverlap === overlapRight) {
ball.dx = -ball.dx;
} else {
ball.dy = -ball.dy;
}
// 击碎砖块
brick.status = 0;
score += 10;
updateScore();
// 检查是否需要增加速度
checkSpeedIncrease();
}
}
}
// 如果一行砖块全部被击碎,增加速度
if (bricksInRow === 0 && r === BRICK_ROWS - 1) {
increaseSpeed();
}
bricksInRow = 0;
}
// 如果所有砖块都被击碎,重新创建砖块并增加速度
if (allBricksGone) {
createBricks();
increaseSpeed();
}
}
// 检查是否需要增加速度
function checkSpeedIncrease() {
// 每得到100分增加一次速度
if (score % 100 === 0 && score !== 0) {
increaseSpeed();
}
}
// 增加速度
function increaseSpeed() {
speedLevel++;
ball.speed = INITIAL_BALL_SPEED * (1 + (speedLevel - 1) * BALL_SPEED_INCREASE);
updateSpeedLevel();
}
// 更新分数
function updateScore() {
scoreElement.textContent = score;
}
// 更新生命
function updateLives() {
livesElement.textContent = lives;
}
// 更新速度等级
function updateSpeedLevel() {
speedLevelElement.textContent = speedLevel;
}
// 显示消息
function showMessage(title, content) {
messageTitle.textContent = title;
messageContent.textContent = content;
gameMessage.style.display = 'block';
}
// 隐藏消息
function hideMessage() {
gameMessage.style.display = 'none';
}
// 开始游戏
function startGame() {
if (gameState === 'ready' || gameState === 'paused') {
gameState = 'playing';
hideMessage();
// 如果是刚准备好的游戏,设置球的初始速度
if (ball.dx === 0 && ball.dy === 0) {
ball.dx = ball.speed * 0.5;
ball.dy = -ball.speed;
}
}
}
// 暂停游戏
function pauseGame() {
if (gameState === 'playing') {
gameState = 'paused';
showMessage('游戏暂停', '按空格键或点击开始按钮继续');
}
}
// 重置游戏
function resetGame() {
initGame();
}
// 游戏结束
function gameOver() {
gameState = 'gameOver';
showMessage('游戏结束', `最终得分: ${score}\n按空格键或点击重置按钮重新开始`);
}
// 事件监听
function setupEventListeners() {
// 键盘控制
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') {
keys.left = true;
} else if (e.key === 'ArrowRight') {
keys.right = true;
} else if (e.key === ' ') {
if (gameState === 'ready' || gameState === 'paused') {
startGame();
} else if (gameState === 'playing') {
pauseGame();
} else if (gameState === 'gameOver') {
resetGame();
}
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft') {
keys.left = false;
} else if (e.key === 'ArrowRight') {
keys.right = false;
}
});
// 鼠标控制
canvas.addEventListener('mousemove', (e) => {
mouseX = e.clientX - canvas.getBoundingClientRect().left;
});
// 按钮控制
startBtn.addEventListener('click', startGame);
pauseBtn.addEventListener('click', pauseGame);
resetBtn.addEventListener('click', resetGame);
// 触摸控制
touchLeft.addEventListener('touchstart', (e) => {
e.preventDefault();
isTouchingLeft = true;
});
touchLeft.addEventListener('touchend', (e) => {
e.preventDefault();
isTouchingLeft = false;
});
touchRight.addEventListener('touchstart', (e) => {
e.preventDefault();
isTouchingRight = true;
});
touchRight.addEventListener('touchend', (e) => {
e.preventDefault();
isTouchingRight = false;
});
// 窗口大小变化时重新调整画布
window.addEventListener('resize', () => {
// 重新初始化游戏以适应新窗口大小
const currentState = gameState;
initGame();
gameState = currentState;
if (gameState !== 'ready' && gameState !== 'gameOver') {
hideMessage();
}
});
}
// 启动游戏
function start() {
initGame();
setupEventListeners();
drawGame();
}
// 开始游戏
start();
</script>
</body>
</html>