当前位置: 首页 > news >正文

从零开始手写mmo游戏从框架到爆炸(二十一)— 战斗系统二

导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客    

        上一章(从零开始手写mmo游戏从框架到爆炸(二十)— 战斗系统一-CSDN博客)我们只是完成了基本的战斗,速度属性并没有真正的发生作用。现在我们加入速度属性。上一章我们说过,比如速度是1000的时候是每隔2秒钟攻击一次,但是服务器不能真的等两秒再计算攻击的结果,那么这个战斗的时长将会超过几分钟,用户也可能等这么久。那么这里要解决几个问题:

        第一个就是速度和出手间隔的换算,我们使用一个比较简单的公式,就是

interval = 500 + (int) (((1 - (speed) * 1.0 / (2000 + speed)) * (1 - (speed) * 1.0 / (2000 + speed))) * 5000);

        这样可以保证最短的出手时间是500,最长也不会超过5000。

       第二个问题就是根据速度插入到队列的问题,首先我们看下对于LinkedList队列的插入demo

public class Main {public static void main(String[] args) {LinkedList<Integer> queue = new LinkedList<>(); // 创建一个空的队列// 添加初始元素for (int i = 1; i <= 5; i++) {queue.addLast(i);}System.out.println("原始队列:" + queue);int targetIndex = 2; // 目标索引为2(从0开始计算)int elementToInsert = 99; // 要插入的元素值ListIterator<Integer> iterator = queue.listIterator();while (iterator.hasNext()) {if (targetIndex == 0) {iterator.next(); // 跳过第一个元素break;} else {iterator.next();targetIndex--;}if (!iterator.hasNext() && targetIndex > 0) {throw new IndexOutOfBoundsException("目标索引超出了队列长度");}}iterator.add(elementToInsert); // 在指定位置插入新元素System.out.println("插入元素后的队列:" + queue);}
}

运行后结果如下:

原始队列:[1, 2, 3, 4, 5]
插入元素后的队列:[1, 2, 3, 99, 4, 5]

那么根据这个方法我们来尝试改造战斗引擎。

       首先Action接口中增加一个interval()的方法,用于获取时间间隔,这个时间间隔是预计攻击时间距离战斗开始时间的间隔,例如计算出来的攻击间隔是500,那么每次计算的结果就是500,1000,1500,2000...以此类推。

public interface Action {boolean run();/**** 是否继续* @return*/boolean checkContinue();int speed();/***** @return*/int intervalTime();
}

   同时创建一个抽象类来抽象部分功能:

public abstract class Attack implements Action{private int intervalTime;private int speed;public int getIntervalTime() {return intervalTime;}public void setIntervalTime(int intervalTime) {this.intervalTime = intervalTime;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}@Overridepublic int intervalTime() {return intervalTime;}@Overridepublic int speed() {return speed;}public int computeInterval(int speed) {return 500 + (int) (((1 - (speed) * 1.0 / (2000 + speed))* (1 - (speed) * 1.0 / (2000 + speed))) * 5000);}
}

         修改 GroupAttack 在创建的时候要不是速度和间隔两个字段

public class GroupAttack extends Attack {private Hero heroA;private List<Hero> defenceList;public GroupAttack(Hero heroA, List<Hero> defenceList) {this.heroA = heroA;this.defenceList = defenceList;setIntervalTime(computeInterval(heroA.getSpeed()));setSpeed(heroA.getSpeed());}@Overridepublic boolean run() {// 自己血量少于0 返回if(heroA.getHp() > 0) {        // 遍历并找到血量最少的攻击defenceList = defenceList.stream().filter(e -> e.getHp() > 0).collect(Collectors.toList());if (!CollectionUtils.isEmpty(defenceList)) {defenceList.sort(Comparator.comparing(Hero::getHp));heroA.attack(defenceList.get(0));return true;}}return false;}@Overridepublic boolean checkContinue() {return heroA.getHp() > 0 && defenceList.stream().anyMatch(e -> e.getHp() > 0);}}

 最后我们再创建一个战斗服务:

public class BattleManyToManyTwo {// 队列不变private final LinkedList<Attack> actions = new LinkedList<>();private int addAction(Attack action){actions.offer(action);return actions.size();}public void fight(List<Hero> listA, List<Hero> listB) throws InterruptedException {// 先初始化listA.sort(Comparator.comparing(Hero::getSpeed).reversed());for (int i = 0; i < listA.size(); i++) {addAction(new GroupAttack(listA.get(i),listB));}// 再放入listBlistB.sort(Comparator.comparing(Hero::getSpeed).reversed());for (int i = 0; i < listB.size(); i++) {GroupAttack attack = new GroupAttack(listB.get(i), listA);insertAction(attack);}// 如果A集合和B集合的生命值都还大于0while(listA.stream().anyMatch(e -> e.getHp() > 0) && listB.stream().anyMatch(e -> e.getHp() > 0)) {Attack pop = actions.pop();boolean run = pop.run();if(run) {// 再放进去if (pop.checkContinue()) {// 要重新计算interval的时间pop.setIntervalTime(pop.getIntervalTime() + pop.computeInterval(pop.speed()));insertAction(pop);}// 打印System.out.println("A集团 :" + JSON.toJSONString(listA));System.out.println("B集团 :" + JSON.toJSONString(listB));}}if(listA.stream().anyMatch(e -> e.getHp() > 0)) {System.out.println("A集团 获胜:" + JSON.toJSONString(listA));}else{System.out.println("B集团 获胜:" + JSON.toJSONString(listB));}}private void insertAction(Attack attack) {int intervalTime = attack.getIntervalTime();// 如果第一个就大于attack的intervalif(actions.get(0).getIntervalTime() > attack.intervalTime()){// 在头插入一个actions.push(attack);}else {ListIterator<Attack> iterator = actions.listIterator();while (iterator.hasNext()) {Attack next = iterator.next();if (next.getIntervalTime() > intervalTime) {break;}}// 在指定位置插入新元素iterator.add(attack);}}public static void main(String[] args) throws InterruptedException {BattleManyToManyTwo battle = new BattleManyToManyTwo();Hero A = new Hero("A");Hero B = new Hero("B");B.setSpeed(2000);B.setAttack(20);Hero C = new Hero("C");C.setSpeed(500);C.setAttack(20);Hero D = new Hero("D");D.setSpeed(10);D.setAttack(15);battle.fight(Arrays.asList(A,C),Arrays.asList(B,D));}}

 运行main方法,查看效果:

B攻击,C生命值减少20
B攻击,C生命值减少20
C攻击,B生命值减少20
A攻击,B生命值减少10
B攻击,C生命值减少20
D攻击,C生命值减少15
C攻击,B生命值减少20
B攻击,C生命值减少20
B攻击,C生命值减少20
B攻击,A生命值减少20
A攻击,B生命值减少10
D攻击,A生命值减少15
B攻击,A生命值减少20
B攻击,A生命值减少20
B攻击,A生命值减少20
A攻击,B生命值减少10
D攻击,A生命值减少15
B集团 获胜:[{"attack":20,"hp":30,"name":"B","speed":2000},{"attack":15,"hp":100,"name":"D","speed":10}]Process finished with exit code 0

全部源码详见:

gitee : eternity-online: 多人在线mmo游戏 - Gitee.com

分支:step-11

请各位帅哥靓女帮忙去gitee上点个星星,谢谢!

http://www.lryc.cn/news/304658.html

相关文章:

  • 强化学习入门(Matlab2021b)-创建环境【3】
  • C++如何避免float误差?
  • 深信服技术认证“SCCA-C”划重点:深信服超融合HCI
  • Vue3路由元信息
  • 实用区块链应用:去中心化投票系统的部署与实施
  • Flink中的双流Join
  • 协程源码 launch 流程跟踪学习
  • 苍穹外卖Day02——总结2
  • 探索Nginx:一款高效、稳定的Web服务器和反向代理工具
  • 文案改写软件,高效改文案的方法
  • 黑马头条-day10
  • C++的stack容器->基本概念、常见接口
  • VUE中引入外部jquery.min.js文件
  • MongoDB聚合运算符:$avg
  • Web 前端 UI 框架Bootstrap简介与基本使用
  • 【Python笔记-设计模式】惰性评价模式
  • 每日学习总结20240221
  • 学生成绩管理系统(C语言课设 )
  • ChatGPT提示词(最新)
  • 算法——模拟
  • 如何进行高性能架构的设计
  • vivado FSM Components
  • 从零开始手写mmo游戏从框架到爆炸(十五)— 命令行客户端改造
  • Elasticsearch:什么是 kNN?
  • 掌握网络未来:深入解析RSVP协议及其在确保服务质量中的关键作用
  • 【Linux】一站式教会:Ubuntu(无UI界面)使用apache-jmeter进行压测
  • Howler.js:音频处理的轻量级解决方案
  • 【讨论】Web端测试和App端测试的不同,如何说得更有新意?
  • 运维SRE-18 自动化批量管理-ansible4
  • 编程笔记 Golang基础 008 基本语法规则