【魔法森林冒险】11/14 战斗系统(二):多波战斗与BOSS战
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京
文章目录
【魔法森林冒险】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 完整核心代码(未修改,拆分讲解)
importjava.util.Scanner;importjava.util.List;importjava.util.ArrayList;importjava.util.Random;/** * 多波战斗系统核心类:WaveBattleSystem * 继承基础战斗系统,实现黑暗洞穴多波敌人战斗逻辑 */publicclassWaveBattleSystemextendsBattleSystem{// ========== 多波战斗核心属性 ==========// 总波次privatefinalint totalWaves;// 当前波次privateint currentWave;// 敌人列表(每波可能有多个敌人)privateList<Enemy> currentWaveEnemies;// 波次奖励(逐波提升)privatefinalint baseWaveReward =10;// 随机数生成器privateRandom random;// ========== 构造方法:初始化多波战斗 ==========publicWaveBattleSystem(Allen allen,Lia lia,int totalWaves){// 基础战斗系统初始化(传入第一个敌人占位)super(allen, lia,newGoblin());this.totalWaves = totalWaves;this.currentWave =0;this.currentWaveEnemies =newArrayList<>();this.random =newRandom();// 多波战斗初始化提示System.out.println("\n🌋 进入黑暗洞穴 - 多波战斗模式!");System.out.println("🎯 总波次:"+ totalWaves +" | 每波敌人强度逐次提升!");System.out.println("🏆 通关奖励:稀有道具 + 高额经验值!");}// ========== 核心方法:启动多波战斗 ==========@OverridepublicvoidstartBattle(){// 多波战斗主循环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();}// ========== 辅助方法:刷新当前波次敌人 ==========privatevoidspawnWaveEnemies(){// 清空上一波敌人 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 ?newGoblin(true):newGoblin();}else{// 混合敌人:60%哥布林(含首领),40%精灵if(random.nextDouble()<0.6){boolean isLeader = random.nextDouble()<(0.2* currentWave); enemy = isLeader ?newGoblin(true):newGoblin();}else{ enemy =newElf();}}// 敌人属性强化(每波提升10%攻击力/血量) 强化敌人属性(enemy); currentWaveEnemies.add(enemy);}}// ========== 辅助方法:敌人属性强化 ==========privatevoid 强化敌人属性(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)+"%!");}// ========== 辅助方法:获取敌人描述 ==========privateStringgetEnemiesDesc(){StringBuilder desc =newStringBuilder();for(int i =0; i < currentWaveEnemies.size(); i++){ desc.append(currentWaveEnemies.get(i).getName());if(i < currentWaveEnemies.size()-1){ desc.append(" + ");}}return desc.toString();}// ========== 核心方法:当前波次战斗 ==========privatebooleanfightCurrentWave(){// 波次战斗主循环:直到所有敌人被击败或Allen死亡while(true){// 1. 检查Allen是否存活if(super.getAllen().getHp()<=0){returnfalse;}// 2. 检查当前波次所有敌人是否被击败if(areAllEnemiesDead()){returntrue;}// 3. 玩家回合(选择攻击目标)playerTurnWithTarget();// 4. 敌人回合(所有存活敌人依次攻击)enemiesTurn();}}// ========== 辅助方法:玩家回合(可选攻击目标) ==========privatevoidplayerTurnWithTarget(){System.out.println("\n👉 艾伦的行动回合!");super.showActionMenu();int choice =super.getValidChoice(1,4);switch(choice){case1:// 攻击:选择目标attackWithTarget();break;case2:// 使用道具super.useItem();break;case3:// 逃跑(多波战斗中逃跑视为失败)System.out.println("❌ 多波战斗中无法逃跑!");playerTurnWithTarget();break;case4:// 查看状态showWaveStatus();playerTurnWithTarget();break;}}// ========== 辅助方法:选择攻击目标 ==========privatevoidattackWithTarget(){// 展示存活敌人列表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();}// ========== 辅助方法:敌人回合 ==========privatevoidenemiesTurn(){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){// 攻击LiaattackLia(enemy);}else{// 攻击Allen enemy.attackEnemy(super.getAllen());}// 检查Allen/Lia是否存活if(super.getAllen().getHp()<=0||super.getLia().getHp()<=0){return;}}}// ========== 辅助方法:敌人攻击Lia ==========privatevoidattackLia(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 +"点伤害!");}}}// ========== 辅助方法:获取存活敌人 ==========privateList<Enemy>getAliveEnemies(){List<Enemy> aliveEnemies =newArrayList<>();for(Enemy enemy : currentWaveEnemies){if(enemy.getCurrentHp()>0){ aliveEnemies.add(enemy);}}return aliveEnemies;}// ========== 辅助方法:检查所有敌人是否死亡 ==========privatebooleanareAllEnemiesDead(){returngetAliveEnemies().isEmpty();}// ========== 辅助方法:展示波次状态 ==========privatevoidshowWaveStatus(){System.out.println("\n📊 第"+(currentWave +1)+"波战斗状态:");super.showStatus();System.out.println("👹 存活敌人数量:"+getAliveEnemies().size()+"/"+ currentWaveEnemies.size());}// ========== 辅助方法:触发Lia随机辅助攻击 ==========privatevoidtriggerLiaRandomHelpAttack(){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 +"点伤害!");}}}// ========== 核心方法:波次结算 ==========privatevoidwaveSettlement(){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 =newHealPotion(); allen.pickItem(rewardItem);System.out.println("🎁 额外奖励:"+ rewardItem.getName()+"!");}}// ========== 核心方法:波次间休整 ==========privatevoidinterWaveRest(){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){case1:// 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;case2:showWaveStatus();interWaveRest();break;case3:// 继续下一波break;}}// ========== 核心方法:多波战斗最终结算 ==========privatevoidfinalSettlement(){System.out.println("\n=====================================");System.out.println("🏁 多波战斗结算!");System.out.println("=====================================");if(super.isVictory()){System.out.println("🎉 恭喜!通关所有"+ totalWaves +"波战斗!");// 最终奖励:稀有道具(魔法花)Item rareItem =newMagicFlower();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());}}// ========== 辅助方法:展示波次状态 ==========privatevoidshowWaveStatus(){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());}}// ========== 辅助方法:获取存活敌人 ==========privateList<Enemy>getAliveEnemies(){List<Enemy> alive =newArrayList<>();for(Enemy enemy : currentWaveEnemies){if(enemy.getCurrentHp()>0){ alive.add(enemy);}}return alive;}// ========== 辅助方法:检查所有敌人是否死亡 ==========privatebooleanareAllEnemiesDead(){returngetAliveEnemies().isEmpty();}}/** * BOSS战斗系统:TreeSpiritBattleSystem * 实现树灵BOSS的特殊战斗规则 */classTreeSpiritBattleSystemextendsBattleSystem{// BOSS阶段:0-普通,1-狂暴(HP<50%)privateint bossPhase;// BOSS回血冷却回合privateint healCooldown;// 随机数生成器privateRandom random;publicTreeSpiritBattleSystem(Allen allen,Lia lia){// 初始化树灵BOSSTreeSpirit treeSpirit =newTreeSpirit();super(allen, lia, treeSpirit);this.bossPhase =0;this.healCooldown =0;this.random =newRandom();System.out.println("\n🌳 遭遇森林守护者 - 树灵BOSS!");System.out.println("⚠️ BOSS特性:HP<50%进入狂暴状态 | 每5回合尝试回血 | 范围攻击!");}@OverridepublicvoidstartBattle(){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阶段 ==========privatevoidcheckBossPhase(){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回合 ==========privatevoidbossTurn(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和Liaint rangeDamage =(int)(boss.getBaseAttack()*0.8);System.out.println("🌪️ 树灵释放范围攻击!");// 攻击Allensuper.getAllen().setHp(super.getAllen().getHp()- rangeDamage);System.out.println("💥 对艾伦造成"+ rangeDamage +"点伤害!HP:"+super.getAllen().getHp()+"/"+super.getAllen().getMaxHp());// 攻击Liasuper.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);}}// ========== 辅助方法:更新冷却回合 ==========privatevoidupdateCooldown(){if(healCooldown >0){ healCooldown--;System.out.println("⏳ 树灵回血冷却剩余:"+ healCooldown +"回合");}}// ========== 核心方法:BOSS战结算 ==========privatevoidbossBattleSettlement(){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 =newAdvancedMagicScroll(); 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());}}}// ========== 依赖类补充(保证代码可运行) ==========// 基础战斗系统父类(简化版)classBattleSystem{privateAllen allen;privateLia lia;privateEnemy enemy;protectedboolean isBattleOver;protectedboolean isVictory;privateScanner scanner;publicBattleSystem(Allen allen,Lia lia,Enemy enemy){this.allen = allen;this.lia = lia;this.enemy = enemy;this.isBattleOver =false;this.isVictory =false;this.scanner =newScanner(System.in);}publicvoidstartBattle(){}protectedvoidshowActionMenu(){System.out.println("1. ⚔️ 攻击");System.out.println("2. 🎒 使用道具");System.out.println("3. 🏃 尝试逃跑");System.out.println("4. 📊 查看状态");System.out.print("输入数字选择:");}protectedintgetValidChoice(int min,int max){int choice =-1;while(true){if(scanner.hasNextInt()){ choice = scanner.nextInt();if(choice >= min && choice <= max)break;elseSystem.out.print("❌ 输入无效!请输入"+ min +"-"+ max +"之间的数字:");}else{ scanner.next();System.out.print("❌ 输入无效!请输入数字:");}}return choice;}protectedvoiduseItem(){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);}protectedvoidallenAttack(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 +"点伤害!");}privateintgetEnemyDefense(Enemy enemy){return enemy instanceofGoblin?3:5;}protectedvoidshowStatus(){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());}publicAllengetAllen(){return allen;}publicLiagetLia(){return lia;}publicEnemygetEnemy(){return enemy;}publicbooleanisVictory(){return isVictory;}publicvoidsetBattleOver(boolean over){this.isBattleOver = over;}publicvoidsetVictory(boolean victory){this.isVictory = victory;}}// 树灵BOSS类classTreeSpiritextendsEnemy{publicTreeSpirit(){super("树灵守护者","森林的古老BOSS",200,20);}// BOSS回血方法publicintheal(){int healValue =30;this.setCurrentHp(Math.min(this.getCurrentHp()+ healValue,this.getMaxHp()));return healValue;}@OverridepublicbooleantakeDamage(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);returnfalse;}returntrue;}}// 高级魔法卷轴道具classAdvancedMagicScrollextendsItem{publicAdvancedMagicScroll(){super("高级魔法卷轴","提升20点攻击力,持续3回合",true,"稀有");}@Overridepublicbooleanuse(Person target){if(target instanceofAllen){Allen allen =(Allen) target; allen.setAttackPower(allen.getAttackPower()+20);System.out.println("⚡ 攻击力提升20点!持续3回合!");returntrue;}returnfalse;}@OverridepublicStringgetEffectDesc(){return"提升20点攻击力,持续3回合";}}// 魔法花道具classMagicFlowerextendsItem{publicMagicFlower(){super("魔法花","提升莉娅信任度20点",false,"稀有");}@Overridepublicbooleanuse(Person target){if(target instanceofLia){Lia lia =(Lia) target; lia.setTrustLevel(lia.getTrustLevel()+20);System.out.println("❤️ 莉娅信任度+20!当前:"+ lia.getTrustLevel()+"/100");returntrue;}returnfalse;}@OverridepublicStringgetEffectDesc(){return"提升莉娅信任度20点";}}// 其他基础类(简化版,保证代码可运行)abstractclassEnemyextendsFigure{protectedint currentHp;protectedint maxHp;protectedint baseAttack;protectedboolean isFleeing;protectedint hateTarget;publicEnemy(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;}publicabstractbooleantakeDamage(int damage);publicvoidattackEnemy(Person target){ target.setHp(target.getHp()-this.baseAttack);System.out.println("👹 "+this.name +"对"+ target.getName()+"造成"+this.baseAttack +"点伤害!");}publicintgetCurrentHp(){return currentHp;}publicvoidsetCurrentHp(int hp){this.currentHp = hp;}publicintgetMaxHp(){return maxHp;}publicvoidsetMaxHp(int hp){this.maxHp = hp;}publicintgetBaseAttack(){return baseAttack;}publicvoidsetBaseAttack(int attack){this.baseAttack = attack;}publicbooleanisFleeing(){return isFleeing;}publicintgetHateTarget(){return hateTarget;}}classGoblinextendsEnemy{publicGoblin(){super("普通哥布林","低智商小怪",50,10);}publicGoblin(boolean isLeader){super(isLeader ?"哥布林首领":"普通哥布林", isLeader ?"哥布林头目":"低智商小怪", isLeader ?80:50, isLeader ?15:10);}@OverridepublicbooleantakeDamage(int damage){this.currentHp -= damage;returnthis.currentHp >0;}}classElfextendsEnemy{publicElf(){super("精灵弓箭手","魔法弓箭手",60,12);}@OverridepublicbooleantakeDamage(int damage){if(Math.random()<=0.15){System.out.println("💨 精灵闪避攻击!");returntrue;}this.currentHp -= damage;returnthis.currentHp >0;}}abstractclassPersonextendsFigure{protectedint hp;protectedint maxHp;protectedint gold;publicPerson(String name,String description){super(name, description);}publicintgetHp(){return hp;}publicvoidsetHp(int hp){this.hp =Math.max(hp,0);}publicintgetMaxHp(){return maxHp;}publicintgetGold(){return gold;}publicvoidsetGold(int gold){this.gold = gold;}}classAllenextendsPerson{privateint attackPower;privateint skillLevel;privateint experience;privateint level;privateList<Item> backpack;publicAllen(){super("艾伦","冒险者");this.maxHp =100;this.hp =100;this.attackPower =15;this.skillLevel =1;this.experience =0;this.level =1;this.backpack =newArrayList<>();}publicintgetAttackPower(){return attackPower;}publicvoidsetAttackPower(int power){this.attackPower = power;}publicintgetSkillLevel(){return skillLevel;}publicList<Item>getBackpack(){return backpack;}publicvoidpickItem(Item item){ backpack.add(item);}publicintgetLevel(){return level;}publicvoidaddExperience(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 +"级!");}}}classLiaextendsPerson{privateint trustLevel;publicLia(){super("莉娅","精灵盟友");this.maxHp =80;this.hp =80;this.trustLevel =0;}publicintgetTrustLevel(){return trustLevel;}publicvoidsetTrustLevel(int level){this.trustLevel =Math.min(level,100);}publicinthelpAllenFight(Enemy enemy){int damage =10; enemy.takeDamage(damage);return damage;}}abstractclassItem{protectedString name;protectedString description;protectedboolean isConsumable;publicItem(String name,String description,boolean isConsumable,String rarity){this.name = name;this.description = description;this.isConsumable = isConsumable;}publicabstractbooleanuse(Person target);publicabstractStringgetEffectDesc();publicStringgetName(){return name;}publicbooleanisConsumable(){return isConsumable;}}classHealPotionextendsItem{publicHealPotion(){super("普通治疗药水","恢复20点HP",true,"普通");}@Overridepublicbooleanuse(Person target){ target.setHp(target.getHp()+20);returntrue;}@OverridepublicStringgetEffectDesc(){return"恢复20点HP";}}abstractclassFigure{protectedString name;protectedString description;publicFigure(String name,String description){this.name = name;this.description = description;}publicStringgetName(){return name;}}// ========== 测试类 ==========classWaveAndBossBattleTest{publicstaticvoidmain(String[] args){// 1. 创建角色Allen allen =newAllen();Lia lia =newLia(); lia.setTrustLevel(70); allen.pickItem(newHealPotion());// 2. 多波战斗测试(3波)WaveBattleSystem waveBattle =newWaveBattleSystem(allen, lia,3); waveBattle.startBattle();// 3. BOSS战测试TreeSpiritBattleSystem bossBattle =newTreeSpiritBattleSystem(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 仇恨分担机制
privatevoidenemiesTurn(){for(Enemy enemy : aliveEnemies){// 仇恨目标为1且Lia信任度≥60 → 攻击Liaif(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辅助攻击/治疗
// 随机辅助攻击privatevoidtriggerLiaRandomHelpAttack(){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 +"点伤害!");}}// 波次间治疗privatevoidinterWaveRest(){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组合技能(信任度满触发)」?