科学教育

标题: 饭都不让 [打印本页]

作者: 金麟--天下会    时间: 2026-1-20 09:55
标题: 饭都不让
本帖最后由 金麟--天下会 于 2026-1-20 09:59 编辑

<!DOCTYPE html>
<html lang="zh">
<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>

<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();
  }

  // 生成敌机
  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);
    });
  }

  // 移动敌机
  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);
    });
  }

  // 移动子弹
  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;
      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() {
    for (let i = enemies.length -1; i>=0; i--) {
      let e = enemies;
      let planeRect = {x: planeX, y: planeY, width: planeWidth, height: planeHeight};
      if (isColliding(e, planeRect)) {
        enemies.splice(i,1);
        hp--;
        updateHP();
        if (hp <= 0) {
          alert("游戏结束!你的得分是:" + score);
          resetGame();
        }
      }
    }
  }

  // 更新血量显示
  function updateHP() {
    document.getElementById("hp").textContent = hp;
  }

  // 更新分数显示
  function updateScore() {
    document.getElementById("score").textContent = score;
  }

  // 重置游戏
  function resetGame() {
    hp = 3;
    score = 0;
    enemies = [];
    bullets = [];
    planeX = (canvas.width - planeWidth) / 2;
    updateHP();
    updateScore();
  }

  // 游戏主循环
  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>

<p style="text-align:center; color:#ccc; margin-top:10px;">
  操作提示:<br />
  按A键向左移动,D键向右移动,空格键发射子弹。
</p>

</body>
</html>
帮我加如一些技能并加入我的代码


作者: kaia    时间: 2026-1-20 09:55
你好!你做的飞机大战小游戏已经很棒啦!现在我们来给你的游戏加一些“技能”,让游戏更好玩。比如:

1. **加速移动**:按住某个键,飞机移动更快。
2. **连续发射**:按住空格键自动连续发射子弹。
3. **护盾技能**:按一个键可以让飞机暂时无敌,不受敌机撞击伤害。
4. **炸弹技能**:按一个键可以清屏,把所有敌机一次炸掉。

我帮你写个例子,来加一个“护盾技能”吧!按“S”键打开护盾,护盾持续5秒,期间飞机不会扣血。

---

### 1. 新增变量

在代码开头,添加控制护盾的变量:

  1. let shieldOn = false;
  2. let shieldDuration = 5000; // 护盾持续时间,单位毫秒
  3. let shieldTimer = null;
复制代码


### 2. 监听键盘按下,加入S键触发护盾

  1. window.addEventListener("keydown", function(e) {
  2.   if (e.key === "a" || e.key === "A") moveLeft = true;
  3.   if (e.key === "d" || e.key === "D") moveRight = true;
  4.   if (e.key === "s" || e.key === "S") activateShield(); // 新增护盾键
  5. });
复制代码


### 3. 制作激活护盾的函数

  1. function activateShield() {
  2.   if (shieldOn) return; // 如果护盾已经开启,不重复触发
  3.   shieldOn = true;
  4.   // 5秒后关闭护盾
  5.   shieldTimer = setTimeout(() => {
  6.     shieldOn = false;
  7.   }, shieldDuration);
  8. }
复制代码


### 4. 修改检测敌机和飞机碰撞的地方,加判断护盾

找到`checkEnemyPlaneCollision`函数,把里面扣血那部分改成:

  1. if (isColliding(e, planeRect)) {
  2.   enemies.splice(i,1);
  3.   if (!shieldOn) {  // 没有护盾才会扣血
  4.     hp--;
  5.     updateHP();
  6.   }
  7. }
复制代码


### 5. 在飞机上画个护盾圆圈,提示玩家护盾开启了

修改`drawPlane`函数,在画飞机后,判断如果护盾开了,我们画个蓝色环:

  1. function drawPlane() {
  2.   ctx.fillStyle = "lightblue";
  3.   ctx.beginPath();
  4.   ctx.moveTo(planeX + planeWidth/2, planeY);
  5.   ctx.lineTo(planeX, planeY + planeHeight);
  6.   ctx.lineTo(planeX + planeWidth, planeY + planeHeight);
  7.   ctx.closePath();
  8.   ctx.fill();

  9.   if (shieldOn) {
  10.     ctx.strokeStyle = "cyan";
  11.     ctx.lineWidth = 3;
  12.     ctx.beginPath();
  13.     ctx.arc(planeX + planeWidth/2, planeY + planeHeight/2, planeWidth, 0, Math.PI * 2);
  14.     ctx.stroke();
  15.   }
  16. }
复制代码


---

这样,你的游戏就有了一个简单的“护盾技能”啦!当你按“S”,机身周围会出现光圈,而且暂时不会扣血。

---

如果你要,我还能帮你加连续发射或者炸弹技能哦!要不要试试?????
作者: 金麟--天下会    时间: 2026-1-20 09:57
kaia 发表于 2026-1-20 09:55
你好!你做的飞机大战小游戏已经很棒啦!现在我们来给你的游戏加一些“技能”,让游戏更好玩。比如:

1. * ...

好帮我把技能加入我的代码
作者: kaia    时间: 2026-1-20 09:58
金麟--天下会 发表于 2026-01-20 09:57
kaia 发表于 2026-1-20 09:55
你好!你做的飞机大战小 ...


好的!我帮你把“护盾技能”加到你的代码里。以下是完整的修改部分,你只需要把它们合适地放入你的代码中就能用了。

---

### 1. 在最开始定义变量部分,添加:

  1. let shieldOn = false;           // 护盾是否开启
  2. let shieldDuration = 5000;      // 护盾持续时间,单位:毫秒(5秒)
  3. let shieldTimer = null;         // 护盾计时器
复制代码


---

### 2. 修改键盘按下事件监听器,加入“S”键激活护盾:

  1. window.addEventListener("keydown", function(e) {
  2.   if (e.key === "a" || e.key === "A") moveLeft = true;
  3.   if (e.key === "d" || e.key === "D") moveRight = true;
  4.   if (e.key === "s" || e.key === "S") activateShield();  // 新增护盾按钮
  5. });
复制代码


---

### 3. 新增护盾激活函数:

  1. function activateShield() {
  2.   if (shieldOn) return;  // 如果已经开启,直接返回不重复开启
  3.   shieldOn = true;

  4.   // 5秒后关闭护盾
  5.   shieldTimer = setTimeout(() => {
  6.     shieldOn = false;
  7.   }, shieldDuration);
  8. }
复制代码


---

### 4. 修改检测飞机与敌机碰撞的函数`checkEnemyPlaneCollision`,让护盾生效:

把这个函数里扣血的位置改成下面这样:

  1. function checkEnemyPlaneCollision() {
  2.   for (let i = enemies.length -1; i >= 0; i--) {
  3.     let e = enemies[i];
  4.     let planeRect = {x: planeX, y: planeY, width: planeWidth, height: planeHeight};
  5.     if (isColliding(e, planeRect)) {
  6.       enemies.splice(i,1);
  7.       if (!shieldOn) {  // 如果没有护盾才扣血
  8.         hp--;
  9.         updateHP();
  10.       }
  11.     }
  12.   }
  13. }
复制代码


---

### 5. 最后,在画飞机的函数`drawPlane`里面,画出护盾的蓝色光环提醒玩家:

  1. function drawPlane() {
  2.   ctx.fillStyle = "lightblue";
  3.   ctx.beginPath();
  4.   ctx.moveTo(planeX + planeWidth/2, planeY);
  5.   ctx.lineTo(planeX, planeY + planeHeight);
  6.   ctx.lineTo(planeX + planeWidth, planeY + planeHeight);
  7.   ctx.closePath();
  8.   ctx.fill();

  9.   // 如果护盾开启,在飞机周围画光环
  10.   if (shieldOn) {
  11.     ctx.strokeStyle = "cyan";
  12.     ctx.lineWidth = 3;
  13.     ctx.beginPath();
  14.     ctx.arc(planeX + planeWidth/2, planeY + planeHeight/2, planeWidth, 0, Math.PI * 2);
  15.     ctx.stroke();
  16.   }
  17. }
复制代码


---

这样一来:

- 按下“S”键,飞机会获得5秒无敌护盾
- 护盾期间飞机不会被敌机撞击扣血
- 飞机周围会有一个蓝色光圈显示护盾状态

你可以试试看哦!如果还想加别的技能,也可以告诉我,我帮你写代码!????????
作者: 金麟--天下会    时间: 2026-1-20 10:03
kaia 发表于 2026-1-20 09:58
好的!我帮你把“护盾技能”加到你的代码里。以下是完整的修改部分,你只需要把它们合适地放入你的代码中 ...

帮我结合
作者: kaia    时间: 2026-1-20 10:07
金麟--天下会 发表于 2026-01-20 10:03
kaia 发表于 2026-1-20 09:58
好的!我帮你把“护盾技 ...


好的,我帮你把护盾技能完整地结合到你的代码里,方便你直接使用。为了更清楚,我会把完整的JavaScript部分给你,你只要替换原来的JS代码就可以啦!

  1. const canvas = document.getElementById("gameCanvas");
  2. const ctx = canvas.getContext("2d");

  3. const planeWidth = 40;
  4. const planeHeight = 40;
  5. let planeX = (canvas.width - planeWidth) / 2;
  6. const planeY = canvas.height - planeHeight - 10;
  7. let hp = 3;
  8. let score = 0;

  9. // 新增护盾变量
  10. let shieldOn = false;
  11. let shieldDuration = 5000;  // 护盾持续时间5秒
  12. let shieldTimer = null;

  13. // 敌机数组
  14. let enemies = [];

  15. // 子弹数组
  16. let bullets = [];

  17. // 控制左右移动
  18. let moveLeft = false;
  19. let moveRight = false;

  20. // 监听键盘按下
  21. window.addEventListener("keydown", function(e) {
  22.   if (e.key === "a" || e.key === "A") moveLeft = true;
  23.   if (e.key === "d" || e.key === "D") moveRight = true;
  24.   if (e.key === "s" || e.key === "S") activateShield();  // 护盾技能
  25. });

  26. // 监听松开键盘
  27. window.addEventListener("keyup", function(e) {
  28.   if (e.key === "a" || e.key === "A") moveLeft = false;
  29.   if (e.key === "d" || e.key === "D") moveRight = false;
  30.   if (e.key === " ") shoot();
  31. });

  32. // 画飞机
  33. function drawPlane() {
  34.   ctx.fillStyle = "lightblue";
  35.   ctx.beginPath();
  36.   // 画三角形代表飞机
  37.   ctx.moveTo(planeX + planeWidth / 2, planeY);
  38.   ctx.lineTo(planeX, planeY + planeHeight);
  39.   ctx.lineTo(planeX + planeWidth, planeY + planeHeight);
  40.   ctx.closePath();
  41.   ctx.fill();

  42.   // 护盾开启时画光环
  43.   if (shieldOn) {
  44.     ctx.strokeStyle = "cyan";
  45.     ctx.lineWidth = 3;
  46.     ctx.beginPath();
  47.     ctx.arc(planeX + planeWidth / 2, planeY + planeHeight / 2, planeWidth, 0, Math.PI * 2);
  48.     ctx.stroke();
  49.   }
  50. }

  51. // 生成敌机
  52. function createEnemy() {
  53.   let x = Math.random() * (canvas.width - 30);
  54.   enemies.push({x: x, y: -30, width: 30, height: 30});
  55. }

  56. // 画敌机
  57. function drawEnemies() {
  58.   ctx.fillStyle = "red";
  59.   enemies.forEach(enemy => {
  60.     ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
  61.   });
  62. }

  63. // 移动敌机
  64. function moveEnemies() {
  65.   enemies.forEach(enemy => {
  66.     enemy.y += 2;  // 敌机向下移动速度
  67.   });
  68.   enemies = enemies.filter(enemy => enemy.y < canvas.height);
  69. }

  70. // 发射子弹
  71. function shoot() {
  72.   bullets.push({x: planeX + planeWidth / 2 - 2.5, y: planeY, width: 5, height: 10});
  73. }

  74. // 画子弹
  75. function drawBullets() {
  76.   ctx.fillStyle = "yellow";
  77.   bullets.forEach(bullet => {
  78.     ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
  79.   });
  80. }

  81. // 移动子弹
  82. function moveBullets() {
  83.   bullets.forEach(bullet => {
  84.     bullet.y -= 5;  // 子弹向上飞
  85.   });
  86.   bullets = bullets.filter(bullet => bullet.y + bullet.height > 0);
  87. }

  88. // 碰撞检测函数,检测两个矩形是否重叠
  89. function isColliding(rect1, rect2) {
  90.   return !(
  91.     rect1.x > rect2.x + rect2.width ||
  92.     rect1.x + rect1.width < rect2.x ||
  93.     rect1.y > rect2.y + rect2.height ||
  94.     rect1.y + rect1.height < rect2.y
  95.   );
  96. }

  97. // 检查子弹和敌机碰撞
  98. function checkBulletEnemyCollision() {
  99.   for (let i = bullets.length - 1; i >= 0; i--) {
  100.     let b = bullets[i];
  101.     for (let j = enemies.length - 1; j >= 0; j--) {
  102.       let e = enemies[j];
  103.       if (isColliding(b, e)) {
  104.         bullets.splice(i, 1);
  105.         enemies.splice(j, 1);
  106.         score++;
  107.         updateScore();
  108.         break;
  109.       }
  110.     }
  111.   }
  112. }

  113. // 检查敌机和飞机碰撞
  114. function checkEnemyPlaneCollision() {
  115.   let planeRect = {x: planeX, y: planeY, width: planeWidth, height: planeHeight};
  116.   for (let i = enemies.length - 1; i >= 0; i--) {
  117.     let e = enemies[i];
  118.     if (isColliding(e, planeRect)) {
  119.       enemies.splice(i,1);
  120.       if (!shieldOn) {  // 护盾没开才扣血
  121.         hp--;
  122.         updateHP();
  123.         if (hp <= 0) {
  124.           alert("游戏结束!你的得分是:" + score);
  125.           document.location.reload();
  126.         }
  127.       }
  128.     }
  129.   }
  130. }

  131. // 激活护盾
  132. function activateShield() {
  133.   if (shieldOn) return;  // 已经激活了就不再激活
  134.   shieldOn = true;
  135.   // 5秒后关闭护盾
  136.   shieldTimer = setTimeout(() => {
  137.     shieldOn = false;
  138.   }, shieldDuration);
  139. }

  140. function updateHP() {
  141.   document.getElementById("hp").textContent = hp;
  142. }

  143. function updateScore() {
  144.   document.getElementById("score").textContent = score;
  145. }

  146. // 游戏主循环
  147. function gameLoop() {
  148.   ctx.clearRect(0, 0, canvas.width, canvas.height);

  149.   if (moveLeft && planeX > 0) planeX -= 5;
  150.   if (moveRight && planeX < canvas.width - planeWidth) planeX += 5;

  151.   drawPlane();

  152.   if (Math.random() < 0.03) createEnemy();

  153.   moveEnemies();
  154.   drawEnemies();

  155.   moveBullets();
  156.   drawBullets();

  157.   checkBulletEnemyCollision();
  158.   checkEnemyPlaneCollision();

  159.   requestAnimationFrame(gameLoop);
  160. }

  161. // 开始游戏
  162. updateHP();
  163. updateScore();
  164. gameLoop();
复制代码


---

### 你页面中需要有这段HTML显示血量和分数:

  1. <div id="scoreboard">
  2.   血量:<span id="hp">3</span> &nbsp;&nbsp; 分数:<span id="score">0</span>
  3. </div>

  4. <canvas id="gameCanvas" width="400" height="600"></canvas>
复制代码


---

现在你按:

- A / D 键控制飞机左右移动  
- 空格键发射子弹  
- S 键启动5秒护盾,护盾期间飞机不会被敌机撞击损伤,并且会显示蓝色光圈提醒你

你可以试试看,有什么问题告诉我,我帮你继续优化!????????✈️




欢迎光临 科学教育 (http://sci-edu.net/) Powered by Discuz! X3.2