You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现受击时生命值条减少?(附p5.js代码求助)

问题修复方案

核心问题分析

  1. 碰撞检测时机错误:在spawnBullets_e中,子弹刚生成就检测碰撞,此时子弹位于敌方位置,不可能接触玩家,碰撞逻辑永远不会触发。
  2. 变量覆盖导致遗漏检测:连续创建两个bullet_e时,变量仅保存最后一个子弹的引用,第一个子弹的碰撞完全没被检测。
  3. 销毁方法错误:使用了不存在的destroyed()方法,p5.play中正确的销毁方法是destroy()。
  4. 未正确调用碰撞检测函数:checkCollisions函数逻辑有误且未在draw循环中执行。

具体修改步骤

  • 将敌方子弹存入数组,方便遍历检测所有子弹与玩家的碰撞
  • 在draw循环中调用碰撞检测逻辑,确保每一帧都检查所有子弹
  • 修正生命值修改逻辑,确保是health -= 5而非直接赋值为-5
  • 使用正确的精灵销毁方法

修改后的完整代码

var bg;
var player, playerImg;
var bullets_e = []; // 改为数组存储所有敌方子弹
var bulletImg;
var missile, missile_e, missileImg, missile_e_img;
var fireBall, fireBall_img;

var enemy, enemyImg;

var trig1, trig2;

var health = 100;
var maxHealth = 100;

function preload() {
  playerImg = loadImage("Assets/TBM-3.png");
  bulletImg = loadImage("Assets/Bullets_01.png");
  missileImg = loadImage("Assets/missile_01.png");
  missile_e_img = loadImage("Assets/missile_02.png");
  fireBall_img = loadImage("Assets/fireBall_01.png");

  bg = loadImage("Assets/Backgrounds/BG_07.png");

  enemyImg = loadImage("Assets/Enemy_FighterJet_Ba.png");
}

function setup() {
  createCanvas(windowWidth, windowHeight);

  player = createSprite(width / 2, height / 2 + 270);
  player.addImage("player", playerImg);
  player.scale = 0.5;

  enemy = createSprite(windowWidth / 2 + 600, windowHeight / 2 - 300);
  enemy.addImage("enemy", enemyImg);
  enemy.scale = 0.6;

  trig1 = createSprite(windowWidth, windowHeight - 650);
  trig1.scale = 0.7;
  trig1.visible = false;

  trig2 = createSprite(windowWidth / 100, windowHeight - 650);
  trig2.scale = 0.7;
  trig2.visible = false;
}

function draw() {
  background(bg, windowWidth, windowHeight);

  playerController();
  enemyController();
  spawnBullets_e();
  checkCollisions(); // 调用碰撞检测
  updateHealth();

  drawSprites();
}

function playerController() {
  if (keyDown(RIGHT_ARROW)) {
    player.x += 8;
  }
  if (keyDown(LEFT_ARROW)) {
    player.x -= 8;
  }
  if (keyDown(UP_ARROW)) {
    player.y -= 6;
  }
  if (keyDown(DOWN_ARROW)) {
    player.y += 6;
  }

  if (keyWentDown("space")) {
    missile = createSprite(player.x + 39, player.y - 29);
    missile.addImage("missile", missileImg);
    missile.scale = 0.08;
    missile.velocityY = -8;
    missile.lifetime = 80;

    missile = createSprite(player.x - 39, player.y - 29);
    missile.addImage("missile", missileImg);
    missile.scale = 0.08;
    missile.velocityY = -8;
    missile.lifetime = 80;
  }
}

function spawnBullets_p() {
  if (frameCount % 4 === 0) {
    let bullet_p = createSprite(player.x + 37, player.y - 29);
    bullet_p.addImage("bullet", bulletImg);
    bullet_p.scale = 0.09;
    bullet_p.velocityY = -30;
    bullet_p.lifetime = 30;

    bullet_p = createSprite(player.x - 37, player.y - 29);
    bullet_p.addImage("bullet", bulletImg);
    bullet_p.scale = 0.09;
    bullet_p.velocityY = -30;
    bullet_p.lifetime = 30;
  }
}

function spawnBullets_e() {
  if (frameCount % 6 === 0) {
    // 创建右侧子弹并存入数组
    let bullet = createSprite(enemy.x + 33, enemy.y + 68);
    bullet.addImage("bullet", bulletImg);
    bullet.scale = 0.09;
    bullet.velocityY = 30;
    bullet.lifetime = 30;
    bullets_e.push(bullet);

    // 创建左侧子弹并存入数组
    bullet = createSprite(enemy.x - 33, enemy.y + 68);
    bullet.addImage("bullet", bulletImg);
    bullet.scale = 0.09;
    bullet.velocityY = 30;
    bullet.lifetime = 30;
    bullets_e.push(bullet);
  }

  // 清理过期子弹,避免数组无限增长
  bullets_e = bullets_e.filter(bullet => !bullet.removed);
}

function enemyController() {
  if (enemy.isTouching(trig1)) {
    enemy.velocityX = -4;
  }
  if (enemy.isTouching(trig2)) {
    enemy.velocityX = 4;
  }

  if (frameCount % 100 === 0) {
    missile_e = createSprite(enemy.x + 50, enemy.y + 68);
    missile_e.addImage("missile2", missile_e_img);
    missile_e.scale = 0.08;
    missile_e.velocityY = +8;
    missile_e.lifetime = 80;

    missile_e = createSprite(enemy.x - 50, enemy.y + 68);
    missile_e.addImage("missile2", missile_e_img);
    missile_e.scale = 0.08;
    missile_e.velocityY = +8;
    missile_e.lifetime = 80;
  }

  if (frameCount % 300 === 0) {
    fireBall = createSprite(enemy.x, enemy.y + 30);
    fireBall.addImage("fireBall", fireBall_img);
    fireBall.scale = 0.09;
    fireBall.velocityY = 5;
    fireBall.lifetime = 90;
  }
}

function checkCollisions() {
  // 遍历所有敌方子弹检测碰撞
  for (let i = bullets_e.length - 1; i >= 0; i--) {
    let bullet = bullets_e[i];
    if (bullet.isTouching(player)) {
      health = Math.max(0, health - 5); // 生命值最低为0
      bullet.destroy(); // 销毁子弹
      bullets_e.splice(i, 1); // 从数组中移除
    }
  }
}

function updateHealth() {
  stroke(0);
  strokeWeight(4);
  noFill();
  rect(10, 10, 200, 20);

  noStroke();
  fill(255, 0, 0);
  rect(10, 10, map(health, 0, maxHealth, 0, 200), 20);
}

额外优化说明

  • 新增了生命值下限控制(Math.max(0, health -5)),避免生命值变为负数
  • 添加了数组清理逻辑,移除已销毁的子弹,防止内存占用过高
  • 变量声明使用let替代未声明的全局变量,符合JavaScript规范

内容的提问来源于stack exchange,提问作者PassionateCoder257

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:30:46