
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录
- [【魔法森林冒险】11/14 战斗系统(二):多波战斗与BOSS战⚜️](#【魔法森林冒险】11/14 战斗系统(二):多波战斗与BOSS战⚜️)
-
- [📝 文章摘要](#📝 文章摘要)
- [⚜️ 一、多波战斗与BOSS战的核心定位:游戏的「难度高峰」](#⚜️ 一、多波战斗与BOSS战的核心定位:游戏的「难度高峰」)
- [🔧 二、核心代码拆解(一):多波战斗系统 - WaveBattleSystem类](#🔧 二、核心代码拆解(一):多波战斗系统 - WaveBattleSystem类)
-
- [2.1 完整核心代码(未修改,拆分讲解)](#2.1 完整核心代码(未修改,拆分讲解))
- [2.2 关键知识点讲解💡](#2.2 关键知识点讲解💡)
- [🔧 三、核心代码拆解(二):Allen+Lia联合作战逻辑](#🔧 三、核心代码拆解(二):Allen+Lia联合作战逻辑)
-
- [3.1 仇恨分担机制](#3.1 仇恨分担机制)
- [3.2 Lia辅助攻击/治疗](#3.2 Lia辅助攻击/治疗)
- [🧪 四、调试示例:多波战斗+BOSS战完整流程](#🧪 四、调试示例:多波战斗+BOSS战完整流程)
-
- [4.1 调试输出结果(核心片段)](#4.1 调试输出结果(核心片段))
- [🚨 五、多波战斗&BOSS战设计的「新手坑」与最佳实践](#🚨 五、多波战斗&BOSS战设计的「新手坑」与最佳实践)
- [📌 知识回顾](#📌 知识回顾)
- [✍️ 写在最后](#✍️ 写在最后)

【魔法森林冒险】11/14 战斗系统(二):多波战斗与BOSS战⚜️
📝 文章摘要
| 内容维度 | 详情说明 |
|---|---|
| 核心摘要 | 本文是「魔法森林冒险」Java项目系列第十一篇,聚焦战斗系统的进阶玩法------多波战斗与BOSS战。从黑暗洞穴的多波敌人战斗流程设计,到树灵BOSS的特殊战斗规则(阶段回血/技能释放),再到Allen+Lia的联合作战逻辑(仇恨分担/技能配合),带你吃透高难度战斗的核心设计思路与代码实现。 |
| 阅读时长 | 17分钟 |
| 适合人群 | 1. Java新手:想掌握「多波循环+状态机+角色协作」的实战应用;2. 游戏开发入门者:想理解BOSS战的阶段设计、多波敌人的难度梯度控制;3. 项目复刻者:想复刻完整的高难度战斗流程,包括多波敌人刷新、BOSS阶段技能、联合作战奖励等核心功能。 |
| 阅读重点 | 1. 多波战斗的流程框架(波次初始化→敌人刷新→波次结算→下一波);2. 树灵BOSS的状态机设计(普通阶段/狂暴阶段/回血机制);3. Allen+Lia联合作战逻辑(仇恨分担/辅助治疗/组合技能);4. BOSS战的结算规则(稀有道具掉落/高额经验奖励)。 |
⚜️ 一、多波战斗与BOSS战的核心定位:游戏的「难度高峰」
在「魔法森林冒险」中,多波战斗和BOSS战是战斗系统的进阶玩法,也是游戏难度和趣味性的核心体现:
✅ 难度梯度化 → 多波敌人逐波强化(数量/攻击力提升),BOSS战分阶段(普通→狂暴),符合玩家成长曲线;
✅ 协作深度化 → Allen主输出+Lia辅助治疗/仇恨分担,联合作战策略性拉满;
✅ 奖励稀缺化 → BOSS战掉落稀有道具(魔法花/高级卷轴),多波战斗结算额外经验,驱动玩家挑战;
✅ 规则特殊化 → BOSS拥有专属技能(范围攻击/回血)、多波敌人有刷新规则,区别于基础回合制战斗。
多波战斗与BOSS战的核心是「波次循环+状态机+角色协作」:以波次为单位驱动多波战斗,以状态机控制BOSS行为,以角色状态联动实现协作,接下来拆解核心代码,吃透这个设计思路!
🔧 二、核心代码拆解(一):多波战斗系统 - WaveBattleSystem类
2.1 完整核心代码(未修改,拆分讲解)
java
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
/**
* 多波战斗系统核心类:WaveBattleSystem
* 继承基础战斗系统,实现黑暗洞穴多波敌人战斗逻辑
*/
public class WaveBattleSystem extends BattleSystem {
// ========== 多波战斗核心属性 ==========
// 总波次
private final int totalWaves;
// 当前波次
private int currentWave;
// 敌人列表(每波可能有多个敌人)
private List<Enemy> currentWaveEnemies;
// 波次奖励(逐波提升)
private final int baseWaveReward = 10;
// 随机数生成器
private Random random;
// ========== 构造方法:初始化多波战斗 ==========
public WaveBattleSystem(Allen allen, Lia lia, int totalWaves) {
// 基础战斗系统初始化(传入第一个敌人占位)
super(allen, lia, new Goblin());
this.totalWaves = totalWaves;
this.currentWave = 0;
this.currentWaveEnemies = new ArrayList<>();
this.random = new Random();
// 多波战斗初始化提示
System.out.println("\n🌋 进入黑暗洞穴 - 多波战斗模式!");
System.out.println("🎯 总波次:" + totalWaves + " | 每波敌人强度逐次提升!");
System.out.println("🏆 通关奖励:稀有道具 + 高额经验值!");
}
// ========== 核心方法:启动多波战斗 ==========
@Override
public void startBattle() {
// 多波战斗主循环
while (currentWave < totalWaves) {
// 1. 刷新当前波次敌人
spawnWaveEnemies();
// 2. 波次战斗初始化
System.out.println("\n=====================================");
System.out.println("🌊 第" + (currentWave + 1) + "/" + totalWaves + "波战斗开始!");
System.out.println("👹 本波敌人:" + getEnemiesDesc());
System.out.println("=====================================");
// 3. 进行当前波次战斗
boolean waveVictory = fightCurrentWave();
// 4. 波次结算
if (waveVictory) {
waveSettlement();
currentWave++;
// 5. 波次间休整(可使用道具/查看状态)
if (currentWave < totalWaves) {
interWaveRest();
}
} else {
// 波次失败,整体战斗失败
System.out.println("\n💀 第" + (currentWave + 1) + "波战斗失败!");
super.setBattleOver(true);
super.setVictory(false);
break;
}
}
// 6. 多波战斗最终结算
finalSettlement();
}
// ========== 辅助方法:刷新当前波次敌人 ==========
private void spawnWaveEnemies() {
// 清空上一波敌人
currentWaveEnemies.clear();
// 波次越强,敌人数量/等级越高
int enemyCount = 1 + currentWave; // 第1波1个,第2波2个...(最多3个)
enemyCount = Math.min(enemyCount, 3);
for (int i = 0; i < enemyCount; i++) {
Enemy enemy;
// 波次≤2:仅哥布林;波次>2:混合哥布林+精灵;波次≥5:精英敌人
if (currentWave <= 2) {
// 普通/首领哥布林(概率随波次提升)
boolean isLeader = random.nextDouble() < (0.1 * currentWave);
enemy = isLeader ? new Goblin(true) : new Goblin();
} else {
// 混合敌人:60%哥布林(含首领),40%精灵
if (random.nextDouble() < 0.6) {
boolean isLeader = random.nextDouble() < (0.2 * currentWave);
enemy = isLeader ? new Goblin(true) : new Goblin();
} else {
enemy = new Elf();
}
}
// 敌人属性强化(每波提升10%攻击力/血量)
强化敌人属性(enemy);
currentWaveEnemies.add(enemy);
}
}
// ========== 辅助方法:敌人属性强化 ==========
private void 强化敌人属性(Enemy enemy) {
double enhanceRate = 1 + (currentWave * 0.1);
enemy.setMaxHp((int) (enemy.getMaxHp() * enhanceRate));
enemy.setCurrentHp(enemy.getMaxHp());
enemy.setBaseAttack((int) (enemy.getBaseAttack() * enhanceRate));
System.out.println("⚠️ " + enemy.getName() + "属性强化" + (currentWave * 10) + "%!");
}
// ========== 辅助方法:获取敌人描述 ==========
private String getEnemiesDesc() {
StringBuilder desc = new StringBuilder();
for (int i = 0; i < currentWaveEnemies.size(); i++) {
desc.append(currentWaveEnemies.get(i).getName());
if (i < currentWaveEnemies.size() - 1) {
desc.append(" + ");
}
}
return desc.toString();
}
// ========== 核心方法:当前波次战斗 ==========
private boolean fightCurrentWave() {
// 波次战斗主循环:直到所有敌人被击败或Allen死亡
while (true) {
// 1. 检查Allen是否存活
if (super.getAllen().getHp() <= 0) {
return false;
}
// 2. 检查当前波次所有敌人是否被击败
if (areAllEnemiesDead()) {
return true;
}
// 3. 玩家回合(选择攻击目标)
playerTurnWithTarget();
// 4. 敌人回合(所有存活敌人依次攻击)
enemiesTurn();
}
}
// ========== 辅助方法:玩家回合(可选攻击目标) ==========
private void playerTurnWithTarget() {
System.out.println("\n👉 艾伦的行动回合!");
super.showActionMenu();
int choice = super.getValidChoice(1, 4);
switch (choice) {
case 1:
// 攻击:选择目标
attackWithTarget();
break;
case 2:
// 使用道具
super.useItem();
break;
case 3:
// 逃跑(多波战斗中逃跑视为失败)
System.out.println("❌ 多波战斗中无法逃跑!");
playerTurnWithTarget();
break;
case 4:
// 查看状态
showWaveStatus();
playerTurnWithTarget();
break;
}
}
// ========== 辅助方法:选择攻击目标 ==========
private void attackWithTarget() {
// 展示存活敌人列表
System.out.println("\n🎯 选择攻击目标:");
List<Enemy> aliveEnemies = getAliveEnemies();
for (int i = 0; i < aliveEnemies.size(); i++) {
Enemy enemy = aliveEnemies.get(i);
System.out.println((i + 1) + ". " + enemy.getName() + " | HP:" + enemy.getCurrentHp() + "/" + enemy.getMaxHp());
}
// 选择目标
int targetChoice = super.getValidChoice(1, aliveEnemies.size());
Enemy targetEnemy = aliveEnemies.get(targetChoice - 1);
// 执行攻击
super.allenAttack(targetEnemy);
// 触发Lia辅助攻击(随机攻击一个存活敌人)
triggerLiaRandomHelpAttack();
}
// ========== 辅助方法:敌人回合 ==========
private void enemiesTurn() {
System.out.println("\n👹 敌人行动回合!");
List<Enemy> aliveEnemies = getAliveEnemies();
for (Enemy enemy : aliveEnemies) {
// 检查敌人是否逃跑
if (enemy.isFleeing()) {
if (random.nextDouble() <= 0.7) {
System.out.println("🏃 " + enemy.getName() + "成功逃跑!");
continue;
}
}
// 敌人攻击(优先攻击仇恨目标)
if (enemy.getHateTarget() == 1 && super.getLia().getTrustLevel() >= 60) {
// 攻击Lia
attackLia(enemy);
} else {
// 攻击Allen
enemy.attackEnemy(super.getAllen());
}
// 检查Allen/Lia是否存活
if (super.getAllen().getHp() <= 0 || super.getLia().getHp() <= 0) {
return;
}
}
}
// ========== 辅助方法:敌人攻击Lia ==========
private void attackLia(Enemy enemy) {
int damage = enemy.getBaseAttack();
Lia lia = super.getLia();
lia.setHp(lia.getHp() - damage);
System.out.println("👹 " + enemy.getName() + "攻击莉娅!造成" + damage + "点伤害!");
System.out.println("❤️ 莉娅当前HP:" + lia.getHp() + "/" + lia.getMaxHp());
// Lia血量过低时,Allen可选择保护
if (lia.getHp() <= 20) {
System.out.println("\n⚠️ 莉娅血量危急!是否保护莉娅?(1. 是 2. 否)");
int protectChoice = super.getValidChoice(1, 2);
if (protectChoice == 1) {
// 保护:承受50%伤害
int protectDamage = (int) (damage * 0.5);
super.getAllen().setHp(super.getAllen().getHp() - protectDamage);
lia.setHp(lia.getHp() + damage - protectDamage);
System.out.println("🛡️ 艾伦保护莉娅!承受" + protectDamage + "点伤害!");
}
}
}
// ========== 辅助方法:获取存活敌人 ==========
private List<Enemy> getAliveEnemies() {
List<Enemy> aliveEnemies = new ArrayList<>();
for (Enemy enemy : currentWaveEnemies) {
if (enemy.getCurrentHp() > 0) {
aliveEnemies.add(enemy);
}
}
return aliveEnemies;
}
// ========== 辅助方法:检查所有敌人是否死亡 ==========
private boolean areAllEnemiesDead() {
return getAliveEnemies().isEmpty();
}
// ========== 辅助方法:展示波次状态 ==========
private void showWaveStatus() {
System.out.println("\n📊 第" + (currentWave + 1) + "波战斗状态:");
super.showStatus();
System.out.println("👹 存活敌人数量:" + getAliveEnemies().size() + "/" + currentWaveEnemies.size());
}
// ========== 辅助方法:触发Lia随机辅助攻击 ==========
private void triggerLiaRandomHelpAttack() {
Lia lia = super.getLia();
if (lia.getTrustLevel() >= 50 && random.nextDouble() <= (0.3 + (lia.getTrustLevel() - 50) * 0.01)) {
List<Enemy> aliveEnemies = getAliveEnemies();
if (!aliveEnemies.isEmpty()) {
// 随机选择一个存活敌人攻击
Enemy randomEnemy = aliveEnemies.get(random.nextInt(aliveEnemies.size()));
int helpDamage = lia.helpAllenFight(randomEnemy);
System.out.println("🤝 莉娅随机辅助攻击!对" + randomEnemy.getName() + "造成" + helpDamage + "点伤害!");
}
}
}
// ========== 核心方法:波次结算 ==========
private void waveSettlement() {
System.out.println("\n🎉 第" + (currentWave + 1) + "波战斗胜利!");
// 波次奖励:金币+经验(逐波提升)
int waveGold = baseWaveReward * (currentWave + 1);
int waveExp = 15 * (currentWave + 1);
Allen allen = super.getAllen();
allen.setGold(allen.getGold() + waveGold);
allen.addExperience(waveExp);
System.out.println("💰 获得" + waveGold + "金币!当前金币:" + allen.getGold());
System.out.println("📚 获得" + waveExp + "经验值!当前等级:" + allen.getLevel());
// 低概率掉落道具
if (random.nextDouble() <= 0.2) {
Item rewardItem = new HealPotion();
allen.pickItem(rewardItem);
System.out.println("🎁 额外奖励:" + rewardItem.getName() + "!");
}
}
// ========== 核心方法:波次间休整 ==========
private void interWaveRest() {
System.out.println("\n🛌 波次间休整!");
System.out.println("1. ❤️ 莉娅为你恢复10点HP(信任度≥50)");
System.out.println("2. 📊 查看状态");
System.out.println("3. ⏭️ 继续下一波战斗");
int choice = super.getValidChoice(1, 3);
switch (choice) {
case 1:
// Lia治疗
if (super.getLia().getTrustLevel() >= 50) {
Allen allen = super.getAllen();
allen.setHp(allen.getHp() + 10);
System.out.println("❤️ 莉娅为你恢复10点HP!当前HP:" + allen.getHp() + "/" + allen.getMaxHp());
} else {
System.out.println("❌ 莉娅信任度不足,无法治疗!");
}
interWaveRest();
break;
case 2:
showWaveStatus();
interWaveRest();
break;
case 3:
// 继续下一波
break;
}
}
// ========== 核心方法:多波战斗最终结算 ==========
private void finalSettlement() {
System.out.println("\n=====================================");
System.out.println("🏁 多波战斗结算!");
System.out.println("=====================================");
if (super.isVictory()) {
System.out.println("🎉 恭喜!通关所有" + totalWaves + "波战斗!");
// 最终奖励:稀有道具(魔法花)
Item rareItem = new MagicFlower();
super.getAllen().pickItem(rareItem);
System.out.println("🎁 通关奖励:" + rareItem.getName() + "(提升莉娅信任度20点)!");
// 高额经验奖励
super.getAllen().addExperience(50);
System.out.println("📚 额外获得50点经验值!");
} else {
System.out.println("💀 多波战斗失败!");
// 失败惩罚:损失20%金币
int loseGold = (int) (super.getAllen().getGold() * 0.2);
super.getAllen().setGold(Math.max(super.getAllen().getGold() - loseGold, 0));
System.out.println("💰 损失" + loseGold + "金币!剩余金币:" + super.getAllen().getGold());
}
}
// ========== 辅助方法:展示波次状态 ==========
private void showWaveStatus() {
System.out.println("\n📊 第" + (currentWave + 1) + "波战斗状态:");
System.out.println("【艾伦】HP:" + super.getAllen().getHp() + "/" + super.getAllen().getMaxHp() +
" | 攻击力:" + super.getAllen().getAttackPower() +
" | 金币:" + super.getAllen().getGold());
System.out.println("【莉娅】信任度:" + super.getLia().getTrustLevel() + "/100" +
" | HP:" + super.getLia().getHp() + "/" + super.getLia().getMaxHp());
System.out.println("【当前波次敌人】:");
for (Enemy enemy : currentWaveEnemies) {
System.out.println(" - " + enemy.getName() + " | HP:" + enemy.getCurrentHp() + "/" + enemy.getMaxHp() +
" | 攻击力:" + enemy.getBaseAttack());
}
}
// ========== 辅助方法:获取存活敌人 ==========
private List<Enemy> getAliveEnemies() {
List<Enemy> alive = new ArrayList<>();
for (Enemy enemy : currentWaveEnemies) {
if (enemy.getCurrentHp() > 0) {
alive.add(enemy);
}
}
return alive;
}
// ========== 辅助方法:检查所有敌人是否死亡 ==========
private boolean areAllEnemiesDead() {
return getAliveEnemies().isEmpty();
}
}
/**
* BOSS战斗系统:TreeSpiritBattleSystem
* 实现树灵BOSS的特殊战斗规则
*/
class TreeSpiritBattleSystem extends BattleSystem {
// BOSS阶段:0-普通,1-狂暴(HP<50%)
private int bossPhase;
// BOSS回血冷却回合
private int healCooldown;
// 随机数生成器
private Random random;
public TreeSpiritBattleSystem(Allen allen, Lia lia) {
// 初始化树灵BOSS
TreeSpirit treeSpirit = new TreeSpirit();
super(allen, lia, treeSpirit);
this.bossPhase = 0;
this.healCooldown = 0;
this.random = new Random();
System.out.println("\n🌳 遭遇森林守护者 - 树灵BOSS!");
System.out.println("⚠️ BOSS特性:HP<50%进入狂暴状态 | 每5回合尝试回血 | 范围攻击!");
}
@Override
public void startBattle() {
int round = 1;
while (!super.isBattleOver()) {
System.out.println("\n🔄 BOSS战第" + round + "回合!");
// 1. 检查BOSS阶段
checkBossPhase();
// 2. 玩家回合
super.playerTurn();
if (super.isBattleOver()) break;
// 3. BOSS回合(特殊技能)
bossTurn(round);
if (super.isBattleOver()) break;
// 4. 冷却回合更新
updateCooldown();
round++;
}
// BOSS战结算
bossBattleSettlement();
}
// ========== 辅助方法:检查BOSS阶段 ==========
private void checkBossPhase() {
TreeSpirit boss = (TreeSpirit) super.getEnemy();
if (boss.getCurrentHp() <= boss.getMaxHp() * 0.5 && bossPhase == 0) {
// 进入狂暴阶段
bossPhase = 1;
boss.setBaseAttack((int) (boss.getBaseAttack() * 1.5));
System.out.println("🔥 树灵进入狂暴状态!攻击力提升50%!");
}
}
// ========== 核心方法:BOSS回合 ==========
private void bossTurn(int round) {
TreeSpirit boss = (TreeSpirit) super.getEnemy();
System.out.println("\n🌳 树灵BOSS行动回合!");
// 1. 回血判定(冷却结束且HP<80%)
if (healCooldown <= 0 && boss.getCurrentHp() < boss.getMaxHp() * 0.8) {
int healValue = boss.heal();
System.out.println("🌱 树灵使用自然之力回血!恢复" + healValue + "点HP!");
healCooldown = 5; // 重置冷却
return;
}
// 2. 技能判定(狂暴阶段有概率释放范围攻击)
if (bossPhase == 1 && random.nextDouble() <= 0.3) {
// 范围攻击:同时攻击Allen和Lia
int rangeDamage = (int) (boss.getBaseAttack() * 0.8);
System.out.println("🌪️ 树灵释放范围攻击!");
// 攻击Allen
super.getAllen().setHp(super.getAllen().getHp() - rangeDamage);
System.out.println("💥 对艾伦造成" + rangeDamage + "点伤害!HP:" + super.getAllen().getHp() + "/" + super.getAllen().getMaxHp());
// 攻击Lia
super.getLia().setHp(super.getLia().getHp() - rangeDamage);
System.out.println("💥 对莉娅造成" + rangeDamage + "点伤害!HP:" + super.getLia().getHp() + "/" + super.getLia().getMaxHp());
// 检查是否战败
if (super.getAllen().getHp() <= 0 || super.getLia().getHp() <= 0) {
super.setBattleOver(true);
super.setVictory(false);
}
return;
}
// 3. 普通攻击
boss.attackEnemy(super.getAllen());
// 检查Allen是否存活
if (super.getAllen().getHp() <= 0) {
super.setBattleOver(true);
super.setVictory(false);
}
}
// ========== 辅助方法:更新冷却回合 ==========
private void updateCooldown() {
if (healCooldown > 0) {
healCooldown--;
System.out.println("⏳ 树灵回血冷却剩余:" + healCooldown + "回合");
}
}
// ========== 核心方法:BOSS战结算 ==========
private void bossBattleSettlement() {
System.out.println("\n=====================================");
System.out.println("🏁 树灵BOSS战结算!");
System.out.println("=====================================");
if (super.isVictory()) {
System.out.println("🎉 恭喜!击败树灵BOSS!");
// BOSS专属奖励
Allen allen = super.getAllen();
// 高额金币
allen.setGold(allen.getGold() + 100);
System.out.println("💰 获得100金币奖励!");
// 稀有魔法卷轴
Item scroll = new AdvancedMagicScroll();
allen.pickItem(scroll);
System.out.println("🎁 获得稀有道具:" + scroll.getName() + "!");
// 大量经验
allen.addExperience(100);
System.out.println("📚 获得100点经验值!");
// Lia信任度满值
super.getLia().setTrustLevel(100);
System.out.println("❤️ 莉娅信任度提升至100!解锁全部辅助技能!");
} else {
System.out.println("💀 BOSS战失败!");
// 惩罚:损失50%金币
int loseGold = (int) (super.getAllen().getGold() * 0.5);
super.getAllen().setGold(Math.max(super.getAllen().getGold() - loseGold, 0));
System.out.println("💰 损失" + loseGold + "金币!剩余金币:" + super.getAllen().getGold());
}
}
}
// ========== 依赖类补充(保证代码可运行) ==========
// 基础战斗系统父类(简化版)
class BattleSystem {
private Allen allen;
private Lia lia;
private Enemy enemy;
protected boolean isBattleOver;
protected boolean isVictory;
private Scanner scanner;
public BattleSystem(Allen allen, Lia lia, Enemy enemy) {
this.allen = allen;
this.lia = lia;
this.enemy = enemy;
this.isBattleOver = false;
this.isVictory = false;
this.scanner = new Scanner(System.in);
}
public void startBattle() {}
protected void showActionMenu() {
System.out.println("1. ⚔️ 攻击");
System.out.println("2. 🎒 使用道具");
System.out.println("3. 🏃 尝试逃跑");
System.out.println("4. 📊 查看状态");
System.out.print("输入数字选择:");
}
protected int getValidChoice(int min, int max) {
int choice = -1;
while (true) {
if (scanner.hasNextInt()) {
choice = scanner.nextInt();
if (choice >= min && choice <= max) break;
else System.out.print("❌ 输入无效!请输入" + min + "-" + max + "之间的数字:");
} else {
scanner.next();
System.out.print("❌ 输入无效!请输入数字:");
}
}
return choice;
}
protected void useItem() {
System.out.println("\n🎒 背包:");
List<Item> backpack = allen.getBackpack();
if (backpack.isEmpty()) {
System.out.println("📦 背包为空!");
return;
}
for (int i = 0; i < backpack.size(); i++) {
System.out.println((i+1) + ". " + backpack.get(i).getName() + " - " + backpack.get(i).getEffectDesc());
}
System.out.println((backpack.size()+1) + ". ❌ 取消");
int choice = getValidChoice(1, backpack.size()+1);
if (choice == backpack.size()+1) return;
Item item = backpack.get(choice-1);
item.use(allen);
System.out.println("✅ 使用" + item.getName() + "成功!");
if (item.isConsumable()) backpack.remove(choice-1);
}
protected void allenAttack(Enemy target) {
int baseDamage = Math.max(allen.getAttackPower() - getEnemyDefense(target), 1);
double critChance = Math.random();
int finalDamage = baseDamage;
if (critChance <= 0.15) {
finalDamage = (int) (baseDamage * 1.5);
System.out.println("💥 暴击!");
}
target.takeDamage(finalDamage);
System.out.println("⚔️ 对" + target.getName() + "造成" + finalDamage + "点伤害!");
}
private int getEnemyDefense(Enemy enemy) {
return enemy instanceof Goblin ? 3 : 5;
}
protected void showStatus() {
System.out.println("\n📊 战斗状态:");
System.out.println("【艾伦】HP:" + allen.getHp() + "/" + allen.getMaxHp());
System.out.println("【莉娅】信任度:" + lia.getTrustLevel() + "/100");
System.out.println("【" + enemy.getName() + "】HP:" + enemy.getCurrentHp() + "/" + enemy.getMaxHp());
}
public Allen getAllen() { return allen; }
public Lia getLia() { return lia; }
public Enemy getEnemy() { return enemy; }
public boolean isVictory() { return isVictory; }
public void setBattleOver(boolean over) { this.isBattleOver = over; }
public void setVictory(boolean victory) { this.isVictory = victory; }
}
// 树灵BOSS类
class TreeSpirit extends Enemy {
public TreeSpirit() {
super("树灵守护者", "森林的古老BOSS", 200, 20);
}
// BOSS回血方法
public int heal() {
int healValue = 30;
this.setCurrentHp(Math.min(this.getCurrentHp() + healValue, this.getMaxHp()));
return healValue;
}
@Override
public boolean takeDamage(int damage) {
// BOSS有10%概率减免50%伤害
if (Math.random() <= 0.1) {
damage = (int) (damage * 0.5);
System.out.println("🌳 树灵的自然护甲减免50%伤害!");
}
this.setCurrentHp(this.getCurrentHp() - damage);
if (this.getCurrentHp() <= 0) {
this.setCurrentHp(0);
return false;
}
return true;
}
}
// 高级魔法卷轴道具
class AdvancedMagicScroll extends Item {
public AdvancedMagicScroll() {
super("高级魔法卷轴", "提升20点攻击力,持续3回合", true, "稀有");
}
@Override
public boolean use(Person target) {
if (target instanceof Allen) {
Allen allen = (Allen) target;
allen.setAttackPower(allen.getAttackPower() + 20);
System.out.println("⚡ 攻击力提升20点!持续3回合!");
return true;
}
return false;
}
@Override
public String getEffectDesc() {
return "提升20点攻击力,持续3回合";
}
}
// 魔法花道具
class MagicFlower extends Item {
public MagicFlower() {
super("魔法花", "提升莉娅信任度20点", false, "稀有");
}
@Override
public boolean use(Person target) {
if (target instanceof Lia) {
Lia lia = (Lia) target;
lia.setTrustLevel(lia.getTrustLevel() + 20);
System.out.println("❤️ 莉娅信任度+20!当前:" + lia.getTrustLevel() + "/100");
return true;
}
return false;
}
@Override
public String getEffectDesc() {
return "提升莉娅信任度20点";
}
}
// 其他基础类(简化版,保证代码可运行)
abstract class Enemy extends Figure {
protected int currentHp;
protected int maxHp;
protected int baseAttack;
protected boolean isFleeing;
protected int hateTarget;
public Enemy(String name, String description, int maxHp, int baseAttack) {
super(name, description);
this.maxHp = maxHp;
this.currentHp = maxHp;
this.baseAttack = baseAttack;
this.isFleeing = false;
this.hateTarget = 0;
}
public abstract boolean takeDamage(int damage);
public void attackEnemy(Person target) {
target.setHp(target.getHp() - this.baseAttack);
System.out.println("👹 " + this.name + "对" + target.getName() + "造成" + this.baseAttack + "点伤害!");
}
public int getCurrentHp() { return currentHp; }
public void setCurrentHp(int hp) { this.currentHp = hp; }
public int getMaxHp() { return maxHp; }
public void setMaxHp(int hp) { this.maxHp = hp; }
public int getBaseAttack() { return baseAttack; }
public void setBaseAttack(int attack) { this.baseAttack = attack; }
public boolean isFleeing() { return isFleeing; }
public int getHateTarget() { return hateTarget; }
}
class Goblin extends Enemy {
public Goblin() {
super("普通哥布林", "低智商小怪", 50, 10);
}
public Goblin(boolean isLeader) {
super(isLeader ? "哥布林首领" : "普通哥布林",
isLeader ? "哥布林头目" : "低智商小怪",
isLeader ? 80 : 50,
isLeader ? 15 : 10);
}
@Override
public boolean takeDamage(int damage) {
this.currentHp -= damage;
return this.currentHp > 0;
}
}
class Elf extends Enemy {
public Elf() {
super("精灵弓箭手", "魔法弓箭手", 60, 12);
}
@Override
public boolean takeDamage(int damage) {
if (Math.random() <= 0.15) {
System.out.println("💨 精灵闪避攻击!");
return true;
}
this.currentHp -= damage;
return this.currentHp > 0;
}
}
abstract class Person extends Figure {
protected int hp;
protected int maxHp;
protected int gold;
public Person(String name, String description) {
super(name, description);
}
public int getHp() { return hp; }
public void setHp(int hp) { this.hp = Math.max(hp, 0); }
public int getMaxHp() { return maxHp; }
public int getGold() { return gold; }
public void setGold(int gold) { this.gold = gold; }
}
class Allen extends Person {
private int attackPower;
private int skillLevel;
private int experience;
private int level;
private List<Item> backpack;
public Allen() {
super("艾伦", "冒险者");
this.maxHp = 100;
this.hp = 100;
this.attackPower = 15;
this.skillLevel = 1;
this.experience = 0;
this.level = 1;
this.backpack = new ArrayList<>();
}
public int getAttackPower() { return attackPower; }
public void setAttackPower(int power) { this.attackPower = power; }
public int getSkillLevel() { return skillLevel; }
public List<Item> getBackpack() { return backpack; }
public void pickItem(Item item) { backpack.add(item); }
public int getLevel() { return level; }
public void addExperience(int exp) {
this.experience += exp;
if (this.experience >= 100) {
this.level++;
this.experience -= 100;
this.attackPower += 2;
this.maxHp += 10;
this.hp = this.maxHp;
System.out.println("🎉 升级到" + level + "级!");
}
}
}
class Lia extends Person {
private int trustLevel;
public Lia() {
super("莉娅", "精灵盟友");
this.maxHp = 80;
this.hp = 80;
this.trustLevel = 0;
}
public int getTrustLevel() { return trustLevel; }
public void setTrustLevel(int level) { this.trustLevel = Math.min(level, 100); }
public int helpAllenFight(Enemy enemy) {
int damage = 10;
enemy.takeDamage(damage);
return damage;
}
}
abstract class Item {
protected String name;
protected String description;
protected boolean isConsumable;
public Item(String name, String description, boolean isConsumable, String rarity) {
this.name = name;
this.description = description;
this.isConsumable = isConsumable;
}
public abstract boolean use(Person target);
public abstract String getEffectDesc();
public String getName() { return name; }
public boolean isConsumable() { return isConsumable; }
}
class HealPotion extends Item {
public HealPotion() {
super("普通治疗药水", "恢复20点HP", true, "普通");
}
@Override
public boolean use(Person target) {
target.setHp(target.getHp() + 20);
return true;
}
@Override
public String getEffectDesc() {
return "恢复20点HP";
}
}
abstract class Figure {
protected String name;
protected String description;
public Figure(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() { return name; }
}
// ========== 测试类 ==========
class WaveAndBossBattleTest {
public static void main(String[] args) {
// 1. 创建角色
Allen allen = new Allen();
Lia lia = new Lia();
lia.setTrustLevel(70);
allen.pickItem(new HealPotion());
// 2. 多波战斗测试(3波)
WaveBattleSystem waveBattle = new WaveBattleSystem(allen, lia, 3);
waveBattle.startBattle();
// 3. BOSS战测试
TreeSpiritBattleSystem bossBattle = new TreeSpiritBattleSystem(allen, lia);
bossBattle.startBattle();
}
}
2.2 关键知识点讲解💡
(1)多波战斗的核心流程
是
是
否
否
多波战斗初始化
当前波次=0
当前波次 < 总波次?
刷新当前波次敌人(属性强化)
当前波次战斗
波次胜利?
波次结算(奖励)
波次间休整
当前波次+1
多波战斗失败结算
多波战斗胜利最终结算
战斗结束
- 敌人刷新阶段:每波敌人数量/属性随波次提升(10%攻击力/血量加成);
- 波次战斗阶段:玩家可选择攻击目标,所有存活敌人依次攻击;
- 波次结算阶段:奖励逐波提升,波次间可休整(Lia治疗/查看状态);
- 最终结算阶段:通关所有波次获得稀有道具,失败则损失金币。
👉 新手重点:多波战斗的核心是「波次循环+敌人强化+阶段奖励」,通过逐波提升难度增加挑战性。
(2)BOSS战的状态机设计
HP < 50%
无(不可逆)
基础攻击 | 每5回合回血
攻击力+50% | 30%概率范围攻击 | 每5回合回血
- 阶段触发:BOSS血量低于50%时进入狂暴阶段,攻击力永久提升50%;
- 技能规则:普通阶段每5回合尝试回血,狂暴阶段额外有30%概率释放范围攻击;
- 防御特性:BOSS有10%概率减免50%伤害,区别于普通敌人。
👉 新手重点:BOSS战的核心是「状态机+特殊技能」,通过阶段变化和专属技能体现BOSS的独特性。
🔧 三、核心代码拆解(二):Allen+Lia联合作战逻辑
3.1 仇恨分担机制
java
private void enemiesTurn() {
for (Enemy enemy : aliveEnemies) {
// 仇恨目标为1且Lia信任度≥60 → 攻击Lia
if (enemy.getHateTarget() == 1 && super.getLia().getTrustLevel() >= 60) {
attackLia(enemy);
} else {
// 否则攻击Allen
enemy.attackEnemy(super.getAllen());
}
}
}
- 触发条件:Lia信任度≥60时,敌人仇恨目标可切换为Lia;
- 协作价值:Lia分担伤害,保护Allen的输出环境,体现角色协作的策略性;
- 保护机制:Lia血量≤20时,Allen可选择保护(承受50%伤害)。
3.2 Lia辅助攻击/治疗
java
// 随机辅助攻击
private void triggerLiaRandomHelpAttack() {
if (lia.getTrustLevel() >= 50 && random.nextDouble() <= (0.3 + (lia.getTrustLevel() - 50) * 0.01)) {
Enemy randomEnemy = aliveEnemies.get(random.nextInt(aliveEnemies.size()));
int helpDamage = lia.helpAllenFight(randomEnemy);
System.out.println("🤝 莉娅随机辅助攻击!造成" + helpDamage + "点伤害!");
}
}
// 波次间治疗
private void interWaveRest() {
if (lia.getTrustLevel() >= 50) {
allen.setHp(allen.getHp() + 10);
System.out.println("❤️ 莉娅为你恢复10点HP!");
}
}
- 辅助攻击:信任度越高,辅助概率越高(50→30%,100→80%),随机攻击一个敌人;
- 波次间治疗:信任度≥50时,Allen可选择让Lia恢复10点HP,提升续航能力;
- BOSS战奖励:击败树灵后Lia信任度直接拉满,解锁全部辅助技能。
🧪 四、调试示例:多波战斗+BOSS战完整流程
4.1 调试输出结果(核心片段)
🌋 进入黑暗洞穴 - 多波战斗模式!
🎯 总波次:3 | 每波敌人强度逐次提升!
🏆 通关奖励:稀有道具 + 高额经验值!
=====================================
🌊 第1/3波战斗开始!
👹 本波敌人:普通哥布林
=====================================
⚠️ 普通哥布林属性强化0%!
👉 艾伦的行动回合!
1. ⚔️ 攻击
2. 🎒 使用道具
3. 🏃 尝试逃跑
4. 📊 查看状态
输入数字选择:1
🎯 选择攻击目标:
1. 普通哥布林 | HP:50/50
输入数字选择:1
💥 暴击!
💥 普通哥布林受到18点伤害!当前HP:32/50
⚔️ 对普通哥布林造成18点伤害!
👹 敌人行动回合!
👹 普通哥布林对艾伦造成10点伤害!
👉 艾伦的行动回合!
...
🎉 第1波战斗胜利!
💰 获得10金币!当前金币:10
📚 获得15经验值!当前等级:1
🛌 波次间休整!
1. ❤️ 莉娅为你恢复10点HP(信任度≥50)
2. 📊 查看状态
3. ⏭️ 继续下一波战斗
输入数字选择:1
❤️ 莉娅为你恢复10点HP!当前HP:90/100
=====================================
🌊 第2/3波战斗开始!
👹 本波敌人:普通哥布林 + 精灵弓箭手
=====================================
⚠️ 普通哥布林属性强化10%!
⚠️ 精灵弓箭手属性强化10%!
...
🎉 第3波战斗胜利!
💰 获得30金币!当前金币:55
📚 获得45经验值!当前等级:1
=====================================
🏁 多波战斗结算!
=====================================
🎉 恭喜!通关所有3波战斗!
🎁 通关奖励:魔法花(提升莉娅信任度20点)!
📚 额外获得50点经验值!
🌳 遭遇森林守护者 - 树灵BOSS!
⚠️ BOSS特性:HP<50%进入狂暴状态 | 每5回合尝试回血 | 范围攻击!
🔄 BOSS战第1回合!
👉 艾伦的行动回合!
1. ⚔️ 攻击
2. 🎒 使用道具
3. 🏃 尝试逃跑
4. 📊 查看状态
输入数字选择:1
💥 暴击!
🌳 树灵的自然护甲减免50%伤害!
💥 树灵守护者受到18点伤害!当前HP:182/200
⚔️ 对树灵守护者造成18点伤害!
🌳 树灵BOSS行动回合!
👹 树灵守护者对艾伦造成20点伤害!
🔄 BOSS战第6回合!
🔥 树灵进入狂暴状态!攻击力提升50%!
👉 艾伦的行动回合!
...
🌳 树灵BOSS行动回合!
🌱 树灵使用自然之力回血!恢复30点HP!
🔄 BOSS战第10回合!
🌳 树灵BOSS行动回合!
🌪️ 树灵释放范围攻击!
💥 对艾伦造成24点伤害!HP:26/100
💥 对莉娅造成24点伤害!HP:56/80
👉 艾伦的行动回合!
...
✅ 树灵守护者被击败!
=====================================
🏁 树灵BOSS战结算!
=====================================
🎉 恭喜!击败树灵BOSS!
💰 获得100金币奖励!
🎁 获得稀有道具:高级魔法卷轴!
📚 获得100点经验值!
❤️ 莉娅信任度提升至100!解锁全部辅助技能!
👉 结论:多波战斗的逐波强化、BOSS战的阶段变化、Allen+Lia的联合作战等核心逻辑均正常生效,符合设计预期!
🚨 五、多波战斗&BOSS战设计的「新手坑」与最佳实践
(1)新手常见错误
| 错误写法 | 正确写法 | 问题说明 |
|---|---|---|
| 多波敌人属性无强化(每波难度相同) | 每波提升10%攻击力/血量 | 战斗无挑战性,玩家体验差 |
| BOSS阶段不可逆但未做状态标记 | 使用bossPhase标记阶段,触发后永久生效 |
BOSS反复进入狂暴阶段,逻辑混乱 |
| 联合作战无策略性(Lia仅单纯加血) | 绑定信任度+仇恨分担+随机辅助 | 角色协作无价值,玩法单一 |
| BOSS技能无冷却(无限回血) | 增加healCooldown冷却回合 |
BOSS无敌,战斗无法获胜 |
(2)最佳实践
- 难度梯度化:多波敌人逐波强化,BOSS分阶段提升难度,符合玩家成长曲线;
- 状态标记化 :使用状态变量(
bossPhase/healCooldown)控制BOSS行为,避免逻辑混乱; - 协作策略化:Lia的辅助/治疗/仇恨分担与信任度强绑定,体现协作价值;
- 奖励差异化:普通战斗→基础奖励,多波战斗→稀有道具,BOSS战→高额奖励,驱动玩家挑战;
- 规则透明化:战斗前明确提示BOSS特性/多波规则,让玩家有策略准备。
📌 知识回顾
- 多波战斗的核心流程是「波次初始化→敌人刷新→波次战斗→波次结算→休整→下一波」,敌人属性随波次逐次强化(10%/波);
- 树灵BOSS战采用状态机设计,HP<50%进入狂暴阶段(攻击力+50%),每5回合尝试回血,狂暴阶段有30%概率释放范围攻击;
- Allen+Lia联合作战体现在「仇恨分担(Lia吸引伤害)+ 辅助攻击(信任度驱动)+ 波次间治疗」,信任度是核心联动指标;
- 多波战斗通关奖励稀有魔法花(提升Lia信任度),BOSS战通关解锁Lia满信任度,形成玩法闭环;
- 多波战斗中无法逃跑,BOSS战有专属防御特性(10%概率减免50%伤害),区别于基础战斗规则。
✍️ 写在最后
多波战斗与BOSS战是「魔法森林冒险」战斗系统的进阶玩法,其「难度梯度化+协作深度化+规则特殊化」的设计思路,既保证了战斗的挑战性,又通过Allen+Lia的联合作战体现了角色联动的趣味性。
下一篇我们会聚焦「场景系统:5大场景的任务串联」,带你拆解Region抽象类的设计、各场景的任务触发逻辑、场景切换规则,以及Lia/老贤者在不同场景中的触发时机🌲。
新手建议:
- 在IDE中运行本文的调试示例,尝试修改BOSS的狂暴阈值(从50%改为40%)和回血冷却(从5回合改为4回合),观察战斗难度变化;
- 思考:如果新增「BOSS弱点机制」(使用火系道具造成双倍伤害),该如何修改
takeDamage()方法?
🔥 系列文章导航:
- 项目总览:设计与架构
- 抽象层设计:Figure/Person类
- Allen类(一):核心属性与初始化
- Allen类(二):道具交互核心逻辑
- Allen类(三):任务进度与状态管理
- Lia类深度解析:盟友角色的设计与交互
- 老贤者 & 树灵:NPC/BOSS角色的设计
- 道具系统:基础/关键/特殊道具的实现
- 敌人系统:Goblin/Elf的AI与战斗基础
- 战斗系统(一):基础回合制逻辑
- 战斗系统(二):多波战斗与BOSS战(本文)
- 场景系统:5大场景的任务串联
...(后续篇章持续更新)
💬 评论区互动:你觉得多波战斗/BOSS战还可以增加哪些趣味功能?比如「BOSS阶段掉落增益道具」「多波战斗随机事件(如宝箱/陷阱)」,或者「Allen+Lia组合技能(信任度满触发)」?