沙盒地图
Actor分类
- logic actor: 驱动整个地图的业务逻辑,管理 map table 对象的更新
- aoi actor: 管理地图 AOI,根据对象类型分层
- pathfind actor: 地图寻路处理,构造多对象并发处理寻路
- pusher actor: 推送地图数据给客户端
- player actor: 处理玩家在地图上的业务数据与逻辑请求
- league actor: 处理联盟在地图上的业务数据与逻辑请求
- ops actor: 对外 API 接口
服务启动数据加载思路
- 创建各层 actor 前把所有的 map table 加载到内存
- 各层 actor 通过 map table 构造自己的副本数据
- map table 只在 logic actor 管理,数据变更时通知其它各层 actor 更新数据
AOI分层思路
- 把不同类型的对象分为多层管理,它们独立运行各自actor上,每层有专属的AOI同步
- 当玩家登录游戏时,传入玩家的坐标到各层,并进行AOI的enter()操作
- 当玩家拖动屏幕时,传入玩家的坐标到各层,并进行AOI的move()操作
- 当玩家退出下线时,传入玩家的坐标到各层,并进行AOI的leave()操作
- 行军层用于军队的寻路,当玩家坐标在当前灯塔范围内时进行AOI对象同步
地图对象分类
- 地图建筑:城池,关卡,码头
- 玩家建筑:联盟驻地,主城,其它玩家建筑
- 资源点
- 怪物
- 行军对象
A星寻路思路
- 大地图分区域,区域之间只有少数连接点
- 分层寻路
- 区域之间寻路:找到区域之间的连接点
- 区域内部寻路:起点 -> 连接点A, 连接点A -> 连接点B, 连接点B -> ... 连接点N, 连接点N -> 终点
- 不规则区域表示法:使用多边则,保存多边形的所有顶点坐标
行军对象状态梳理
- 0 - 空闲状态
- 1 - 停留状态
- 2 - 撤退状态
- 3 - 占领状态
- 4 - 采集状态
- 5 - 驻守状态
- 6 - 攻城状态
- 7 - 调动状态
- 8 - 集结状态
- 9 - 征兵状态
- 10 - 到达状态
- 100 - 行军状态
- 101 - 调动行军状态
- 102 - 集结行军状态
- 103 - 运输回城状态
- 200 - 战斗状态
- 201 - 战斗等待状态
<!-- - 行军状态:空闲,停留,行军,撤退,占领,采集,驻守,攻城
- 二级状态:重伤,战斗,运输,骑乘,委托,调动,征兵 -->
行军碰撞业务梳理
行军碰撞列表
- 攻击列表
- 进攻列表 - 进入地块的部队在与
防守队列 的 敌对部队 相交时进入 (PVP)
- 攻占列表 - 通过
行军-攻占 指令进入, 会参与子地块的碰撞 (PVP)
- 掠夺列表
- 攻城列表
- 防守列表
- 驻守列表 - 通过
行军-驻守 指令进入, 会参与子地块的碰撞
- 城防部队 - 大型城池特有的配置 (PVE)
- 占领列表 - 通过
行军-占领 指令进入 (PVP)
- 攻城列表 - 通过
行军-攻城 指令进入 (PVP)
- 行军列表 - 通过
行军 指令在到达目标点之前经过的地块上 (PVP)
- 停留列表 - 通过
行军 指令到达目标点之后停在地块上 (PVP)
- 调动列表 - 通过
行军-调动 指令进入 (PVP)
- 采集列表 - 通过
行军-采集 或者 行军-占领 完成后进入,只有资源点才有,并且只有单个部队的列表 (PVP)
- 城防守军 - 建筑耐久守军通用配置,
攻城 指令时拆除耐久 (PVE)
- 地块守军 - 地图对象通用配置,
行军-占领 攻打之后进入 占领列表 (PVE)
行军碰撞顺序
- 以进入地块的行军对象为参照,部队进入
进攻列表 ,依次碰撞本地块上的 驻守、占领、攻城、行军、停留、调动、征兵、采集 列表(驻守方为防守方)
- 当
驻守列表 有范围时,会扫描周围地块,不会碰撞进入 进攻列表 的队伍,只有 进攻列表 的队伍进入 防守列表 后,驻守列表 才会碰撞(驻守方为进攻方)
- 当攻城或者掠夺的时候(打玩家建筑或者主城),扫描主城军列表和调动列表
行军碰撞流程
- 行军碰撞检测
- 部队发起
行军 指令进行移动
- 每进入一个地块,先检查
进攻队列 中是否有 同盟部队,如果有,则进入 进攻队列,并设置 进攻状态
- 否则,依次检查 PVP 防守队列中是否有
敌对部队,如果有,则进入 进攻队列
- 如果
进攻队列 不为空,且 防守队列 有友军部队,则进入 防守队列
- 当
进攻队列 为空,且不与 防过队列 碰撞时,进入 行军队列,或者执行行军到达逻辑
- 行军碰撞过程
- 每个 ticker 分别从
攻击队列 和 防守队列 中弹出 5 个部队,分别构建战斗保存到提交队列,并发送验证
- 战斗返回之后,败方加入
撤退队列 走 撤退 逻辑,胜方 Push 回原来的队列
- 如果
进攻队列 为空,则碰撞过程结束
- 如果
进攻队列 不为空,但是 防守队列 为空,检查 进攻队列,把同盟部队加入 防守队列,其它继续留在 进攻队列, 再次交战
- 行军碰撞细节
- 只要进入
进攻队列 就设置 战斗(等待?)状态, 不可操作
防守队列 中的部队可以进行各自的逻辑
城战玩法梳理
攻城模式参考
- 三谋:城池四面城墙单独配置守军、耐久,每面城墙对应一座攻城大营。占领大营可宣战,部队集结后自动列队,然后加入攻城队列。
- 三战:城池自成一体,守军与耐久共享,攻城开启后,所有部队选择攻城次数后,行军到城池中心点加入攻城队列。
攻城设计
- 宣战模式参考三谋,攻城模式参考三战
- 宣战阶段:城池四面配置攻城大营,占领可宣战,部队集结后自动列队。
- 攻城阶段:所有部队行军到城墙位置,加入先城池中心地块的行军对象发生碰撞,再加入攻城队列(这个过程所有攻城联盟共享)。
技术设计
配置
- 城池与攻城大营之间的关联关系
- 城池每一面城墙可攻打的坐标点
- 攻城大营的主力部队与拆迁部队的坐标点,与城墙攻打点的关联
- 主力部队与拆迁部队的出兵时间
逻辑
- 攻打攻城大营
- 点击
攻城大营 发送 攻城 指令
- 部队行军到
攻城大营 墙上 (非 攻城 指令不可行军,寻路要特殊处理,方法 TODO),先碰撞再加入 攻城队列
- 走
攻城 和 攻城结束 逻辑(会根据建筑类型走不同的逻辑)
- 攻城大营攻城结束的逻辑为:修改攻城大营所属为我方联盟ID
- 攻城大营建造
- 占领
攻城大营 后才能修建,需要做权限判断,和数量限制
攻城大营 修建完成时,做法一是替换 攻城大营 为另一个不同配置的 攻城大营, 需要在 AOI 做一次 enter 和 leave; 做法二是用同一个 攻城大营 配置,只记录一个 是否修建 的状态,只在 AOI 做一个 update, 但是需要配置两套属性
- 宣战
- 点击
城池 选择 宣战 指令,并选择 宣战时间, 此时需要判断是否满足条件
- 把
宣战 的联盟和状态记录到 城池 或者 攻城大营 上?
- 设置
宣战阶段 并开始 ticker 检查,如果时间到了,进入 攻城阶段,开始 出兵 和 攻城 逻辑
- 任务阶段只要
攻城大营 被攻破,进入 攻城失败 流程
- 集结
- 点击
攻城大营 发送 集结 指令,部队通过 行军-集结 指令进入 行军 状态,并设置子状态为 集结;或者分为两个一级状态 集结中 和 集结
- 行军到
攻城大营 后,设置为 集结 状态,并加入地块的 集结队列, 同时把集结点加入回城点选项并设置为默认回城点
- 出兵
宣战阶段 结束,进入 攻城阶段, 未 集结 的部队可以手动请求 攻城 指令
- 每个 ticker 选择获取地块上的
集结队列 并弹出一批主力部队,行军到前排点;
- 主力部队出完后,每个 ticker 选择获取地块上的
集结队列 并弹出一批拆迁部队,行军到后排点;
- 经过一段时间后,每个 ticker 把前排主力行军到城墙点进入
攻城队列,进行 攻城 逻辑
- 每次驻城部队的战斗返回,检查驻城部队数量是否为 0,每个 ticker 把后排拆迁行军到城墙点进入
攻城队列,进行 攻城 逻辑
- 以上出兵逻辑只会做一次,在
攻城大营 记录状态
- 如果
主力部队 和 拆迁部队 数量极度不均衡,甚至某一个为空,策划分配逻辑感觉有点问题(如何均匀排列,主力为0拆迁不动)
- 攻城
- 以城池中心坐标的地块作为锚点,遍历所有子地块,分别处理地块的逻辑
- 碰撞的驻守队列会额外检查父地块
- 如果碰撞完成了,就会构造
驻城部队 的战斗,战斗验证成功 驻城部队 减一,并且进攻方增加 2 秒 CD
驻地部队 为空时,先增加 3 分钟 CD(需要状态记录),再构建 守军部队 战斗,战斗验证成功扣除耐久,并设置 3 分钟 CD
- 过程中记录部队攻城数据
- 城池耐久和驻城部队受损,触发
回复,每过 30 分钟恢复驻城部队数量和耐久(走通用建筑回复逻辑)
- 攻城成功
- 耐久为 0 时,攻城成功,把城池所属设置最后一击的玩家联盟ID
- 如果首次攻占的,发奖励,记排行榜
- 所有部队退回集结点
- 如果城池有守军,退回各自的主城
- 如果有其它攻城同盟,执行
攻城失败 逻辑
- 攻城失败
攻城 过程中,检查是否超时,超时则失败
- 部队回到集结点
- 等待 CD 后可以再次
宣战
- 不会影响其它联盟的
攻城 逻辑