« ejoy2d sprite pack 的空间优化 | 返回首页 | 可靠 UDP 传输 »

用 2d 缩放及斜切变换模拟斜视角下的旋转

过年回武汉家中,只有一台 2000 块的一体机可以用,自然是跑不动 3d 游戏的。我挑了一款 Invisible Inc 玩,居然很流畅。

这是款 XCOM like 的策略游戏,场景是 isometric 的。但是用 Q E 两个键可以旋转场景,虽然静止下来只有四个方向,但是旋转过程却以动画方式呈现。这让我一度认为它的场景是基于 3d 模型制作的。但令人惊讶的是,在低配置的一体机上却非常流畅。相比较,我最近在玩的 XCOM 2 却在 GTX 550 显卡上也有卡顿。

我仔细观察后,发现其实 Invisible Inc 的场景里的物件都只是 2D 图片。甚至只有正面和背面两张图,通过左右镜像得到了四个视角。它的旋转速度很快,并加了一定的模糊效果,欺骗了人眼。其实只有地板和墙壁是真正旋转的,其它物件只有坐标在做旋转,而图片本身在旋转过程中并没有变化。

也就是说,它的引擎其实是基于 2D 制作的,模拟出了 3d 才有的视觉效果。

我对墙壁的旋转很感兴趣,一开始以为是预渲染了若干张图。后来试着解开了 .kwad 资源包(可自行 google 到工具)发现里面的资源图片只有一或两张。ps. 图片是用 zlib 压缩过的 RGBA 位图,格式也可以 google 到。

以门为例,只有正面(或背面)的矩形图片。想来是在引擎中变形为斜视角下需要的平行四边形。

我简单推导了一下变换矩阵,需要一点初中平面几何知识就够了。

以 30 度倾角为例,x:y 大约是 2:1 。所以斜切变换时的转角是 arctan(tan(x)/2) 度,变换矩阵为 [1, tan(x)/2, 0 , 1, 0, 0 ]

另外需要先在 x 轴上做一个缩放,缩放比为 cos(x) 。

虽然 tan 在 90 度时会变成无穷大,但是两个矩阵相乘后,tan 函数消失了,变成了 sin 。最终的变换矩阵为:

[cos(x), sin(x)/2 , 0, 1, 0, 0 ]


我从 Invisible Inc 的资源包里解了一张门的图片如下:

wall.png

我们可以用 css 的 transform 给一个变换矩阵 style="transform: matrix(0.707, 0.3535, 0,1,0,0);" ,模拟在 30 度倾角下,旋转 45 度的效果:

wall.png

当然,因为这个是仿射变换,没有透视,所以还是会有些怪怪的。


最后,Invisible Inc 是个相当不错的游戏,推荐。

创意工场里有中文 Mod ,但是版本比较老,不推荐。如果想用需要自己改一下。

有两个问题:

  1. 游戏的排版引擎是靠空格分词折行的,汉化 mod 制作的同学不清楚这点,为了避免长句子后半截断了,结果把字体调的特别小,看起来很难受。其实只需要在长句子的每个汉字后加个空格就可以解决分行的问题了,这个写个脚本处理一下翻译文本即可。另外,字库要重新做一下。

  2. 游戏之前的格式化串是用的 C 风格,比如用 %d 替代运行时要插入的数字。但是最新的引擎改成用 {1} 引用第一个参数,{2} 引用第 2 个参数这样的了,所以在汉化 mod 用于最新版时,会出现大量 第 %d 天这样的文字,看不到数字,很干扰游戏。需要自己重新在 credit 界面按 ctrl insert, 弹出控制台,输入 localize 重新导出一份文本改一下。

以上我过年在家临时改了一份,上班后没带过来,懒得重新弄了。本来游戏就不太需要汉化就可以玩的。

ps. 为什么游戏引擎要修改文本格式化方案呢?这是因为在不同语言中,单词的次序可能是不一样的。在英语里,说的是 A 导致 B ,换到中文(或其他语言) 中,可能表述方式变成了 B 被 A 导致。两个词的次序就反了。如果用 C 风格的格式化,依赖参数传递次序,翻译就乱了。(我简单校对了一下原来的汉化文本,就有这种乱序错误)

另外,升级后的格式化方案还可以对输入参数做多次引用,以解决一些语言中词需要变形的需要。比如老版本中,%d turn(s) 在新版本中可以写成 {1} {1:turn|turns} 。根据第一个参数是否为 1 来选择使用 turn 还是 turns 。

这些是游戏做本地化的经验,在此记录一笔。

Comments

这么多年才知道,云风大大竟然也是武汉人!
不同语言的单复数上下文太不一样,我认为还是直接区分为两个不同的localize key对进行翻译的非程序员来说更简单粗暴灵活。
云风大侠对于VR有什么见解
开眼界了, 数学运算在图形学上的运用. 没想到还能用css transform来验证变换矩阵
初级程序员前来膜拜
初级程序员前来膜拜
模糊本身就需要大量运算。
有理有据。。

Post a comment

非这个主题相关的留言请到:留言本