Published on

slg地图

最近公司游戏打算内置一个slg玩法, 所以准备做一个slg大地图, 这两年和场景打了不少交道, 一直在负责mmo的场景相关。 不过slg的地图设计会和mmo的不太一样, 这里写下初步的设计。

地图最小单位是Tile, 一个11的格子, 对于一个nm的大地图来说,即便是1024*1024,也有着上百万的格子, 需要尽可能的利用多线程的能力, 所以需要对地图进行分割。

需要有一个map_service服务, 这个服务的职责是将一个n*m的大地图切割成x个shard, 以及将对应的cmd分配到shard服务执行, 或者将多个shard服务的执行结果整合返回。

shard_service服务, 由n*m个Block组成, Block管理下面的Tile, 这里的Block有什么作用呢, 一个索引单位, 通过位置xy可以快速找到对应的Block, 这里也承载着aoi的功能, 类似于格子算法,不过这里并不是一个Tile一个格子, 或者也可以说是灯塔, 灯塔管理者下面的实体, 实体有变化可以通知到对应的人, 将扫描缩小到一个较小的范围, 这里或许会有一些浪费, 例如当关注区域在两个BLock中间的时候,实际上两边的变化并不需要通知到, 但是这里是一个Block为单位, 所以还是会通知到客户端。

单个Tile有是否占用的状态, 这个很容易想到可以用位图来做, 省内存而且可以高效查询。

一个march_service, 专门维护行军的状态。

关于行军状态, 目前暂时不需要做寻路, 因为直接无视碰撞, 也就是直线行走, 这里可以直接记录开始位置,结束位置, 然后直接计算出当前在哪个位置就行, 不需要一直做实际移动, 所以问题在于如何通知给其他人, 这里我想简单设计, 对于单次行军, 计算出, 经过了多少个Block, 什么时间点到达这个Block, 当到达了某个Block, 就将状态推送给这个Block, 那么, 关注了Block的玩家就可以直到这里有人行军经过。

还有一个随机位置问题,这是一个常见的需求,要在地图里随机生成怪物资源等等, 我想, 这里也可以用Block解决, 策划需要划出一片地方, 也就是某些资源会在这片地方随机生成, 那么这里就会涉及多个Block, Block里面, 只需要记录, 还有没有空位, 那么我们只需要随机两次, 第一次, 找到一个有空位的Block, 第二次, 找到这个Block里面的所有空位, 再随机出一个位置, 因为单个Block不会特别大, 所以这个消耗看起来是可以接受的。


今天睡醒, 针对这里的设计, 突然想到, 针对slg里面的地图实体, 建筑, 资源点, 怪物, 守卫, 营地, 玩家主城, 等大量实体, 几乎都是静态的。

为什么这么说, 建筑, 资源点, 基本不变, 怪物和守卫等, 可能根据需求而定,目前需求来说,是不移动的, 玩家主城, 会出现迁移, 占领等, 发生变化的时候, 也是删除, 然后在另一个地方新增, 而不是持续的移动。怪物被击杀后刷新, 也是类似的原理。

和之前做的mmo不同, mmo里面有大量实体会频繁的持续移动, 并且玩家大部分情况下, 视野的关注范围是自己附近。

而slg这里不一样, 玩家是以上帝视角去关注, 会以查询的方式随时查询各个地方的状况。

那么, 对于我认为几乎静态的对象, 可以用空间索引算法, 做出一个高效查询的结构, 即便维护修改有一定的成本, 但对于大量查询, 少量移动来说, 应该是合理的。

对于非静态的部分, 是行军, 我在上面也说了, 我们目前需求上, 行军无视碰撞, 这里做的很简单, 不做成真正的持续移动行军, 而是按“时间驱动的行军过程”处理, 维护行军状态机、起止点、路线、时间戳和关键事件。

如果行军需求升级了呢, 不再这么简单, 我想不影响上面的结构, 因为本身行军已经是单独抽离出来的一个服务, 行军可以单独升级算法, 如果怪物守卫等也出现了持续移动, 那么也可以当成是一种行军。

我对slg游戏玩的不算多, 仅针对玩过的游戏得出以上结论, 不知道对于复杂的slg游戏, 这个结论是否成立。