如何实现受击时生命值条减少?(附p5.js代码求助)
问题修复方案
核心问题分析
- 碰撞检测时机错误:在
spawnBullets_e中,子弹刚生成就检测碰撞,此时子弹位于敌方位置,不可能接触玩家,碰撞逻辑永远不会触发。 - 变量覆盖导致遗漏检测:连续创建两个
bullet_e时,变量仅保存最后一个子弹的引用,第一个子弹的碰撞完全没被检测。 - 销毁方法错误:使用了不存在的
destroyed()方法,p5.play中正确的销毁方法是destroy()。 - 未正确调用碰撞检测函数:
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
相关产品推荐
相关产品推荐

