从零开始手写mmo游戏从框架到爆炸(二十一)— 战斗系统二
导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客
上一章(从零开始手写mmo游戏从框架到爆炸(二十)— 战斗系统一-CSDN博客)我们只是完成了基本的战斗,速度属性并没有真正的发生作用。现在我们加入速度属性。上一章我们说过,比如速度是1000的时候是每隔2秒钟攻击一次,但是服务器不能真的等两秒再计算攻击的结果,那么这个战斗的时长将会超过几分钟,用户也可能等这么久。那么这里要解决几个问题:
第一个就是速度和出手间隔的换算,我们使用一个比较简单的公式,就是
这样可以保证最短的出手时间是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上点个星星,谢谢!
相关文章:
从零开始手写mmo游戏从框架到爆炸(二十一)— 战斗系统二
导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客 上一章(从零开始手写mmo游戏从框架到爆炸(二十)— 战斗系统一-CSDN博客)我们只是完成了基本的战斗,速度属性并没有…...
![](https://www.ngui.cc/images/no-images.jpg)
强化学习入门(Matlab2021b)-创建环境【3】
目录 1 前言2 根据类模板创建自定义环境2.1 创建类模板2.2 Environment properties(环境特性)2.3 Required Functions(需要的环境方法)2.3.1 Constructor function(构造函数)2.3.2 reset function2.3.3 step function2.4 Optional Functions(可选的环境方法)2.5 Environment Vi…...
![](https://img-blog.csdnimg.cn/img_convert/f3c9e8a3c9095c511ff649f514d2843b.jpeg)
C++如何避免float误差?
C如何避免float误差? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「c的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! …...
![](https://img-blog.csdnimg.cn/direct/ec9fb1874d5446b8871ee8e08e256290.png)
深信服技术认证“SCCA-C”划重点:深信服超融合HCI
为帮助大家更加系统化地学习云计算知识,高效通过云计算工程师认证,深信服特推出“SCCA-C认证备考秘笈”,共十期内容。“考试重点”内容框架,帮助大家快速get重点知识 划重点来啦 *点击图片放大展示 深信服云计算认证(S…...
![](https://img-blog.csdnimg.cn/direct/29f3a100a9ae4461b6d0e66cf74a9480.png)
Vue3路由元信息
路由元信息即定义路由时的meta信息 使用路由元信息定义页面在浏览器显示的标题 定义路由 const router createRouter({history:createWebHistory(import.meta.env.BASE_URL),routes:[{path:"/",component:()>import("/components/Login.vue"),meta:{…...
![](https://img-blog.csdnimg.cn/direct/95581e0888434c01a039e8e10a96c63a.png)
实用区块链应用:去中心化投票系统的部署与实施
一、需求分析背景 随着技术的发展,传统的投票系统面临着越来越多的挑战,如中心化控制、透明度不足和易受攻击等问题。为了解决这些问题,我们可以利用区块链技术去中心化、透明性和安全性来构建一个去中心化投票系统。这样的系统能够确保投票过…...
![](https://img-blog.csdnimg.cn/direct/2b675f147689455587990918f5f39270.png)
Flink中的双流Join
1. Flink中双流Join介绍 Flink版本Join支持类型Join API1.4innerTable/SQL1.5inner,left,right,fullTable/SQL1.6inner,left,right,fullTable/SQL/DataStream Join大体分为两种:Window Join 和 Interval Join 两种。 Window Join又可以根据Window的类型细分为3种…...
![](https://img-blog.csdnimg.cn/direct/19b369310d6647318c969b03c0156b19.png)
协程源码 launch 流程跟踪学习
为了更深入学习协程的底层实现原理,了解协程线程切换的根本本质。也为了以后在工作中可以根据不同的需求场景,更加随心所欲的使用不同的协程。 今天通过 launch 跟踪一下协程的执行流程。 fun getData() {Trace.beginSection("getData");Log.…...
![](https://img-blog.csdnimg.cn/direct/638358c3bfab4f4686f9c5962af9099a.png)
苍穹外卖Day02——总结2
前期文章 文章标题地址苍穹外卖Day01——总结1https://blog.csdn.net/qq_43751200/article/details/135466359?spm1001.2014.3001.5501苍穹外卖Day01——解决总结1中存在的问题https://lushimeng.blog.csdn.net/article/details/135473412 总结2 前期文章1. 新增员工模块1.1 …...
![](https://www.ngui.cc/images/no-images.jpg)
探索Nginx:一款高效、稳定的Web服务器和反向代理工具
在网站性能优化和架构设计中,Nginx以其高性能、低资源消耗和良好的扩展性成为了许多开发者和服务器管理员的首选。本文将为您详细介绍Nginx的概念、特点、安装、配置和使用,帮助您更好地了解并运用这款优秀的工具。 一、Nginx简介 Nginx(发…...
![](https://img-blog.csdnimg.cn/direct/a0c0bd7a59c44778aec859162bb2678b.jpeg)
文案改写软件,高效改文案的方法
在互联网飞速发展的今天,文案的重要性在营销和传播中变得越发突出。而高质量的文案内能够吸引人们的注意力,打动他们的心弦,这样更能促使他们产生需求。然而,想要写一篇引人入胜的文案并不容易,需要时间和经验来调整和…...
![](https://img-blog.csdnimg.cn/direct/033ad989a145424bb12a5bc06a884bd9.png)
黑马头条-day10
文章目录 app端文章搜索1、文章搜索1.1 ElasticSearch环境搭建1.2 索引库创建①需求分析②ES导入数据场景分析③创建索引和映射 1.3 索引数据同步①app文章历史数据导入ES②文章实时数据导入ES 1.4 文章搜索多条件复合查询①关键词搜索②搜索接口定义 2、搜索历史记录2.1 需求说…...
![](https://img-blog.csdnimg.cn/direct/c2511c41283946369f4f7e8fe65c9378.png)
C++的stack容器->基本概念、常见接口
#include<iostream> using namespace std; #include <stack> //栈stack容器常用接口 void test01() { //创建栈容器 栈容器必须符合先进后出 stack<int> s; //向栈中添加元素,叫做 压栈 入栈 s.push(10); s.push(20); s…...
![](https://www.ngui.cc/images/no-images.jpg)
VUE中引入外部jquery.min.js文件
jquery官网:https://jquery.com/ cdn链接:https://code.jquery.com/jquery-3.7.1.js <template><div class"">测试jq<div id"jq">这是一个盒子</div></div> </template><script> import…...
![](https://www.ngui.cc/images/no-images.jpg)
MongoDB聚合运算符:$avg
$avg运算符返回给定数值的平均值 $avg可用于以下阶段: $addFields阶段(从MongoDB 3.4开始可用)$bucket阶段$bucketAuto阶段$group阶段包含$expr表达式的$match阶段$project阶段$replaceRoot阶段(从MongoDB 3.4开始可用)$replaceWith阶段(从MongoDB 4.2开始可用)$s…...
![](https://img-blog.csdnimg.cn/direct/b2f06f37636f4a1594c661d5b2e3e358.png)
Web 前端 UI 框架Bootstrap简介与基本使用
Bootstrap 是一个流行的前端 UI 框架,用于快速开发响应式和移动设备优先的网页。它由 Twitter 的设计师和工程师开发,现在由一群志愿者维护。Bootstrap 提供了一套丰富的 HTML、CSS 和 JavaScript 组件,可以帮助开发者轻松地构建和定制网页和…...
![](https://www.ngui.cc/images/no-images.jpg)
【Python笔记-设计模式】惰性评价模式
一、说明 将某些对象的创建或计算延迟到真正需要它们的时候,以减少不必要的资源消耗和提高性能。 惰性评价在Python中实现也成为生成器,一般通过yield关键字实现。 (一) 解决问题 在处理大量数据时,使用惰性加载可以避免一次性加载所有数…...
![](https://www.ngui.cc/images/no-images.jpg)
每日学习总结20240221
每日总结 20240221 花自飘零水自流。一种相思,两处闲愁。 —— 李清照「一剪梅红藕香残玉簟秋」 1. stat 在Linux中,stat 是一个用于显示文件或文件系统状态的命令行工具。它提供了关于文件的详细信息,包括文件类型、权限、大小、所有者、修…...
![](https://img-blog.csdnimg.cn/direct/8b4c5a091a4846cbb8dd23b96808a537.png)
学生成绩管理系统(C语言课设 )
这个学生成绩管理系统使用C语言编写,具有多项功能以方便管理学生信息和成绩。首先从文件中读取数据到系统中,并提供了多种功能(增删改查等)选项以满足不同的需求。 学生成绩管理系统功能: 显示学生信息增加学生信息删除学生信息…...
![](https://www.ngui.cc/images/no-images.jpg)
ChatGPT提示词(最新)
它能干什么? 包括但不限于: 类别描述学术论文它可以写各种类型的学术论文,包括科技论文、文学论文、社科论文等。它可以帮助你进行研究、分析、组织思路并编写出符合学术标准的论文。创意写作它可以写小说、故事、剧本、诗歌等创意性的文学作品&#…...
![](https://img-blog.csdnimg.cn/direct/169ed4985f5e4cba98e521bfdd6b4d48.png)
算法——模拟
1. 什么是模拟算法? 官方一点来说 模拟算法(Simulation Algorithm)是一种通过模拟现实或抽象系统的运行过程来研究、分析或解决问题的方法。它通常涉及创建一个模型,模拟系统中的各种事件和过程,以便观察系统的行为&a…...
![](https://img-blog.csdnimg.cn/direct/cf209748379c4f8296b4fa8a53b49950.png)
如何进行高性能架构的设计
一、前端优化 减少请求次数页面静态化边缘计算 增加缓存控制:请求头 减少图像请求次数:多张图片变成 一张。 减少脚本的请求次数:css和js压缩,将多个文件压缩成一个文件。 二、页面静态化 三、边缘计算 后端优化 从三个方面进…...
![](https://img-blog.csdnimg.cn/direct/1a8a11fd81ce4273a21a909afc8bbb34.png)
vivado FSM Components
Vivado合成功能 •同步有限状态机(FSM)组件的特定推理能力。 •内置FSM编码策略,以适应您的优化目标。 •FSM提取默认启用。 •使用-fsm_extraction off可禁用fsm提取。 FSM描述 Vivado综合支持Moore和Mealy中的有限状态机(…...
![](https://img-blog.csdnimg.cn/direct/3b6b40080aa2435cb0671436c0183343.png)
从零开始手写mmo游戏从框架到爆炸(十五)— 命令行客户端改造
导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客 到现在,我们切实需要一个客户端来完整的进行英雄选择,选择地图,打怪等等功能。所以我们需要把之前极为简陋的客户端改造一下。 首先…...
![](https://img-blog.csdnimg.cn/direct/558ed1954a094a388881c140c154d7c8.png)
Elasticsearch:什么是 kNN?
kNN - K-nearest neighbor 定义 kNN(即 k 最近邻算法)是一种机器学习算法,它使用邻近度将一个数据点与其训练并记忆的一组数据进行比较以进行预测。 这种基于实例的学习为 kNN 提供了 “惰性学习(lazy learning)” 名…...
![](https://www.ngui.cc/images/no-images.jpg)
掌握网络未来:深入解析RSVP协议及其在确保服务质量中的关键作用
第一部分:RSVP简介 资源预留协议(RSVP)是一种网络协议,用于在网络中的各个节点之间预留资源,以支持数据流的服务质量(QoS)要求。RSVP特别适用于需要固定带宽和处理延迟的应用,如视频…...
![](https://img-blog.csdnimg.cn/direct/72ea17715cb445d2b7ff3dbf0288aa5d.png)
【Linux】一站式教会:Ubuntu(无UI界面)使用apache-jmeter进行压测
🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 🛸学无止境,不骄不躁,知行合一 文章目录 前言一、Java…...
![](https://img-blog.csdnimg.cn/direct/4dceee2c47c2403489151f78b36d4594.png#pic_center)
Howler.js:音频处理的轻量级解决方案
文章目录 Howler.js:音频处理的轻量级解决方案引言一、Howler.js简介1.1 特性概览 二、Howler.js基本使用使用详解2.1 创建一个Howl对象2.2 控制音频播放2.3 监听音频事件 三、进阶功能3.1 音频Sprites3.2 3D音频定位 四、微前端场景下的Howler.js Howler.js&#x…...
![](https://img-blog.csdnimg.cn/9f3301b11fdc4ff79124aaa3e4bc2ec1.png)
【讨论】Web端测试和App端测试的不同,如何说得更有新意?
Web 端测试和 App 端测试是针对不同平台的上的应用进行测试,Web应用和App端的应用实现方式不同,测试时的侧重点也不一样。 Web端应用和App端应用的区别: 平台兼容性 安装方式 功能和性能 用户体验 更新和维护 测试侧重点有何不同 平台…...
![](https://img-blog.csdnimg.cn/direct/4bba0ab1eea245dd87795c8e137fff9a.png#pic_center)
运维SRE-18 自动化批量管理-ansible4
12.2handles handles触发器(条件),满足条件后再做什么事情应用场景:想表示:配置文件变化,再重启服务 配置handlers之前,每次运行剧本都会重启nfs,无论配置文件是否变化。 [rootm01 /server/ans/playbook]…...
![](/images/no-images.jpg)
wordpress4.9安装/网络seo营销推广
1、首先你要有图形化桌面 如果没有 用以下命令安装:yum -y groupinstall "Desktop" yum -y groupinstall "X Window System" yum -y groupinstall "Chinese Support" //此为中文简体包,如果不需要,可以不下 将…...
![](/images/no-images.jpg)
企业黄页信息查询/万词优化
Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准: 技能(任何人都能容易学会命令式编程)模式(有些人用“模式-模式”,举个例子,模式可以应用到任何地方…...
![](https://img-blog.csdnimg.cn/20201010093859759.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0FXZW5fSmFjaw==,size_16,color_FFFFFF,t_70#pic_center)
wordpress 初始化/seo顾问合同
原因: Springboot版本为2.1.3.RELEASE, Netty版本为4.1.50.Final, 引入spring-boot-starter-data-redis依赖后, 因为其中也有Netty依赖, 但是版本只有4.1.33, 因而版本冲突导致异常 解决方法: 1. 将Springboot版本改为2.2.6.RELEASE 2. 或将Netty版本改为4.1.33.Final<pa…...
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
wordpress 推广返利/今日重大新闻头条
题目链接: http://codeforces.com/problemset/problem/831/A 题目描述: 让你判断数列是不是符合题目描述的规律增长 解题思路: 我知道我的思路是对的, 但是肯定是不好的, 因为BUG特别难找 代码: #include …...
![](/images/no-images.jpg)
网站开发公司长春/网站发布
数据处理一般步骤1、识别出X和Y2、识别出连续 和 分类变量3、分割数据集,70%训练集,30%测试集4、建立模型5、训练模型、测试模型一、对离散特征的编码离散特征的编码分为两种情况:1、离散特征的取值之间没有大小的意义,比如color&…...
![](/images/no-images.jpg)
做游戏排行榜的网站模板/怎么在网上销售
本文实例讲述了Python实现的拟合二元一次函数功能。分享给大家供大家参考,具体如下:背景:使用scipy拟合一元二次函数。参考:HYRY Studio-《用Python做科学计算》代码:# -*- coding:utf-8 -*-#! python3import numpy as…...