跳到游戏
Hadukis

文章

差了 17 倍的瞄准线

· 阅读约 4 分钟

在弹弓游戏里,那条虚线就是和玩家之间的全部约定。 你往后拉,虚线告诉你这一发会飞向哪里,你松手。 如果虚线在说谎,就没有技巧可学,只剩运气,以及一种被游戏坑了的感觉。

ScaleSling 的第一次试玩,反馈只有两句话: 「堡垒自己会倒」和「飞的地方跟线指的不一样」。两句都是真的,而且都不是调参能解决的问题。 这篇讲的是第二个。堡垒的事有单独一篇。

那条线在干什么

不管以什么角度把龙往后拉,虚线引导都会从屏幕顶端冲出去,再也不下来。 角度陡也好,角度平也好,满力也好,轻轻一拉也好,都一样。 与此同时,龙本身飞出一条再正常不过的弧线,落在虚线从来没指过的地方。

引导线的原理,是让一个假想的抛射物随时间一步步前进:从弹弓出发,加上速度, 把重力加到速度上,重复,每隔几步放一个点。 这个循环加重力的方式,是用重力设置乘以一步的时长。

游戏底下的物理引擎不是这么做的。它把重力当作一个力来施加, 而力要通过步长的平方才变成速度的变化。 每秒六十步时,一步大约是 16.7 毫秒,所以引导线用的重力, 只有龙实际受到的大约十七分之一。 一个只受十七分之一重力的抛射物,表现正如那条线所示:一直往上,越飞越高。

在第一个谎言之上,还叠着第二个小一点的谎言。龙有空气阻力, 两秒内会吃掉它大约一半的速度。引导线没考虑这一点。 如果只修重力,得到的线会以正确的形状落下来,但落在错误的地方。

修正后的那一步只有两行:先用阻力乘速度,再加上按步长平方计算的重力。 阻力值现在放在一个共享的设置文件里,而不是藏在龙的代码里, 因为有两段不同的代码需要它,而它们绝不能再出现分歧。

用证明代替目测

检查这类修复,最诱人的办法是拉几下弹弓,看虚线看着对不对。 这个 bug 最初就是这么活下来的:一条只错一点点的线看起来挺可信, 而且没人能把同一发打两次。

所以现在有一个小脚本,运行真正的物理引擎,不需要浏览器,也不需要屏幕, 用的是游戏自己的常量。它以一系列不同的角度和力度发射一个刚体,让它一步步前进, 再把它实际的去向和引导线的算法预测的去向做比较。

修复之前,90 步之后两者已经相差 1,300 像素。修复之后,差值为零,落点精确到像素。 这个脚本一秒不到就能跑完,而且只要有人动了引导线、物理设置或龙的刚体,它就会再跑一遍。

探针也在说谎

追查这个问题的时候,我们还有一个自动玩家:一个对每个关卡开火、 然后报告哪些关卡能通关的脚本。它报告说第 2 关赢不了,第 4 关根本打不出伤害。

两个结论都是假的。如果你用的物理引擎允许刚体休眠,原因值得了解。 为了省计算量,引擎会停止模拟一段时间内没动过的东西。 一条在弹弓里等着的龙,一直没动,所以它在休眠。 给一个休眠的刚体设置速度,写进去的是一个引擎永远不会读的数字: 这一发以 17.9 的速度离开弹弓,然后原地不动,直到永远。

人类玩家从来没遇到过这种情况,因为拖动龙会让它每一帧都在移动,它一直是醒着的。 只有不经拖动直接发射的那一发会失败,而这恰恰就是自动测试会做的事。 那份报告里每一个「无法通关」,都是一条从来没动过的龙, 而我们当时已经因为它开始修改关卡材质了。

修复方法是在发射前调用一次唤醒刚体。教训则更大: 在相信一台机器说某件事不可能之前,先确认它测的那件事确实发生了。 探针现在会记录每一发飞了多远。零距离、零伤害的结果,说明的是测量工具坏了,而不是关卡太难。

对玩家来说变了什么

虚线现在就是真实的路径。不管什么角度和力度,虚线在哪里结束,龙就落在哪里, 而且这是由机器检查的,不是靠某个人眯着眼盯着屏幕。 如果你以前玩过 ScaleSling,觉得弹弓不公平,那时候它确实不公平,而现在不会了。

在这里玩。