KiDoom:在电路板上玩《毁灭战士》

描述

 

KiCAD

引言:当“万物皆可运行 DOOM”遇到极致创意

在技术圈,“万物皆可运行 DOOM”是一个广为流传的梗,从计算器到数码相机,无数设备都被大神们成功移植了这款经典游戏。但如果这个问题变得更疯狂一些:如果游戏的墙壁是真实的电路板铜线,敌人是芯片封装,会是怎样一番景象?

答案就是 KiDoom 项目。它将 1993 年的经典游戏《毁灭战士》(DOOM)渲染在了一个专业的 PCB编辑器 KiCad 中。这个项目背后充满了巧妙的技术构思和令人惊讶的实现细节,下文将为你揭示其中最有趣的五个事实。

-----------------------------------------------------------------------------

1. 核心理念:一场“无人问津”却极致优雅的技术炫技

KiDoom 并非为了解决任何实际问题,它的诞生源于一个纯粹的好奇心和技术探索精神:“如果 DOOM 的墙壁是真实的 PCB 走线会怎样?” 项目的创建者旨在回答一个根本没人问过的问题,这本身就充满了一种极客式的浪漫。

What if DOOM's walls were actual PCB traces? What if enemies were QFP-64 chips and health packs were SOT-23 transistors? KiDoom answers these questions nobody asked...

这种看似“无用”的创造,恰恰是技术社区创新精神和幽默感的最佳体现。它证明了最纯粹的乐趣往往来自于探索技术的边界,而非仅仅满足实用需求。

2. 技术突破:从每秒 0.15 帧到可玩的关键转变

项目最初的构想是使用 PCB 焊盘来逐个像素地渲染游戏画面,但这个思路很快被证明是行不通的。

  • 每帧像素数: 320 x 200 = 64,000 个
  • 渲染时间: 64,000 个焊盘 × 每焊盘 0.1 毫秒 = 每帧 6.4 秒
  • 最终帧率: 0.15 FPS (完全不可玩)

真正的突破在于一个“顿悟时刻”:开发者意识到 DOOM 引擎内部本身就是以矢量(线段)而非像素来计算可见几何体的,它将这些数据存储在 drawsegs[] 和 vissprites[] 等内部数组中。而 PCB 的铜走线恰好也是矢量数据。这个发现彻底改变了实现路径,其渲染效率比像素扫描方案快了 200 到 500 倍。

  • 每帧线段数: 约 100-300 条
  • 渲染时间: 约 200 条走线 × 每走线 0.1 毫秒 = 每帧 20 毫秒 (+ 刷新开销)
  • 最终帧率: 10-25 FPS (足够进行基本游戏)

这个从像素到矢量的思维转变,是整个项目得以从一个不可能的想法,变成一个可玩的技术演示的基石。

3. 最具创意的设计:用芯片封装的复杂性来代表游戏角色

KiDoom 项目中最为精妙的设计,在于它建立了一套实体映射系统:游戏中的不同实体(敌人、道具等)被渲染为不同复杂度的真实 PCB 元件封装。

游戏角色 PCB 封装 引脚数 示例
收藏品 SOT-23 3 医疗包、弹药夹、钥匙卡
装饰物 SOIC-8 8 油桶、尸体、火炬
敌人 QFP-64 64 僵尸、恶魔、玩家

这种设计的巧妙之处在于,它创造了一种“任何 PCB 设计师都能直观理解的视觉层级”。一个强大的霰弹枪手是一个复杂的 64 引脚芯片,而一个简单的医疗包只是一个 3 引脚的晶体管。为了实现这个映射超过 150 种不同游戏实体的系统,开发者必须深入 DOOM 的 C 语言源代码进行修改。挑战在于,游戏原生的 vissprite_t 渲染结构体中并不包含实体的类型信息。解决方案是直接对引擎进行“外科手术”:通过修改 r_defs.h 文件为 vissprite_t 结构体增加一个 mobjtype 字段,并在 r_things.c 文件的 R_ProjectSprite() 函数中捕获 thing->type,从而在渲染每一帧时都能精确知道每个实体的具体身份。

4. 架构解密:它并非在 KiCad 内部 运行 DOOM

一个常见的误解是 KiDoom 让 DOOM 运行在了 KiCad 内部,但事实并非如此。在这个项目中,KiCad 只是作为“显示器”或“渲染器”。真正的 DOOM 游戏引擎是作为一个独立的 C 语言进程在后台运行的。

项目采用了一种“三模式渲染”架构,同时运行三个并行的可视化窗口:

  • SDL 窗口: 真正玩游戏的地方,显示完整的 DOOM 画面。
  • Python 线框窗口: 用于调试,显示从游戏中提取出的矢量线条。
  • KiCad PCB 窗口: 项目的主角,显示由铜走线构成的墙壁和由元件封装构成的实体。

每一帧的数据都遵循一个清晰的流程:从 C 语言的 DOOM 引擎 drawsegs[] 和 vissprites[] 数组中提取几何数据,通过 Unix 套接字序列化为 JSON 格式,再由 Python 脚本接收并解析,最终更新到 KiCad 的画布上。这种清晰的架构划分,展现了项目并非一个简单的脚本,而是一个经过深思熟虑的复杂系统。而整个系统的性能瓶颈,也清晰地指向了 KiCad 的 Python API 调用 pcbnew.Refresh(),这一步会消耗 30-50 毫秒,是帧率的主要限制因素。

5. 最终观感:复古街机风与现代工程工具的奇妙融合

KiDoom 的最终画面既不像现代游戏的精细像素,也没有复杂的纹理,而是一种独特的线框风格,仿佛是复古街机游戏与现代工程软件的结合体。

Think "1982 vector arcade game meets 1993 FPS meets 2025 PCB editor."

画面的关键视觉元素包括:

  • 墙壁: 蓝色(B.Cu 底层铜)的铜走线框。
  • 实体: 真实的 PCB 元件封装。
  • 远近提示: 近处的走线更粗,远处的更细,以此实现深度暗示。
  • 天花板/地板: 并非逐扇区渲染,而是由简单的全屏渐变色代表。

KiDoom 将经典游戏、复古的矢量图形美学和专业的工程软件这三个看似无关的元素,成功地融合成了一种前所未有的、令人着迷的视觉体验。

-----------------------------------------------------------------------------

结论:在限制中诞生的极致创意

KiDoom 不仅是一个成功的技术演示,更是一个关于创造力、问题解决和技术热情的精彩故事。它向我们展示了,即使是使用最意想不到的工具,只要有足够的巧思,也能创造出令人惊叹的作品。

Is it practical? No. Is it efficient? Barely. Is it the correct use of a professional PCB design tool? Absolutely not. But it works.

这个项目留给我们的思考是:在你的专业领域,是否存在一些看似“不务正业”却能激发无限创意的疯狂想法?或者,下一个能运行 DOOM 的,会是什么意想不到的东西?

项目主页:

https://www.mikeayles.com/#kidoom

 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分