客户端ARPG角色行为模型
[概述]
对于玩家自身而言, 场景中的角色分两种:自己,别的生物(包括别的玩家,monster, npc等)。而生物本身是一个集合{属性数据(状态), 行为(动作表现)}。
站在玩家自身的角度来看, 对于别的生物, 他们的所有数据和行为都是来自服务器, 客户端要做的相当于播放录像的功能, 根据服务器送过来的指令对他们进行控制和表现。
而玩家自身, 其行为来自两个地方:1、操作模块(比如说客户端的io操作, 程序发出的操作指令等, 操作模块内部封装了所有的操作指令, 对玩家对象进行控制), 2、服务器指令。操作模块的指令会向两个路径分发:1、向服务器发送请求,2、向玩家自身发送指令.
[角色行为]
和角色行为相关的变量:
1、 完成条件(即条件满足前不能进行其他行为)。
2、 位置(产生行为的角色位置)。
3、 方向。
4、 状态(此行为对应的角色状态)。
5、 动作表现。
[行为分类]
1、walk. 终点位置, 速度
2、run. 终点位置, 速度
3、攻击(施法). 位置,方向
4、受伤(被攻击).
5、死亡. 位置
6、冲撞、被冲撞、死亡击飞等运动轨迹相关. 终点位置
[玩家自身]
[一] 连续移动
1、客户端角色Me每预先跑一步A-->B, 都要等待服务器的返回(失败或者成功)。在服务器返回响应之前(Me有可能在移动过程中, 也有可能已经到达B点等候),客户端有可能存在以下操作:
a、移动操作, 即点击场景其他地方C(即玩家想下一步移动到C),此时应该把C立即加入到移动队列中。
如果服务器返回成功, 则继续处理移动队列;如果服务器返回失败, 则将Me拉回到A点, 并清空移动队列。
b、其他操作(如攻击)
如果服务器返回成功, 则清空移动队列, 并处理操作队列;如果服务器返回失败, 则将Me拉回到A点, 并清空移动队列, 操作队列。
[二] 攻击
客户端角色Me的位置CP, 服务器位置SP
1、CP与SP位置一致, 则立即发送attack指令到服务器, 并立即切换到attack状态,表现攻击动作。
2、CP与SP位置不一致(有可能正在移动过程中, 即已经发送move指令到服务器), 则立即发送attack指令到服务器(预先攻击)
a、如果attack指令返回成功, 则等待CP与SP相同时则前端进行攻击行为流程。
b、如果attack指令返回失败, 则清除标志, 并等待下一步操作。
3、尝试释放技能的时机
a、任务开始时在当前位置判断能否释放。
(有可能攻击失败, 因为玩家位置已变, 延时通知)
b、开始一次新的移动,先向服务请求移动,前端预移动,并且判断能否释放, 如果可以则预释放。服务器返回移动请求和释放请求成功后,等到达目的点之后表现攻击动作和特效,否则清除预攻击状态。
(有可能攻击失败, 因为玩家位置已变, 延时通知。这时候是否需要根据当前玩家移动的时间做一个判断策略?一次移动的时间间隔是560ms, 正常的网络传输延时极限(玩家移动广播到达之前+自己发送攻击请求到服务器延时)3个传输延时和2个服务器处理延时)。
c、收到攻击对象位置变化广播时,判断能否释放,如果可以, 则根据自己当前的状态进行释放或者预释放。
(这个时候成功率最高, 因为玩家位置延时最短。)
以上三个时机形成了开始一个攻击任务整个阶段的闭环。
[其它场景对象]
这里的处理模型, 主要用于处理行为队列中存在多个行为的情况(大部分原因是网络延迟引起的)
[一] 移动
1、 行为队列全部是移动行为, 两种处理方式:
a、 依次处理每个移动行为。
b、 根据队列长度,直接处理队尾的移动行为,并清空行为队列。
2、 行为队列最后一个行为是攻击行为, 同样是两种处理方式:
a、 依次处理每个移动行为。
b、根据队列长度,直接处理队尾的攻击行为,并清空行为队列。
[二] 攻击
处理模型同上。
[三] 服务器强制同步行为
服务器有时候会强制同步行为, 如瞬移等。 则立即清空行为队列, 并执行强制同步行为。
[操作模块]
操作模块是针对玩家自身的操作(io操作、自动挂机产生的操作等),将其转换为控制玩家对象的一个逻辑控制任务, 这里用operation表示,比如移动、释放技能、访问npc等都可称之为operation。
1、创建一个operation之前, 要先判断能否创建这个operation,不能则不响应玩家操作;若能, 则创建一个operation,并且插入到operation队列中。
例如玩家当前处于摆摊或则死亡等不能移动的状态, 如果这时候玩家操作想移动, 则直接返回不响应。
例如技能cd没到或魔法值不够等处于不能释放技能的状态, 如果这时候玩家操作想释放技能, 则直接返回不响应。
2、若当前正在执行的operation失败, 则要判断失败原因, 判断是否要重新尝试。
例如移动任务,在移动过程中遇到阻挡点或则服务器返回移动失败, 则重新寻路。寻路成功,则继续执行;失败,则放弃任务。
例如释放技能(有可能会创建一个移动的子任务),在执行过程中发现魔法值不足等问题, 则直接放弃任务。若是移动失败,则尝试重新寻路。
[行为队列模式(FIFO)]
无论是某个具体的动作行为,还是某个改变状态的操作, 都可以抽象为一个action cmd。
每个entity持有一个ActionModel, 每个ActionModel维护一个action list。
[一]实现细节
1、因为要频繁产生action cmd, 如何防止碎片化问题, 在解决这个问题的时候, 不能影响可维护性和扩展性, 尤其是扩展性。
2、action list: a1 a2 a3, 在表现上, 由于a2是一个持续性过程, a3有可能会影响a2的表现, 也就是a3可以在a2的执行过程中直接处理, 从而达到并发性表现(并发性的cmd可以使得表现更为丰富)。据此可以抽象, action cmd可以分为:互斥性action和并发性action。
action list的处理流程:
if(curAction.isEnd)
{
curAction = list.empty ? action_idle : list.pop_front;
} while(!list.front.isMutex(curAction))
{
Process(list.pop_front);
} curAction.update;
[事件与状态]
1、移动
{run, walk} --> {move}
failed:
拉回原地
2、攻击
{物理攻击} --> {物理攻击状态}
{魔法攻击} --> {魔法攻击状态}
failed:
只播放攻击动作, 不播放后续的特效
3、冲撞
{rush} --> {冲撞状态}
{rushed} --> {被冲撞状态}
4、受伤
{beHit} --> {hurt}
5、死亡
{die} --> {死亡状态}
6、采集
{gatherItem} --> {采集状态}
实时战斗系统问题锦集
1、人物动作处理策略
由于某个原因(网络延迟等), 当前正在处理的动作尚未结束(比如移动尚未到达目的地), 此时又收到另外一个要处理的动作协议,这时候的处理策略。
a、直接将人物状态设置到当前动作的目标状态, 然后开始新的动作。
b、按正常流程处理当前动作, 并且把要处理的动作入队, 待当前动作完成, 再依次处理动作队列里的内容。
问题衍生:如果把问题放大化, 即当前动作尚未结束, 后面收到一串待处理的动作, 此时的处理策略。
有可能出现的情况:
a、正在移动, 网络送来攻击行为 -->位置不一致
b、正在攻击, 网络送来移动行为 -->位置不一致
c、正在攻击, 网络送来新的攻击行为 -->表现不一致
处理原则:优先保证位置一致,其次保证表现上的一致性。
处理策略(实际上这里的动作处理, 仅仅是影响人物的表现, 还有坐标位置):
动作按处理的紧急:
<1>可以延迟处理的,放入队列缓存
<2>需要立即处理的(如冲撞, 不立即处理的话,冲撞和被冲撞的表现不一致了。如怪物正在攻击(表现攻击动作))
2、技能释放的处理策略
技能分类:
按技能的释放方式:主动、被动
按攻击目标的数量:群攻、单体
按是否需要目标:需要、不需要
按是否魔法锁定:锁定、不锁定
按施法距离:近身、远程
按作用目标:只能对自己、只能对队友、只能对敌人
技能释放的前提条件:
cd、距离、魔法量、目标
技能释放的要素:
释放人、目标、方向、 目标点
<1>从当前位置释放,作用于目标(或目标点)(要判断施法距离)
<2>在当前位置朝当前方向释放技能(战士技能)
<3>在当前位置朝鼠标方向释放技能(shift+左键攻击或者两个比较特殊的技能(地狱冰封,极光电影))
<4>施加于自身(可以合并到<1>, 只是不用判断施法距离)
特殊案例:
群体治疗术、群体隐身术(作用于当前鼠标位置)
单体治疗术、单体隐身术(作用于当前鼠标所在的目标, 如果没有目标,作用于自身)
3、打击感的体现
4、鼠标和键盘按着不放进行操作的延时机制
如果按着鼠标或者键盘不放,一秒钟可以触发次数:
鼠标:由程序主线程控制, window系统不会主动触发
键盘:34次/s
如果窗口样式指定了CS_DBLCLKS, 则双击鼠标产生的事件:
down->up->double click->up
否则:
down->up->down->up,此时需要使用者根据一定的规则自己检测并生成双击事件。
客户端ARPG角色行为模型的更多相关文章
- Lodop客户端本地角色注册号常见误区
之前写过一篇关于Lodop和c-lodop注册号的区别:LODOP.C-LODOP注册号的区别第一种角色客户端本地打印角色是最常见的角色,最常见的场景,关于c-lodop云打印,它的第一种角色是取代L ...
- GJM : 基于Actor模式的c#网络游戏服务器的实现和Unity游戏客户端的连接 [转载]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- [lua] 游戏客户端逻辑使用lua协程
我们的游戏有这样一种情景:客户端中角色需要用到一些公会的数据,但服务器不会在玩家(创角后)一进入到游戏里就推送给玩家,而是需要客户端自己在需要的时候向服务器请求公会的数据,之前的实现就是在请求消息的时 ...
- redis 系列19 客户端
一. 概述 Redis服务器是可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复.通过使用I/O多路复用技术实现的文件事 ...
- Redis实现之客户端
客户端 Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复.通过使用 ...
- redis学习笔记——客户端
Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复. 对于每个与服务 ...
- redis 笔记03 RDB 持久化、AOF持久化、事件、客户端
RDB 持久化 1. RDB文件用于保存和还原Redis服务器所有数据库中的所有键值对数据. 2. SAVE命令由服务器进程直接执行保存操作,所以该命令会阻塞服务器. 3. BGSAVE由子进程执行保 ...
- Blazor应用程序基于角色的授权
原文:https://chrissainty.com/securing-your-blazor-apps-configuring-role-based-authorization-with-clien ...
- LODOP和C-LODOP注册与角色等简短问答【增强版】
之前的简短问答:Lodop.c-lodop注册与角色简短问答.Lodop简短问答客户反馈篇 及排查步骤 及注册相关本文重新整理相关简短问答,调整问答顺序,增加相关的问答. 其他相关(非简短问答):LO ...
随机推荐
- map reduce filter
三个函数比较类似,都是应用于序列的内置函数.常见的序列包括list.tuple.str. 1.map函数 map函数会根据提供的函数对指定序列做映射. map函数的定义: map(function ...
- tee 命令基本使用方法、输出到多个文件
功能说明:读取标准输入的数据,并将其内容输出成文件.语 法:tee [-ai][--help][--version][文件...]补充说明:tee指令会从标准输入设备读取数据,将其内容输出到标准输出 ...
- JDBC连接属性
JDBC连接属性 hibernate.connection.driver_classs属性:设置连接数据库的驱动: hibernate.connection.url属性:设置所需连接数据库的URL: ...
- Objective C 基础
1,字符串加@: 不加@的是C语言字符串. 加@的代表的是OC的NSString http://www.jikexueyuan.com/course/71_2.html 2,setValuesForK ...
- ①创建项目testpackage ②在pack2.B中添加方法f ③在类A中添加如下三个成员变量:int型的私有变量i float型的变量f double型的公有变量d 在pack1.B的main方法中为对象a的成员变量f和d分别赋值为2和3 在pack2.C的main方法中为对象a的成员变量d赋值为3
package pack1; public class A { private int i; float f; public double d; public float getF() { retur ...
- jquery动态样式操作
获取与设置样式 获取class和设置class都可以使用attr()方法来完成.例如使用attr()方法来获取p元素的class,JQuery代码如下: 1 var p_class = $(" ...
- shift移动变量
1.移动变量 脚本 sh05.sh #!/bin/bash # Program # Program shows the effect of shift function # History: # // ...
- [转载] 为 Key-Value 数据库实现 MVCC 事务
http://mp.weixin.qq.com/s?__biz=MzA5ODM5MDU3MA==&mid=400086920&idx=1&sn=b8174184059e2886 ...
- 14 Using Indexes and Clusters
do not build indexes unless necessary. 索引是非常占资源的To maintain optimal performance, drop indexes that a ...
- JS事件中的对象
在触发任何事件时都会产生一个对象.如:DOM事件,window事件等,都会产生一个对象,该对象就是当前元素的事件对象. DOM事件对象 <body> <input type=&quo ...