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

永久免费的自建网站江西seo网站排名优化

永久免费的自建网站,江西seo网站排名优化,a5做网站,扬州网站优化本章节#xff0c;我们学习一下玩家周边怪物的刷新。在上一章节中#xff0c;我们提过这个事情。当玩家移动完毕之后#xff0c;会显示周围的游戏对象#xff0c;其中就包括NPC怪物。当然#xff0c;玩家“孵化”自己#xff08;调用spawnMe方法#xff09;的时候#…本章节我们学习一下玩家周边怪物的刷新。在上一章节中我们提过这个事情。当玩家移动完毕之后会显示周围的游戏对象其中就包括NPC怪物。当然玩家“孵化”自己调用spawnMe方法的时候也会显示周围的游戏对象。我们首先看一下玩家“孵化”自己的时候调用的是WorldObject 的spawnMe 方法在这个方法中重要的一句代码 World.getInstance().addVisibleObject(this, getWorldRegion(), null); 我们继续到World 类中查看addVisibleObject 方法如下所示 // 从地图上查找附近的游戏对象 final ListWorldObject visibleObjects getVisibleObjects(object, 2000); for (int i 0; i visibleObjects.size(); i) {// 周围的对象把 当前角色我 加入到 _knownObjects 列表中wo.getKnownList().addKnownObject(object, dropper);// 当前角色我 把 周围对象加入到 _knownObjects 列表中object.getKnownList().addKnownObject(wo, dropper); }我们重点查看最后一句代码object.getKnownList().addKnownObject(wo, dropper); 也就是当前玩家把周围的游戏对象NPC怪物添加到自己的_knownObjects 列表中。这里需要注意的是游戏玩家的getKnownList() 方法返回的是PlayerKnownList 类它的addKnownObject方法如下 else if (object.isNpc()) {activeChar.sendPacket(new NpcInfo((Npc) object, activeChar)); }该代码会根据游戏对象的类型向玩家客户端发送不同数据这里的NpcInfo就是NPC怪物对应的数据包信息。接下来我们再来看游戏角色移动完毕之后的操作也就是游戏角色Creature类中的updatePosition方法最后的代码部分 // 到达目标点之后更新周围游戏对象 if (distFraction 1) {getKnownList().updateKnownObjects();ThreadPool.execute(() - getAI().notifyEvent(CtrlEvent.EVT_ARRIVED));return true; }我们继续查看PlayerKnownList 类的updateKnownObjects的方法其实这个方法位于父类WorldObjectKnownList中代码如下 if (_activeObject instanceof Creature) {findCloseObjects();forgetObjects(); }我们继续查看findCloseObjects 方法代码如下 if (_activeObject.isPlayable()){ for (WorldObject object : World.getInstance().getVisibleObjects(_activeObject)) {addKnownObject(object); }}这里大家一定不要忘记Java的多态我们实例化的是子类PlayerKnownList即使我们调用了WorldObjectKnownList里面的addKnownObject方法它还是会调用PlayerKnownList里面的重写的addKnownObject方法的。上面我们已经介绍过这个方法了它就是向玩家客户端发送NpcInfo数据包。 既然我们玩家身边已经出现了NPC怪物那么我们就可以对其进行攻击了。首先我们应该点击选择我们要攻击的对象NPC怪物。此时会向服务器端发送Action数据包。这个Action数据包的应用比较广泛我们后期还会遇到它。我们查看这个Action数据包。 private int _objectId; // 鼠标点击选中的游戏对象IDprivate int _originX; // 玩家当前位置private int _originY; // 玩家当前位置private int _originZ; // 玩家当前位置接下来我们继续查看run方法 // 鼠标点击选中的游戏对象根据ID查询final WorldObject obj World.getInstance().findObject(_objectId);obj.onAction(player);我们先根据游戏对象ID来找到这个游戏对象实例紧接着就会调用游戏对象的onAction方法。这里要注意的是调用的是NPC怪物的onAction方法不是玩家Player的onAction方法。接下来我们就去怪物类Monster的onAction方法。实际上这个方法是在它的父类Npc中我们去父类Npc中查看这个onAction方法的参数是当前玩家哦。在这个方法中分为两种情况。一种是Npc怪物不是当前玩家Player的目标对象_target另一种就是Npc怪物是当前玩家Player的目标对象。当我们第一次选中Npc怪物的时候它当然不是当前玩家的目标对象因此执行第一种情况的代码。 if (this ! player.getTarget()) {// 设置当前玩家的选择目标player.setTarget(this);// 发送 MyTargetSelected 数据包player.sendPacket(new MyTargetSelected(getObjectId(), 0));// 设置开始攻击时间player.setTimerToAttack(System.currentTimeMillis());// 校验玩家当前位置player.sendPacket(new ValidateLocation(this)); }以上代码就是设置当前玩家已经选中的鼠标点击的游戏对象Npc怪物然后向客户端发送MyTargetSelected数据包其实就是告诉客户端服务器端已经选中了可以进行下一步操作了。接下来我们就可以继续单击我们鼠标选中的游戏对象Npc怪物。那么客户端依然向服务器端发送Action数据包依然会调用怪物类Monster的onAction方法。当时由于我们前面的操作中已经设置了玩家的目标对象因此这里该执行第二种情况。 // 校验玩家当前位置 player.sendPacket(new ValidateLocation(this)); // 设置玩家为攻击状态 player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);这里会调用玩家的PlayerAI类让其进入到AI_INTENTION_ATTACK 攻击状态。这个setIntention方法实际位于父类AbstractAI中 case AI_INTENTION_ATTACK: {onIntentionAttack((Creature) arg0);break; }上面的onIntentionAttack方法实际位于CreatureAI类参数就是攻击对象。这里由分为两种情况一种是当今玩家已经处于攻击状态防止用户多次点击攻击相同目标另一种就是当前玩家不是攻击状态。显然我们属于后者我们查看对应的代码 // 改变玩家的状态 changeIntention(AI_INTENTION_ATTACK, target, null); // 设置攻击目标 setAttackTarget(target); // 停止移动 stopFollow(); // 执行 EVT_THINK notifyEvent(CtrlEvent.EVT_THINK, null);这里我们重点查看最后一句代码notifyEvent(CtrlEvent.EVT_THINK, null); 这个notifyEvent方法位于父类AbstractAI中代码如下 case EVT_THINK: {onEvtThink();break; }上面的onEvtThink是在PlayerAI类中它会根据不同状态执行不同行为这个onEvtThink方法实际上循环执行的。因为玩家的自动攻击就是有AI进行循环执行。那么循环的开始位置就是这里的onEvtThink方法。那么循环的代码在哪里呢我们往后看就明白了。 if (getIntention() AI_INTENTION_ATTACK) {// 自动攻击thinkAttack(); }这里不用说一定是要执行thinkAttack方法的而这个方法最终会调用Player的doAttack方法这个方法的代码逻辑并不多主要在它的父类Creature中的doAttack方法它的参数就是被攻击的对象我们大致介绍一下这个方法。 // 获取手持武器 final Weapon weaponItem getActiveWeaponItem(); final Item weaponInst getActiveWeaponInstance();// 检查灵魂蛋使用 boolean wasSSCharged;// 根据武器计算攻击时间 final int timeAtk calculateTimeBetweenAttacks(target, weaponItem);// 攻击到一半的时候给与目标伤害 final int timeToHit timeAtk / 2;// 本次攻击结束时间 _attackEndTime GameTimeTaskManager.getInstance().getGameTicks(); _attackEndTime (timeAtk / GameTimeTaskManager.MILLIS_IN_TICK); _attackEndTime - 1;// 武器的等级 int ssGrade 0;// 发送给客户端的攻击数据包 final Attack attack new Attack(this, wasSSCharged, ssGrade);// 计算下次攻击时间 final int reuse calculateReuseTime(target, weaponItem);// 是否产生伤害可能miss哦 hitted doAttackHitSimple(attack, target, timeToHit);// 更新玩家PVP状态 player.updatePvPStatus(target);// miss效果 if (!hitted){sendPacket(new SystemMessage(SystemMessageId.YOU_HAVE_MISSED));abortAttack(); }// 如果命中造成伤害就广播Attack数据包 if (attack.hasHits()) {broadcastPacket(attack); }// 定时任务执行 NotifyAITask 任务就是执行L2PlayerAI 中的 onEvtThink 方法 ThreadPool.schedule(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), timeAtk reuse);请注意上面的NotifyAITask任务会执行L2PlayerAI 中的 onEvtThink 方法。在上面的说明中我们已经说了这个onEvtThink方法实际上循环执行的。什么时候结束呢要么玩家取消攻击要么怪物死亡等等情况发送。其实就是取消玩家的AI_INTENTION_ATTACK状态即可。接下来我们在简单说一下上面的doAttackHitSimple方法。 // 攻击是否miss final boolean miss1 Formulas.calcHitMiss(this, target);// 计算伤害值 damage1 (int) Formulas.calcPhysDam(this, target, null, shld1, crit1, false, attack.soulshot);// timeToHit 时间后执行 HitTask 伤害任务。攻击动作到一半的时候造成伤害。 ThreadPool.schedule(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk);// 攻击数据包中添加伤害值 attack.addHit(target, damage1, miss1, crit1, shld1);上面的HitTask伤害任务就是执行 onHitTimer(_hitTarget, _damage, _crit, _miss, _soulshot, _shld); 我们直接介绍onHitTimer 方法即可。 // 发送伤害信息就是SystemMessage 数据包。 sendDamageMessage(target, damage, false, crit, miss);// 计算吸血增加玩家HP final double absorbPercent getStat().calcStat(Stat.ABSORB_DAMAGE_PERCENT, 0, null, null); setCurrentHp(getStatus().getCurrentHp() absorbDamage);// 计算反射伤害减少玩家HP final double reflectPercent target.getStat().calcStat(Stat.REFLECT_DAMAGE_PERCENT, 0, null, null); getStatus().reduceHp(reflectedDamage, target, true);// 减少怪物目标HP怪物死亡后掉落物品最为奖励 target.reduceCurrentHp(damage, this);// 设置怪物开始反击玩家 target.getAI().notifyEvent(CtrlEvent.EVT_ATTACKED, this);// 发送开始自动攻击数据包就是AutoAttackStart 数据包 getAI().clientStartAutoAttack(); 这需要大家注意的是上面的主要攻击代码都是集中在Creature类。这个类我们之前讲解过它是玩家Player和怪物Monster的父类里面的移动代码是共享的。当然对于攻击也是如此也是共享于玩家和怪物的。也就是说上面的怪物开始反击玩家的代码也在Creature类中。两者不同的地方在于AI类是不一样的。但是AI类最终还是调用的Creature类doAttack方法。在这个doAttack方法中会根据当前的角色实例Player或Monster来进行不同的代码逻辑判断。这里就不再详细介绍了。 玩家和怪物结束战斗的情况第一就是两者距离问题第二就是一方死亡。第一个距离问题涉及到两者相互追逐的情况。如果是玩家逃跑的话玩家就自动放弃主动攻击的状态而转入移动的状态怪物可能会追击仍然是战斗状态。如果能追击上就发起攻击不能追击上就转入正常的状态返回出生点进入巡逻状态。第二个就是一方死亡双方都会停止自动攻击。如果怪物死亡就会掉落物品。如果是玩家死亡就会弹框给与提示原地复活还是回到附近村庄。如果一方死亡的话另一方都会改变状态。例如玩家会停止自动攻击的状态怪物也会停止自动攻击进入正常状态。战斗双方在“自动战斗”过程中都是使用定时器完成的。结束战斗的话就需要取消定时器。 怪物死亡后重新复活是在RespawnTaskManager类中管理的他是一个单例类同时也是一个线程。在这个线程类中有一个MapNpc, Long PENDING_RESPAWNS 集合。这个集合的Key就是死亡npc而Long值就是再次复活的时间。该线程会不停的从PENDING_RESPAWNS 集合获取死亡的npc然后根据时间判断是否需要复活。 // 当前时间 final long time System.currentTimeMillis();// 循环死亡的npc for (EntryNpc, Long entry : PENDING_RESPAWNS.entrySet()) {// 如果到了复活的时间就复活if (time entry.getValue().longValue()){// 复活npcspawn.respawnNpc(npc);} }复活代码就是调用 Spawn类的respawnNpc方法在这个方法里面就直接调用initializeNpc(oldNpc) 方法重新初始化当前的npc对象。initializeNpc方法我们之前已经讲解过了这里不再叙述了。那么这个RespawnTaskManager 类哪里调用呢就是在这个Spawn类中的decreaseCount方法中 RespawnTaskManager.getInstance().add(oldNpc, System.currentTimeMillis() _respawnDelay); 这个respawnDelay时间就是来自于孵化数据表spawnlist中的respawn_delay字段值。只不过在Spawn类中要做一个小设置_respawnDelay value 10 ? 10000 : value * 1000; 也就是说如果这个respawn_delay字段值小于10的话就修改为1000010秒否者就乘以1000换算成毫秒级单位。那么这个Spawn类中的decreaseCount方法谁来调用就是在npc类的onDecay方法中。该方法是在DecayTaskManager中调用的这也是一个单例线程类。而DecayTaskManager的调用是在npc类的doDie方法中调用。看到doDie方法大家应该就非常清除了就是怪物死亡时候调用的方法。 本章节涉及的内容均已上传百度网盘 https://pan.baidu.com/s/1XdlcCFPvXnzfwFoVK7Sn7Q?pwdavd4 欢迎加企鹅交流裙874700842裙文件里面也可以下载所有内容。
http://www.pierceye.com/news/168268/

相关文章:

  • 考试网站建设房价2024年暴跌
  • 北京网站seo价格建设教育培训的网站
  • 怎样做网站手机和电脑通用木马工业设计公司
  • 榆林市建设局官方网站ppt中网站布局图怎么做
  • 网站视频插件代码如何创建自己的软件
  • 如何免费建造网站电商网站建设哪家好
  • ps做网站首页设计教程郑州seo优化外包热狗网
  • 给网站增加功能怎么做360搜索关键词优化软件
  • 如何做公司网站空间南昌做网站的公司哪个比较好的
  • 美容网站开发网络营销的功能有哪些
  • 推广自己的网站需要怎么做做政协网站的目的是什么
  • 综合性电子商务网站有哪些商城系统软件开发
  • 网站服务器解决方案企业门户网站管理要求
  • 南京网站开发南京乐识专注岳阳网站建设网站
  • 做一直播网站要多少钱淘宝客如何建设推广网站
  • 网站模板内容怎么添加图片不显示菏泽做网站
  • 个人网站备案条件盐城做网站哪家好
  • 小型网站开发教程wordpress自适应小说
  • 来宾网站制作公司网站提交至google
  • 唐山网站建设怎么样专业的个人网站建设哪家
  • 成品网站w灬源码在线看重庆网站制作设计
  • 有没有在家做的兼职网站网站模板如何删除
  • 建站公司用的开源框架家纺网站模板
  • 做情网站甘肃省城乡城乡建设厅网站
  • 开发一个网站做公司内部用一个网站能用asp c
  • 设计师服务平台鱼巴士有哪些网站阜宁网站设计
  • 企业网站开发所需要的模块郴州网警
  • 案例网站网页设计实训报告结束语
  • 重庆网上房地产网站龙岩属于哪里
  • 高水平的番禺网站建设在天猫开店需要什么条件与费用