hw cf1d2ee40a update há 3 meses atrás
..
aoi cf1d2ee40a update há 3 meses atrás
docs 6ec054be01 1 há 4 meses atrás
exchange 6ec054be01 1 há 4 meses atrás
internal cf1d2ee40a update há 3 meses atrás
league cf1d2ee40a update há 3 meses atrás
logic cf1d2ee40a update há 3 meses atrás
ops 6ec054be01 1 há 4 meses atrás
pathfind cf1d2ee40a update há 3 meses atrás
player cf1d2ee40a update há 3 meses atrás
rank cf1d2ee40a update há 3 meses atrás
scout cf1d2ee40a update há 3 meses atrás
season 6ec054be01 1 há 4 meses atrás
union 6ec054be01 1 há 4 meses atrás
CHANGE.md 6ec054be01 1 há 4 meses atrás
README.md 6ec054be01 1 há 4 meses atrás
map.go cf1d2ee40a update há 3 meses atrás

README.md

沙盒地图

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 - 战斗等待状态 <!-- - 行军状态:空闲,停留,行军,撤退,占领,采集,驻守,攻城
  • 二级状态:重伤,战斗,运输,骑乘,委托,调动,征兵 -->

行军碰撞业务梳理

行军碰撞列表

  1. 攻击列表
    1. 进攻列表 - 进入地块的部队在与 防守队列敌对部队 相交时进入 (PVP)
    2. 攻占列表 - 通过 行军-攻占 指令进入, 会参与子地块的碰撞 (PVP)
    3. 掠夺列表
    4. 攻城列表
  2. 防守列表
    1. 驻守列表 - 通过 行军-驻守 指令进入, 会参与子地块的碰撞
    2. 城防部队 - 大型城池特有的配置 (PVE)
    3. 占领列表 - 通过 行军-占领 指令进入 (PVP)
    4. 攻城列表 - 通过 行军-攻城 指令进入 (PVP)
    5. 行军列表 - 通过 行军 指令在到达目标点之前经过的地块上 (PVP)
    6. 停留列表 - 通过 行军 指令到达目标点之后停在地块上 (PVP)
    7. 调动列表 - 通过 行军-调动 指令进入 (PVP)
    8. 采集列表 - 通过 行军-采集 或者 行军-占领 完成后进入,只有资源点才有,并且只有单个部队的列表 (PVP)
    9. 城防守军 - 建筑耐久守军通用配置,攻城 指令时拆除耐久 (PVE)
    10. 地块守军 - 地图对象通用配置, 行军-占领 攻打之后进入 占领列表 (PVE)

行军碰撞顺序

  1. 以进入地块的行军对象为参照,部队进入 进攻列表 ,依次碰撞本地块上的 驻守占领攻城行军停留调动征兵采集 列表(驻守方为防守方)
  2. 驻守列表 有范围时,会扫描周围地块,不会碰撞进入 进攻列表 的队伍,只有 进攻列表 的队伍进入 防守列表 后,驻守列表 才会碰撞(驻守方为进攻方)
  3. 当攻城或者掠夺的时候(打玩家建筑或者主城),扫描主城军列表和调动列表

行军碰撞流程

  1. 行军碰撞检测
    1. 部队发起 行军 指令进行移动
    2. 每进入一个地块,先检查 进攻队列 中是否有 同盟部队,如果有,则进入 进攻队列,并设置 进攻状态
    3. 否则,依次检查 PVP 防守队列中是否有 敌对部队,如果有,则进入 进攻队列
    4. 如果 进攻队列 不为空,且 防守队列 有友军部队,则进入 防守队列
    5. 进攻队列 为空,且不与 防过队列 碰撞时,进入 行军队列,或者执行行军到达逻辑
  2. 行军碰撞过程
    1. 每个 ticker 分别从 攻击队列防守队列 中弹出 5 个部队,分别构建战斗保存到提交队列,并发送验证
    2. 战斗返回之后,败方加入 撤退队列撤退 逻辑,胜方 Push 回原来的队列
    3. 如果 进攻队列 为空,则碰撞过程结束
    4. 如果 进攻队列 不为空,但是 防守队列 为空,检查 进攻队列,把同盟部队加入 防守队列,其它继续留在 进攻队列, 再次交战
  3. 行军碰撞细节
    1. 只要进入 进攻队列 就设置 战斗(等待?)状态, 不可操作
    2. 防守队列 中的部队可以进行各自的逻辑

城战玩法梳理

攻城模式参考

  • 三谋:城池四面城墙单独配置守军、耐久,每面城墙对应一座攻城大营。占领大营可宣战,部队集结后自动列队,然后加入攻城队列。
  • 三战:城池自成一体,守军与耐久共享,攻城开启后,所有部队选择攻城次数后,行军到城池中心点加入攻城队列。

攻城设计

  • 宣战模式参考三谋,攻城模式参考三战
  • 宣战阶段:城池四面配置攻城大营,占领可宣战,部队集结后自动列队。
  • 攻城阶段:所有部队行军到城墙位置,加入先城池中心地块的行军对象发生碰撞,再加入攻城队列(这个过程所有攻城联盟共享)。

技术设计

配置

  • 城池与攻城大营之间的关联关系
  • 城池每一面城墙可攻打的坐标点
  • 攻城大营的主力部队与拆迁部队的坐标点,与城墙攻打点的关联
  • 主力部队与拆迁部队的出兵时间

逻辑

  1. 攻打攻城大营
    1. 点击 攻城大营 发送 攻城 指令
    2. 部队行军到 攻城大营 墙上 (非 攻城 指令不可行军,寻路要特殊处理,方法 TODO),先碰撞再加入 攻城队列
    3. 攻城攻城结束 逻辑(会根据建筑类型走不同的逻辑)
    4. 攻城大营攻城结束的逻辑为:修改攻城大营所属为我方联盟ID
  2. 攻城大营建造
    1. 占领 攻城大营 后才能修建,需要做权限判断,和数量限制
    2. 攻城大营 修建完成时,做法一是替换 攻城大营 为另一个不同配置的 攻城大营, 需要在 AOI 做一次 enterleave; 做法二是用同一个 攻城大营 配置,只记录一个 是否修建 的状态,只在 AOI 做一个 update, 但是需要配置两套属性
  3. 宣战
    1. 点击 城池 选择 宣战 指令,并选择 宣战时间, 此时需要判断是否满足条件
    2. 宣战 的联盟和状态记录到 城池 或者 攻城大营 上?
    3. 设置 宣战阶段 并开始 ticker 检查,如果时间到了,进入 攻城阶段,开始 出兵攻城 逻辑
    4. 任务阶段只要 攻城大营 被攻破,进入 攻城失败 流程
  4. 集结
    1. 点击 攻城大营 发送 集结 指令,部队通过 行军-集结 指令进入 行军 状态,并设置子状态为 集结;或者分为两个一级状态 集结中集结
    2. 行军到 攻城大营 后,设置为 集结 状态,并加入地块的 集结队列, 同时把集结点加入回城点选项并设置为默认回城点
  5. 出兵
    1. 宣战阶段 结束,进入 攻城阶段, 未 集结 的部队可以手动请求 攻城 指令
    2. 每个 ticker 选择获取地块上的 集结队列 并弹出一批主力部队,行军到前排点;
    3. 主力部队出完后,每个 ticker 选择获取地块上的 集结队列 并弹出一批拆迁部队,行军到后排点;
    4. 经过一段时间后,每个 ticker 把前排主力行军到城墙点进入 攻城队列,进行 攻城 逻辑
    5. 每次驻城部队的战斗返回,检查驻城部队数量是否为 0,每个 ticker 把后排拆迁行军到城墙点进入 攻城队列,进行 攻城 逻辑
    6. 以上出兵逻辑只会做一次,在 攻城大营 记录状态
    7. 如果 主力部队拆迁部队 数量极度不均衡,甚至某一个为空,策划分配逻辑感觉有点问题(如何均匀排列,主力为0拆迁不动)
  6. 攻城
    1. 以城池中心坐标的地块作为锚点,遍历所有子地块,分别处理地块的逻辑
    2. 碰撞的驻守队列会额外检查父地块
    3. 如果碰撞完成了,就会构造 驻城部队 的战斗,战斗验证成功 驻城部队 减一,并且进攻方增加 2 秒 CD
    4. 驻地部队 为空时,先增加 3 分钟 CD(需要状态记录),再构建 守军部队 战斗,战斗验证成功扣除耐久,并设置 3 分钟 CD
    5. 过程中记录部队攻城数据
    6. 城池耐久和驻城部队受损,触发 回复,每过 30 分钟恢复驻城部队数量和耐久(走通用建筑回复逻辑)
  7. 攻城成功
    1. 耐久为 0 时,攻城成功,把城池所属设置最后一击的玩家联盟ID
    2. 如果首次攻占的,发奖励,记排行榜
    3. 所有部队退回集结点
    4. 如果城池有守军,退回各自的主城
    5. 如果有其它攻城同盟,执行 攻城失败 逻辑
  8. 攻城失败
    1. 攻城 过程中,检查是否超时,超时则失败
    2. 部队回到集结点
    3. 等待 CD 后可以再次 宣战
    4. 不会影响其它联盟的 攻城 逻辑