|
|
你好!你提供的代码里有一些“乱码”其实是因为JavaScript中数组没有写完整,还有一些地方拼写和逻辑有点小问题。我帮你把这些地方改成正确的代码,并且用文字描述每个部分的意思,好让你更容易懂。
我先给你一个修正好的版本,然后再讲解关键点:
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <title>飞机大战小游戏</title>
- <style>
- body {
- margin: 0;
- overflow: hidden;
- background: black;
- color: white;
- font-family: "微软雅黑", sans-serif;
- }
- #gameCanvas {
- background: #111;
- display: block;
- margin: auto;
- border: 2px solid white;
- }
- #scoreboard {
- text-align: center;
- margin-top: 10px;
- }
- </style>
- </head>
- <body>
- <canvas id="gameCanvas" width="400" height="600"></canvas>
- <div id="scoreboard">
- 血量:<span id="hp">3</span> 分数:<span id="score">0</span>
- </div>
- <p style="text-align:center; color:#ccc;">
- 操作提示:按A键向左移动,D键向右移动,空格键发射子弹。
- </p>
- <script>
- const canvas = document.getElementById("gameCanvas");
- const ctx = canvas.getContext("2d");
- const planeWidth = 40;
- const planeHeight = 40;
- let planeX = (canvas.width - planeWidth) / 2;
- const planeY = canvas.height - planeHeight - 10;
- let hp = 3;
- let score = 0;
- // 敌机数组,开始为空
- let enemies = [];
- // 子弹数组,开始为空
- let bullets = [];
- // 控制左右移动
- let moveLeft = false;
- let moveRight = false;
- // 监听键盘按下
- window.addEventListener("keydown", function(e) {
- if (e.key === "a" || e.key === "A") moveLeft = true;
- if (e.key === "d" || e.key === "D") moveRight = true;
- });
- // 监听键盘松开
- window.addEventListener("keyup", function(e) {
- if (e.key === "a" || e.key === "A") moveLeft = false;
- if (e.key === "d" || e.key === "D") moveRight = false;
- if (e.key === " ") shoot();
- });
- // 画飞机(用三角形表示)
- function drawPlane() {
- ctx.fillStyle = "lightblue";
- ctx.beginPath();
- ctx.moveTo(planeX + planeWidth / 2, planeY);
- ctx.lineTo(planeX, planeY + planeHeight);
- ctx.lineTo(planeX + planeWidth, planeY + planeHeight);
- ctx.closePath();
- ctx.fill();
- }
- // 生成敌机,随机x位置
- function createEnemy() {
- let x = Math.random() * (canvas.width - 30);
- enemies.push({ x: x, y: -30, width: 30, height: 30 });
- }
- // 画敌机(红色矩形)
- function drawEnemies() {
- ctx.fillStyle = "red";
- enemies.forEach(enemy => {
- ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
- });
- }
- // 移动敌机,向下移2像素
- function moveEnemies() {
- enemies.forEach(enemy => {
- enemy.y += 2;
- });
- // 删除超出画面底部的敌机
- enemies = enemies.filter(enemy => enemy.y < canvas.height);
- }
- // 发射子弹,子弹初始位置在飞机头部中间
- function shoot() {
- bullets.push({ x: planeX + planeWidth / 2 - 2.5, y: planeY, width: 5, height: 10 });
- }
- // 画子弹(黄色矩形)
- function drawBullets() {
- ctx.fillStyle = "yellow";
- bullets.forEach(bullet => {
- ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
- });
- }
- // 移动子弹,向上移5像素
- function moveBullets() {
- bullets.forEach(bullet => {
- bullet.y -= 5;
- });
- // 删除飞出画面的子弹
- bullets = bullets.filter(bullet => bullet.y + bullet.height > 0);
- }
- // 碰撞检测两个矩形是否相交
- function isColliding(rect1, rect2) {
- return !(
- rect1.x > rect2.x + rect2.width ||
- rect1.x + rect1.width < rect2.x ||
- rect1.y > rect2.y + rect2.height ||
- rect1.y + rect1.height < rect2.y
- );
- }
- // 检查子弹和敌机碰撞
- function checkBulletEnemyCollision() {
- for (let i = bullets.length - 1; i >= 0; i--) {
- let b = bullets[i];
- for (let j = enemies.length - 1; j >= 0; j--) {
- let e = enemies[j];
- if (isColliding(b, e)) {
- // 子弹和敌机都消失
- bullets.splice(i, 1);
- enemies.splice(j, 1);
- score++;
- updateScore();
- break; // 跳出内层循环,继续检查下一个子弹
- }
- }
- }
- }
- // 检查敌机和飞机碰撞
- function checkEnemyPlaneCollision() {
- let planeRect = { x: planeX, y: planeY, width: planeWidth, height: planeHeight };
- for (let i = enemies.length - 1; i >= 0; i--) {
- let e = enemies[i];
- if (isColliding(e, planeRect)) {
- enemies.splice(i, 1); // 敌机消失
- hp--;
- updateHP();
- if (hp <= 0) {
- alert("游戏结束!你的得分是:" + score);
- document.location.reload(); // 重新加载页面,重玩游戏
- }
- }
- }
- }
- // 更新血量显示
- function updateHP() {
- document.getElementById("hp").textContent = hp;
- }
- // 更新分数显示
- function updateScore() {
- document.getElementById("score").textContent = score;
- }
- // 游戏主循环
- function gameLoop() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- // 根据按键移动飞机
- if (moveLeft && planeX > 0) planeX -= 5;
- if (moveRight && planeX < canvas.width - planeWidth) planeX += 5;
- drawPlane();
- // 控制敌机出现概率(大约每30帧一个)
- if (Math.random() < 0.03) createEnemy();
- moveEnemies();
- drawEnemies();
- moveBullets();
- drawBullets();
- checkBulletEnemyCollision();
- checkEnemyPlaneCollision();
- requestAnimationFrame(gameLoop);
- }
- // 初始化血量和分数
- updateHP();
- updateScore();
- gameLoop();
- </script>
- </body>
- </html>
复制代码
---
### 这个代码做了什么?
1. **画布和飞机**
- 画布大小是400x600像素,背景是暗色的。
- 飞机用一个蓝色的三角形表示,会在画布底部中间。
- 用变量 `planeX` 和 `planeY` 控制位置。
2. **敌机**
- 敌人是红色的30x30像素的方块,从屏幕顶端随机位置往下飞。
- 敌机会慢慢往下移动,如果飞出画面就消失。
3. **子弹**
- 按空格键可以发射子弹,黄色小长方形从飞机头部向上飞。
- 子弹飞出画面会消失。
4. **移动控制**
- 按“A”键飞机向左移动,按“D”键向右移动。
- 用事件监听处理按键按下和松开。
5. **碰撞检测**
- 判断敌机和子弹是否碰撞,碰撞时子弹和敌机都会消失,分数加一。
- 判断敌机和飞机是否碰撞,碰撞时敌机消失,血量减少。血量变为0游戏结束。
6. **显示信息**
- 屏幕上方显示血量和分数,会随时更新。
7. **游戏循环**
- 利用 `requestAnimationFrame` 每帧刷新画面,移动角色,检测碰撞。
---
### 为什么之前的代码看起来像乱码?
- 数组写法要用方括号 [],你写成了 `let enemies = ;`,少了 []
- 遍历数组时,要用索引取元素,比如 `let b = bullets`
- 有些变量比较少写全,比如 `if (hp 0)` 应该写成 `if (hp <= 0)`
- 语法不完整电脑就不会运行,所以才会有错误
---
如果你想自己试一下,可以复制我上面这段代码,保存成 `.html` 文件,用浏览器打开,就能玩这个小游戏啦!如果还有哪里不明白,我可以再帮你解释哦~ |
|