2D 载具

1996 年 8 月下旬的一个周末,Pat Kerr 编写了一个 2D 物理原型,它后来成为《Grand Theft Auto》中车辆系统的基础。三十年后,他用 JavaScript 将其重建,并详细讲解了该模型的工作原理。

中文
复制
复刻版 2D 车辆物理模拟的截图,一辆线框小车在网格上留下弯曲的轮胎轨迹

一个项目的历史 · 1996–2026

2D 载具

1996 年 8 月下旬的一个周末,我写了一个 2D 物理模拟,它后来成了那款大热的游戏《Grand Theft Auto》(也就是《GTA》)中载具系统的基础。

它最初只是我用 GFA BASIC 在 Atari ST 家用电脑上写的一个线框小 demo(后来移植到 C 语言,用在了真正的游戏里)。

在它 30 周年之际,我用 JavaScript 把它重制* 了一遍,形式稍微好看一点,算是“复刻版”,给任何有兴趣看看或上手玩玩的人。

玩 Motion Lab

玩 Motion Lab:一辆线框汽车在模拟网格上留下弯曲的轮胎轨迹。

1996 年的想法,在 Motion Lab 中重制。

操作说明

上面的重制版可以直接玩,如果你在手机上,也有触屏操作。

除了默认的“Car”模式(1),你还可以选择技术上更简单的 Spaceship(也就是“Ship”,2)和“Brick”(3)模式,既可以通过设置里的模式选择器切换,也可以直接按键盘上对应的数字键。

场地四周的碰撞屏障可以通过点击或按“B”来开关,“G”则开关垂直重力(只有在 Ship 和 Brick 模式下才真正说得通)。

摄像机控制由“Z”和“X”提供:“Z”开关所谓的摄像机“死区”,它决定载具移动多远之后摄像机才会跟上;“X”开关一个与速度相关的缩放功能,开快的时候摄像机会稍微拉远一点(就像 GTA 里那样)。

*(当然,完全没有任何侵犯版权或商标的意思)

[自愿免责声明:本作品完全独立于《Grand Theft Auto》系列及其发行商“Take-Two”,也与名为“Rockstar Games”的开发实体毫无关联。我非常乐意把这一点说得清清楚楚。甚至可以说是求之不得。]

工作原理

一个小想法,两层结构。

这个原型把一个通用的 2D 刚体和一个刻意做得很简单的汽车模型结合在了一起。

最初的模拟是从类似“Brick”的东西开始的,之后我加入了一些增强,做出了“Ship”(刻意让人联想到 1986 年的经典游戏“Thrust”),最后又加入了必要的元素,让它更像一辆“Car”。

系统的核心是一个简单的经典 2D 刚体动力学模拟。据我所知,这种做法在当时(有一些明显的例外)的游戏中还不常见,大多数游戏载具用的是高中水平的“质点物理”(F = ma),任何旋转分量都靠各种不靠谱的“hack”来处理。使用真正的刚体物理(包括力矩)能让旋转处理得更连贯。

在这个核心之上,我加入了一个“新颖”的载具模拟层,基于一个简单、近似、技术上并不正确的轮胎行为模型。这基本上是我半懂半猜的结果,虽然我知道它在物理上并不准确,但在当时看来,对我的目的来说已经“足够好”了。

从输入到运动

这些图描述的是当前的 JavaScript 复刻版。浏览器界面提供控制,模拟以固定时间步推进,Canvas 渲染器绘制出结果状态。把这些职责分开,就更容易看清一次按键在哪里变成力,而这个力又在哪里变成运动。点击任意图片可查看大图。

Motion Lab 运行时:浏览器控制输入固定步长模拟,模拟更新载具后由 Canvas 渲染器绘制。

整体流程,从页面和控制到模拟与绘制。

一个刚体,三种行为

载具把一个刚体、一个描述其显示形状与碰撞几何的 shell,以及一个提供其行为的 dynamics 对象组合在一起。Brick 接受来自指针拖拽的力;Ship 在附着点施加推力;Car 加入引擎力和转向,并在四个轮胎位置施加阻力。切换模式会替换 shell 和行为,同时保留刚体的位置与运动状态。

载具构成:Car、Ship 和 Brick 各自把一个形状模型和力模型与同一个持久刚体组合起来。

载具协调器如何把形状、行为和刚体状态组合在一起。

力可以推动刚体,也可以让它转动

刚体除了记录位置和速度,还记录角度和角速度。穿过质心的力改变它的运动;偏离质心施加的力还能让它转动。仿真把所有力和力矩加起来,更新速度,再推进位置和角度。旋转刚体上某一点有自己的速度,等于刚体整体的运动与绕质心运动的叠加。

Barrier 用的就是这个点速度。当某个形状越过一条边时,仿真把它移回内侧,如果它正朝 barrier 运动,就施加一个接触冲量。因此偏心撞击既能改变速度,也能改变自转。这是一个简单的 barrier 求解器,边无摩擦,而不是通用的碰撞系统。

刚体物理:力与力矩更新运动,barrier 冲量则考虑接触速度和旋转力臂。

共用的物理核心,以及解决 barrier 接触所用的步骤。

刻意近似的轮胎

对每个轮胎,Car 测量其所在位置的速度,并把它分解为两个分量:沿车轮朝向的和横向的。它对滚动施加很小的阻力,对横向运动施加强得多的阻力。转向会改变前轮的朝向,所以它们的力也会让车身转动。手刹增大后轮的滚动阻力,并降低后轮的横向抓地力。

这些阻力与速度成正比,没有上限。这是一个方便的阻尼模型,而不是对轮胎摩擦、打滑或可用抓地力的真实描述。它用极少的机制换来了车轮抵抗横向移动的那种有用手感。Ship 和 Brick 使用同一个物理核心,只是施加力的方式不同。

三种力模型:Car 的轮胎阻力和转向力、Ship 的推力,以及 Brick 由指针施加的力。

力模型,包括车轮速度分量和手刹行为。

把各部分拼起来

Vehicle 协调器让选中的 dynamics 对象施加各自的力,然后推进刚体。它还会把外壳的局部点转换成世界坐标用于绘制,并找出每个 barrier 所面对的曲面点。当一个平面与 barrier 接触时,它取接触点的中点,避免因选取单个角而引入的人为旋转。

Vehicle 的方法:安装模式、施力并积分运动、变换形状点,以及选择 barrier 接触位置。

模式安装、仿真更新和接触几何的细节。

来源: patkerr.co.uk← 返回首页