May 19, 2022

RogueLike 原型开发工具

我很喜欢 RogueLike 游戏,我是说字面意义上的像 Rogue 那样的游戏 。在这种游戏中,画面是最不重要的部分,只要能清晰表达出游戏需要的交互意义就够了。

我对用字符拼凑出来的游戏界面有种特别的爱好,小时候自制游戏就是从 text mode 开始的。 在今天,如果只是想验证一下某个游戏的原型,一个 Rogue 风,text mode 的交互界面,可能还是最省事的。因为你不必刻意的去准备美术素材,考虑这些素材如何和代码协同工作,制定繁杂的工作流。为游戏创作一点有趣的 ascii art 不仅不用太长的时间,可能还是写代码过程中的一点有趣的调剂。

前段时间在做项目中一个试验性模块时,我尝试做了一个简单的 Lua 库 帮助我用 text mode 搭建交互。最近又碰到一个更复杂的需求,评估了一下,基于 SDL2 做一个更完善一点的 RogueLike 库或许更一劳永逸。

阅读全文 "RogueLike 原型开发工具" »

May 07, 2022

游戏数据的展示

游戏的业务逻辑到画面呈现的过程和 GUI 系统在结构上有相似之处,又有一些不同点。

在软件设计时,我们通常倾向与把数据和展示分离。在 GUI 系统中,数据通常被称为 Model ,展示被称为 View 。典型的 MVC (及其衍生品 MVP/MVVM 等)模式就是建立在此基础上。业务逻辑修改 Model ,经过展示模块,把 Model 映射到 View 中呈现给用户。

传统的面向对象设计中,很多人倾向于按对象划分,每个对象有数据部分和展示部分。对于游戏,我不喜欢这种设计。我更倾向于把数据和展示完全分离,再用 id 把同一个对象关联其数据模块和展示模块中分离的实体。这是因为,游戏尤其是虚拟世界广阔的游戏,屏幕展示的仅仅是虚拟世界很小的一部分。在同一时间,大部分的数据都不必展示。甚至数据也未必存在于本地的内存中。

我倾向于把游戏软件切分为 gameplay 和 view 两个完全分离的模块,各自有独立的数据结构和设计。gameplay 应该可以完全独立于 view 运转,而让图形引擎关心且只关心 view 部分。在制作游戏软件时,如何解决好 gameplay 的信息如何在 view 模块中展示出来,就成了必须考虑的设计点。

阅读全文 "游戏数据的展示" »

April 19, 2022

蒙皮数据的压缩

传统的蒙皮数据需要在模型顶点上存两组数据,其一为该顶点受哪些骨头的影响,其二为受这些骨头影响的权重。因为 GPU 的对齐影响,通常游戏中会将同一顶点受影响的骨头数量上限设为 4 。如果不做任何优化,骨头总数在 256 以下时,每个顶点需要 4 个字节保存骨头编号,再用 4 个 float 表示分别的权重。

因为权重之和总是为 1 ,所以,只用 3 个 float 也是可以的(第四个权重通过简单的计算就可以得到)。

因为权重总是 0-1 之间的数字,所以 32bits float 的精度远超所需,我们也并不需要浮点数。所以用 16bits [0,65535) 甚至 8bits (0,255] 来表示 0-1 的权重也够了。

所以,蒙皮一般至少占用 64bit 的定点数据 (4+4 bytes) 。

如果想进一步压缩,就需要一些复杂的技巧了。这两天读了几篇关于动画蒙皮数据压缩的 paper ,挺受启发的。

首先是这一篇 Vertex-Blend Attribute Compression

阅读全文 "蒙皮数据的压缩" »

April 12, 2022

Lua binding 中正确的 callback

今天修了个 skynet 中的 bug :在 Lua 中重新设置 callback 函数会失效。

skynet 已经有 10 年的历史了,十年前,某些 lua 的惯用法我还不太熟悉。比如,如果一个 C 框架的接口设置了一个回调函数,如何将其 binding 到 Lua 函数上,我当初没有想到好的方法。

最为传统的方法是把 Lua callback function 放到 Lua 的注册表中。当 C 框架的 callback 发生时,在 C 版本的 callback 函数中去查找 Lua 注册表中的 callback function ,然后用 pcall 执行它。

几乎大部分 C 模块的 lua binding 都用这个方案来封装 callback 函数。但它有一个最大的问题:调用 lua callback function 时,Lua 的状态机 L 如何传递。

阅读全文 "Lua binding 中正确的 callback" »

March 29, 2022

全民大规模新冠检测方案的一些想法

今天吃饭的时候和同事聊起最近上海深圳等超大城市全民新冠检测的问题。我认为现有方案有极大的改进空间。

千万级的全民检测,需要动用的资源是非常可观的,如果我们能优化这个过程,收益也会极其可观。现有的集体检测已经是相对独立个体分别检测做过优化了:通常是很多人放在一起混检,这样减少了检测成本。但我认为这是远远不够的。

现在自测盒的成本已经很低,至少一个自测盒的零售价格远低于我自己去医院做一次检测。所以我认为,如果全民自测的话,单从检测成本上来说,可能也是划算的。而且,对于群体检测,完全可以全家用同一个检测盒,这样如果是阳性,家庭成员就算没有全部感染,也最少是个密接。这比社区混检有效很多。

至于自测盒可能准确度不高的问题,完全可以自行多次自测来弥补。而目前采取的社区集体混检的形式,反而造成了人群密集,增加了病毒传染的风险。

但是,在千万级人口的城市中全民自测,显然结果是不可信的,这是我下面想谈的主要问题:如何设计一个方案,即降低了全民检测的成本,又能保持结果的可信度。即:如果有人自测发现自己阳性(或干脆不想自测),因为恐惧隔离而瞒报的问题。

阅读全文 "全民大规模新冠检测方案的一些想法" »

March 23, 2022

层次组件的问题

最近思考了 ECS 框架中的一些问题。

具体业务中,有许多组件的构成非常复杂,本质上数据是有层次结构的。用一个二维表的结构很难清晰表述。它还牵扯到另一个问题:是否需要支持一个实体有多个统一类型的组件。例如,玩家实体身上多个装备栏、多个技能 Buf 该如何表达?

我有一些不成熟的想法,还没有具体落地,先记录一下:

阅读全文 "层次组件的问题" »

March 18, 2022

effekseer 的 shader 转译

我们的游戏引擎一开始是自己实现的粒子系统 。在实现完之后,做配套编辑工具的阶段,开发工具的同学建议换成其它开源的成熟系统,这样就不必花太多精力在维护一套工具了。

他推荐了 Effekseer ,并完成了 Effekseer 和我们引擎的整合工作。

最近,我在推特上看到有个同学也在寻找 bgfx 下的粒子系统的方案,他希望有一个比 bgfx 自带粒子演示更完善的东西,同时又表示整合 popcorn 实在是过于麻烦。我向他推荐了 effekseer 。

阅读全文 "effekseer 的 shader 转译" »

February 25, 2022

ECS 中的对象引用

我们很难避免在 ECS 系统中相互引用 Entity 。而我对 ECS 模式的使用是鼓励去引用的。为此,我对许多常见依赖引用的模式给了对应的解决方案。

最近的一个 luaecs 开发版本中,提供了一种 Lua 层面的引用方案 :在创建 Entity 时,可以指定一个 table 作为该对象的引用。系统会更新它,让它保持为一个有效的(形如 select 过程中的)迭代器。这样,业务层就可以随时通过它 sync entity 中的数据。

我一直不是太喜欢这个方案,所以一直再考虑不同的解决方法。念念不忘 必有回响。昨天,我尝试了一个新的、更满意一点的方案。

阅读全文 "ECS 中的对象引用" »

February 23, 2022

信息茧房

最近一个月,无论我打开推特,还是微博豆瓣,每天都被“徐州八孩母亲事件”刷屏。在公司吃工作餐的时候,也和同事聊过这个事件。从我的角度看,此事的热度之高,持续时间之久,近年罕见。能读到我的 blog 这一篇的同学,相信都对这件事的来龙去脉不会太陌生。如果你不了解,那么 google 一下“徐州八娃女”或是“丰县铁链女” 就能找到很多信息。

但是,我很清醒的知道,热度只存在于自己所在的这么个小圈子。我相信在中国社会中,不知道此事的人群才是大多数。就算在微博上百万转发,也不会有所改变。毕竟,翻墙的人还是少数。而墙内的微博微信,都帮助人们把各自的信息茧房建设的很好。

阅读全文 "信息茧房" »

February 14, 2022

Factorio 的乐趣

我玩 Factorio 有记录的时间已经超过 2000 小时了。从它上 steam 的第一天我就开始玩,但大部分时间花在最近两年。

我在 steam 上的推荐语最初只有一句话,很能代表我初见这个游戏的感觉:“这个游戏满足了我对城市建设、物流调配、自动化建造、甚至还有铁路模拟,等等类型游戏的一切梦想。”

小时候最爱凯撒系列,它代表了当时城市建设和物流游戏的巅峰,我从中发现了无穷的乐趣,这是让我第一天就买下 Factorio 的缘故。

阅读全文 "Factorio 的乐趣" »

January 29, 2022

支持惰性展开和差异更新的 Lua 表

年前最后两天,陆续给我们组的同事批了假,都回家过年了。我留守在公司做点项目无关的东西。

最近在 skynet 的讨论版有人讨论配置表的更新问题。这几年,不管在公司内,还是从外部听见,总有人在讨论这个问题。我重新理了一下需求:

  1. 数据以 Lua table 的形式提供:支持 Lua 所有的内置类型:整数、浮点数、子表 、字符串、布尔量。可选支持函数、指针。
  2. 数据表通常有很多(冗余)数据,但大多数情况下只会用到一下部分,初始化的过程应尽量快。
  3. 如有可能,少占内存。数据表属于不变数据,应尽可能的在多个 VM 间共享。数据表应对 GC 有尽可能少的影响。
  4. 可以在不关闭 VM 的前提下,更新数据。
  5. 访问数据表应遵从 Lua 的使用惯例,并尽可能和原生表性能一致。

阅读全文 "支持惰性展开和差异更新的 Lua 表" »

January 18, 2022

我们需要一个怎样的动画模块

最近这个项目,里面有大量的机械动画:采矿机、抽水泵、发电机、组装机、机械臂、等等。

我发现,我们自研的引擎的动画模块其实是不够用的。

我们在设计引擎的动画模块时,是按过去经常做的 MMORPG 里的需求来设计的。主要是控制 Avatar 的动作:走、跳、跑、攻击、等等。在从制作软件导入动画数据后,引擎需要做的加工主要是动画和动画之间的融合。例如,从走路过渡到跑步。还有在动画中加入一些运行时的控制:例如转头盯着物体、调整脚掌贴合地面。这些是用 IK 模块来实现的。

阅读全文 "我们需要一个怎样的动画模块" »

January 10, 2022

流体系统

我们最近在开发的类似异星工厂的游戏中,一个重要的物流子系统就是流体系统。我个人觉得,它是所有子系统中最难实现的一个。

Factorio 的流体系统也经历过多次改动。在开发日志上有记载的就有三次:New fluid systemFluid optimisationsNew fluid system 2。作为一个 5 年近 2000 小时的老玩家,我感觉的到流体系统的修改一直在做,不只这三次;而且直到今天,流体系统在游戏中依然会出现一些反直觉的行为。

一个好的流体系统非常难兼顾高效和拟真。在 Factorio 的仿制品戴森球计划上线时,我饶有兴趣的想看看它是怎么做流体管道的,但让我失望的是,它几乎把流体系统砍掉了。

我在 Factorio 中非常喜欢流体系统的伴生玩法。所以,在我们的游戏中,即使我没有做传送带,也要做一个流体子系统出来。我们的设计直接参考了前面提到的几篇 blog ,并加入了一些我自己的想法。

阅读全文 "流体系统" »

Misc

Categories

Archives

Recent Comments