Hotdry.
systems

深度剖析 RollerCoaster Tycoon 的汇编级性能优化艺术

从手写汇编到按位运算,解析 Chris Sawyer 如何在 1999 年硬件上实现数千名游客的流畅模拟。

如果要选出游戏史上优化做得最极致的作品,1999 年发布的《过山车大亨》(RollerCoaster Tycoon,以下简称 RCT)绝对榜上有名。这款由 Chris Sawyer 独自完成编程的游戏,几乎全部用汇编语言编写,在那个仅有数百兆赫兹处理器的年代,硬是模拟出了一个拥有数千名游客的主题乐园,且帧率稳定流畅。即便是二三十年后的今天,类似的模拟经营游戏在优化方面依然常常捉襟见肘,那么 RCT 究竟是如何做到的?

汇编语言:最后的荣光

在 RCT 诞生的年代,汇编语言曾是游戏开发的主流选择,但到 1999 年时,大多数商业游戏已经转向 C 或 C++,仅有少量关键模块保留汇编实现。然而 RCT 却几乎全部使用汇编编写,这在商业游戏史上几乎是孤例。有观点认为 RCT 很可能是最后一例真正意义上的大型汇编游戏。

编译器在这些年已经进化得非常智能,曾经需要手动优化的很多技巧,现代编译器已经能自动完成。但在 1999 年的硬件环境下,手写汇编带来的性能增益是实打实的。Chris Sawyer 得以直接控制 CPU 的每一条指令,确保每个循环、每次内存访问都物尽其用。这种近乎偏执的优化态度,为后续的各种微优化奠定了基础。

精准的数据类型:节省每一字节

如果你需要存储游戏中的金钱数值,会如何选择数据类型?大多数开发者会直接选用 64 位整数或浮点数,毕竟内存不值钱。但 Chris Sawyer 在 RCT 中采用了截然不同的策略:为不同的金钱场景使用不同的数据类型。

公园整体价值需要较大的数值范围,使用 4 字节有符号整数;而调整商店商品价格时,数值范围很小,仅使用 1 字节无符号整数。这种精细化的数据类型选择,在内存带宽极其有限的年代意义重大。有意思的是,后来开源重制版 OpenRCT2 在现代 CPU 上运行时,将这些细粒度类型统一简化为 8 字节变量,因为对现代硬件而言,这种优化带来的收益已微乎其微。

按位运算:替代乘除的终极加速

在阅读 OpenRCT2 源码时,会发现大量类似 value << 2 这样的表达式。这并非炫技,而是刻意为之的优化:用左移位操作替代乘法,用右移位替代除法。

原理很简单:二进制系统中,每左移一位等于乘以 2,每右移一位等于除以 2。与其执行耗时的乘除指令,CPU 只需搬运位即可完成。在当年的 486 或早期 Pentium 处理器上,这种优化的性能差异是显著的。

更值得注意的细节是:RCT 的游戏数值公式被特意设计为大量使用 2 的幂次方。想象一下,如果让现代游戏设计师把公式中的参数从 9.5 改成 8,他们一定会觉得荒谬。但 Chris Sawyer 同时兼任程序员和设计师,有权限也有动机做这种看似不合理的调整,最终让游戏中几乎所有数值运算都能用按位操作完成。这种设计与实现的深度耦合,是现代开发流程中难以复制的优势。

游客行为:彻底颠覆的路径规划

游戏中最耗性能的操作之一是路径搜索。传统做法是让每个游客先决定想去哪里(根据偏好选择游乐设施),然后计算路径前往目标。这种设计在游客数量达到数千时,路径搜索的开销会瞬间击垮帧率。

RCT 的做法截然不同:游客在公园中几乎是盲目游荡。他们沿着当前路径行走,遇到岔口时随机选择方向,没有任何目标感。即便游客喊饿喊渴,也不会主动寻找最近的餐厅,而是继续随机行走,直到偶遇食物。这种看似「愚蠢」的 AI 行为,恰恰是极致的性能优化 —— 完全绕过了昂贵的路径计算。

当然,RCT 并非完全不用路径搜索。当维护人员需要前往故障设施,或游客想离开公园时,仍然需要计算路径。但即便在这些场景下,RCT 也设置了搜索深度上限:普通游客最多搜索 5 个路口,维护人员可以搜索 8 个路口,购买地图的游客可以搜索 7 个。如果搜索超过限制仍未找到路径,系统直接返回失败。这种「有损」的路径搜索虽然会导致游客偶尔迷路,但换来的却是帧率的稳定。

更有意思的是,这个技术限制被巧妙地转化为了游戏机制。游客找不到出口时会抱怨,玩家能看到「无法找到出口」的想法气泡。这在现代游戏开发中几乎不可能出现 —— 程序员和设计师职责分离的模式下,技术妥协很难变成设计特色。

无碰撞的人群系统

当公园人数达到数千时,大多数游戏会面临一个两难选择:要么让游客相互穿透(看起来不真实),要么实现复杂的碰撞检测(性能灾难)。RCT 再次选择了「绕过问题」的思路:游客之间完全没有碰撞检测,成千上万的游客可以重叠在同一块路面上。

但这不意味着玩家可以无限堆砌游客。游戏仍然会统计每个游客周围的邻近人数,如果某个区域过于拥挤,游客的快乐度会下降,并发出抱怨。玩家看到的结果与传统碰撞系统类似(需要扩张道路),但计算量却少了好几个数量级。

写在最后

RCT 的优化哲学,本质上是一种「设计层面的优化优先于实现层面的优化」的思路。Chris Sawyer 并不执着于在代码细节上精雕细琢,而是从游戏设计层面入手,用看似「偷懒」的机制换来了巨大的性能收益。这种思路在今天依然有深刻的借鉴意义:当技术挑战无法通过堆砌算力解决时,改变设计本身往往是最有效的出路。

资料来源:本文主要参考 Larst Of Us 网站上发布的《The gold standard of optimization: A look under the hood of RollerCoaster Tycoon》一文。

查看归档