跳到正文
Hacker News· mariuz·· 8 天前AI 评分12

Doom 移植到 Castle Game Engine(Object Pascal / Free Pascal)

A Port of Doom to the Castle Game Engine (Object Pascal / Free Pascal)

AI 导读

一个用 Object Pascal 编写的 Doom 移植版,基于 Castle Game Engine,可直接读取原始 WAD 格式,内置 BSD 授权的 Freedoom Phase 1(36 张 ExMy 地图)和 Phase 2(32 张 MAPxx 地图),也支持加载自有的 Doom 1 / Doom 2 IWAD 与 PWAD。

正文 · AI 翻译

Build Web

在浏览器中游玩:https://mariuz.github.io/castle-doom/(WebAssembly 构建) · 下载:Releases(Windows 安装程序或 zip、Linux、macOS)· 更新日志

使用 Castle Game Engine(Object Pascal)渲染和游玩的 Doom 关卡。它直接读取原始 WAD 格式:Freedoom Phase 1 和 Phase 2(BSD 许可,已捆绑在 data/wads/ 中)开箱即用,你自己的原版格式 Doom 1 / Doom 2 IWAD 和 PWAD 可以从菜单(“Open IWAD...”、“Add PWAD...”)或命令行加载:

castle-doom -iwad DOOM2.WAD -file mymap.wad -deh mymap.deh -warp MAP01

这个项目特意写成一次引擎之旅:每个 Doom 子系统都映射到 Castle Game Engine 的一项功能上。

E1M1 start

Door opened to the outside Lift and a zombieman
MAP04 with a cacodemon Title screen
Doom Castle Game Engine
WAD 数据块(VERTEXES、LINEDEFS、SECTORS、BSP NODES……) DoomWad / DoomMap 单位,纯 Pascal 记录
墙壁、地板、天花板 在代码中构建的 X3D 节点:TIndexedTriangleSetNode、TUnlitMaterialNode、用于扇区光照的逐顶点 TColorNode、每个可移动扇区一个 TCastleScene
纹理(TEXTURE1 + PNAMES 补丁合成、平面、精灵) 解码为 TRGBAlphaImage,通过自定义 URL 协议 doomgfx:/tex/STARTAN3.png(RegisterUrlProtocol)提供,以便引擎的纹理缓存在场景之间共享它们
动画平面/墙壁(NUKAGE、BFALL……) 每 8 个 tic 交换一次 TImageTextureNode.SetUrl
天空 一个跟随摄像机的带纹理圆柱体场景
光照衰减 Doom 的 colormap 算术作为 GLSL 着色器效果(TEffectNode,一个带有扇区光照的 FloatVertexAttribute),在真实的 PLAYPAL / COLORMAP 中查找每个像素(精确的颜色和色带),带有枪口闪光灯、无敌和光照放大 colormap(用 F 切换)
玩家 TCastleWalkNavigation:重力、PreferredHeight 41、ClimbHeight 24(楼梯)、Radius、鼠标视角、头部摆动;通过地图场景上的 PreciseCollisions 进行碰撞
物品 / 怪物 每个物品一个 TCastleTransform,带有 TCastleBillboard 行为和四边形 TCastleScene;精灵旋转像 R_ProjectSprite 一样选取
射击 Doom 的自动瞄准(P_AimLineAttack)和线攻击以 Doom 单位针对 linedef 和物品包围盒进行追踪
门、升降台、地板、天花板、楼梯、粉碎机 扇区高度变化会就地重新生成受影响的 TCastleScene 坐标
声音(DS* DMX 数据块) 通过 doomsfx:/DSPISTOL URL 协议即时转换为 WAV,使用 TCastleSoundSource 实现定位音频
音乐(D_* MUS 或 MIDI 数据块 + GENMIDI OPL 音色) DoomMusic 程序使用 GENMIDI 寄存器驱动 Nuked OPL3(一个由 DoomOpl3 加载的共享库;否则使用内置 FM 模型)并将歌曲渲染为 WAV(doommus:/D_E1M1.wav),在 SoundEngine.LoopingChannel[0] 上循环
状态栏 STBAR + 数字补丁合成为一张图像,由像素完美的 TCastleImageControl 显示
武器精灵、闪光、屏幕闪光、消息 TCastleImageControl、TCastleRectangleControl、TCastleLabel
标题 / 中场 TCastleView

阅读 docs/ARCHITECTURE.md 以了解移植如何逐单元工作以及每个部分使用哪些引擎 API;docs/ROADMAP.md 列出了仍缺失的内容(按优先级排序);CLAUDE.md 包含构建、测试和贡献说明。

已实现的功能

  • Freedoom Phase 1(36 张 ExMy 地图)和 Phase 2(32 张 MAPxx 地图),菜单中可选择地图。
  • 带纹理的墙壁,遵循 Doom 的钉住规则和偏移,遮罩中间纹理(格栅),来自 BSP 子扇区的地板和天花板,天空,带“假对比度”的扇区光照等级。
  • 门(手动、开关、走过触发、上锁、炽热)、升降台(永久升降台会停止并恢复)、地板(升至最短的下方纹理、环形)、天花板、粉碎机(慢速粉碎机在压碎物体时减速、无声粉碎机、停止并恢复)、楼梯、传送器、光照变化、滚动墙壁、开关纹理、秘密扇区、伤害地板、出口(普通和秘密)以及中场屏幕。
  • 拾取物:生命值、护甲、弹药、钥匙、武器、强化道具,带有 Doom 的消息。
  • 怪物像 Doom 里那样苏醒:在它们眼前出现时,或当你的枪声传到它们的 扇区时(声音会穿过开着的门传播,在关着的门前停止,最多穿过一条隔音 线;伏击怪物还必须看到你)。它们会追击(2D Doom 式移动,遵循台阶/坠落 规则,它们会开门、使用传送器和仅限怪物的传送线;幽灵被 绘制成 Doom 的斑点状 fuzzoffset 绒毛;飞行怪像 Doom 的 P_ZMovement 那样向你升起和下沉, 它们的尸体会坠落),用近战、即时命中或投射物攻击,会受伤、死亡 (被过量击杀时爆成碎块),被击中和爆炸击退(你也是), 在关闭的门和粉碎机下作为尸体被压成碎块,掉落物品,并在被另一个怪物击中时互相打斗(内讧)。失落灵魂 冲锋,痛苦元素吐出失落灵魂(它们死亡时再多吐三个),大恶魔复活 死者并用火焰攻击烧你。桶会爆炸并造成溅射伤害。Boss 死亡会触发特殊地图事件(E1M8、E2M8、 E3M8、E4M6、E4M8、MAP07、指挥官基恩)。MAP30 上的罪恶圣像吐出方块, 方块生成怪物,并会被穿过其墙壁上洞口的火箭杀死。
  • 武器:拳头、电锯、手枪、霰弹枪、超级霰弹枪、链枪,以及火箭发射器的 真实投射物(溅射伤害)、等离子枪和 BFG(充能、球体、曳光弹喷射)。 拳头和电锯会让你转向它们击中的目标,就像 Doom 里那样。
  • 带脸、钥匙、手臂、弹药表的状态栏;武器摆动,切换时武器放下和抬起; 来自 WAD 调色板的伤害、拾取和辐射防护服色调;关卡之间的 Doom 屏幕融化效果。
  • 自动地图(Tab),带有 Doom 的线条颜色、玩家箭头、缩放、网格和一个显示全部作弊。
  • 用于消息的 Doom 文本字体,以及真正的幕间屏幕(关卡名称、FINISHED、 带动画和声音的击杀/物品/秘密/时间、标准时间、ENTERING)。
  • 来自 WAD 的 DEHACKED 字符串的 Freedoom 自己的措辞:拾取和门消息、关卡 标题(也在自动地图上)、噩梦和退出问题。
  • 终章:Freedoom 的故事文本(从 WAD 的 DEHACKED 字符串读取)、结束 画面、E3M8 之后的兔子滚动和 MAP30 之后的 Doom 2 演员表。
  • 来自 WAD 图形的 Doom 自己的菜单:标题页循环(TITLEPIC、CREDIT、HELP2) 直到按键打开菜单;新游戏、章节和技能选择(全部五个技能,包括 噩梦的快速怪物和重生)、读取游戏、阅读此内容!(F1);-skill 1..5。 在游戏中,Esc / F2 / F3 / F4 在暂停的游戏上打开 Doom 的主菜单、保存和读取页面以及声音 音量页面(M_* 图形、温度计滑块);存档会获得一个输入的 名称(Doom 的 _ 光标;默认显示地图、击杀数和时间)。 选项页面选择 WAD、地图和技能。
  • 保存和读取:F2 / F3 槽位菜单,F6 / F9 快速保存 / 读取,标题屏幕上的“继续(快速保存)”,-loadgame N。所有内容都会被保存:开着的门、移动的升降机、已使用 的开关、尸体、战斗中的怪物、物品栏和自动地图。在浏览器中,存档 保存在页面的 localStorage 中,因此它们在重新加载后仍然存在;主页的“你的 存档”部分将它们导出到文件并导入回来,桌面版读取 同一个文件(选项:导出 / 导入存档,--export-saves / --import-saves)。
  • 外部 IWAD 和 PWAD(菜单文件对话框或 -iwad / -file / -deh / -warp),PWAD 数据块 像 Doom 中那样覆盖 IWAD 的数据块;原版和 ZDoom 扩展节点(XNOD、ZNOD、 XGLN/ZGLN、XGL2/ZGL2、XGL3/ZGL3)以及 glBSP GL 节点(V1、V2、V3、V5,也来自 一个 .gwa 文件),因此用 ZDBSP 或 glBSP 构建的地图也能加载。
  • 音乐:MUS 和 MIDI 数据块在模拟的 OPL3(Nuked OPL3,作为随游戏打包的共享库加载)上播放,由 WAD 的 GENMIDI 乐器库驱动,即原版的 AdLib / Sound Blaster 音效;当库缺失时以及在浏览器中,会使用内置的 FM 模型播放。包括标题、关卡和过场音乐。

(尚)未完成

参见 docs/ROADMAP.md。要点:不支持 UDMF 地图,DeHackEd 补丁会改变事物、帧和代码指针,但不会改变武器的帧,浏览器中的音乐是近似的 FM 模型(那里没有 OPL3 模拟器)。

构建与运行

安装 Castle Game Engine 7(其 Windows 下载包内含 Free Pascal),然后(在 Windows 上,从引擎的 bin/ 中复制 OpenAL32.dll 和 wrap_oal.dll 到可执行文件旁边以支持声音;castle-engine package 会自动完成此操作):

castle-engine compile --mode=release
castle-engine run

或在 Castle Game Engine 编辑器中打开 CastleEngineManifest.xml。

按键:WASD/方向键移动,Shift 奔跑,鼠标视角,鼠标左键 / Ctrl 开火,E/Space 使用,1-7 和鼠标滚轮切换武器,F 光照衰减,M 鼠标视角开/关,J 音乐开/关,F4 音效 / 音乐音量,Tab 自动地图(+/-/滚轮缩放,G 网格,I 显示全部),F2/F3 保存/加载菜单,F6/F9 快速保存/加载,N/P 下一张/上一张地图,F5 截图,F8 引擎的检查器(按名称查看地图、每个事物和游戏状态),H 帮助,Esc 在暂停的游戏上打开 Doom 的菜单(选项:结束游戏、消息、鼠标灵敏度、音效音量;再次按 Esc 或点击菜单项旁边即可恢复;在浏览器中,按 Esc 释放鼠标会以相同方式打开它,并且会显示“点击以环顾四周”的提示,直到再次点击捕获鼠标)。

游戏手柄(Windows、Linux 和浏览器,在浏览器中按下按钮后手柄才会出现):左摇杆移动 / 平移,右摇杆转向 / 视角,右扳机开火,A / X 使用,LB / RB 上一把 / 下一把武器,View 自动地图,Menu 打开 Doom 的菜单;在菜单中,方向键、A(Enter)和 B(返回)。

自动化冒烟测试(加载地图、运行脚本、保存截图、退出):

castle-doom --autotest E1M1 shots/e1m1 --demo "S,F:3,S,T:90,U,W:2,S,X,S,Q"

持续集成

  • .github/workflows/build.yml:在每次推送时打包 Windows x86_64、Linux x86_64 和 macOS 应用包(x86_64 和 aarch64,未签名:首次打开时右键 > 打开),每个都在 GitHub 对应系统的运行器上,由 castle-build-ci 设置好 FPC 和 CGE 快照,并生成一个 Windows 安装程序(MSI,在 Windows 运行器上使用 WiX,由 tools/make_msi_wxs.py 从 Windows zip 生成);推送标签 vX.Y.Z,或使用 release_tag 手动运行工作流,会将它们附加到 GitHub Release。
  • Autotests 作业运行 FPCUnit 单元测试(tests/castle_doom_tests.lpr:WAD、地图 BSP、音乐渲染、DeHackEd),然后在 Xvfb 下运行 tools/run_autotests.py。
  • .github/workflows/web.yml:构建 WebAssembly 版本(FPC 主分支的 wasm32 交叉编译器和 Pas2js 从源代码构建并缓存,因为 Docker 镜像尚未提供它们),并将 pages/ + 游戏部署到 GitHub Pages。

源代码布局

code/doomwad.pas        WAD directory and palette
code/doomgraphics.pas   patches, textures, flats, sprites, animations, doomgfx: protocol
code/doommap.pas        map lumps, BSP queries, subsector polygons
code/doomgeometry.pas   map -> X3D scenes (chunks that can be regenerated)
code/doomthings.pas     thing type table (info.c reduced)
code/doomactors.pas     sprite billboards with frame animation
code/doomworld.pas      game logic: movers, specials, pickups, AI, weapons
code/doomsound.pas      DMX -> WAV, doomsfx: protocol
code/doommusic.pas      MUS/MIDI parsing, GENMIDI -> OPL3 registers or the FM model, doommus: protocol
code/doomopl3.pas       Nuked OPL3 loaded as a shared library (data/lib)
code/doomhud.pas        status bar composition
code/doomautomap.pas    automap (DrawPrimitive2D)
code/doomfont.pas       STCFN text
code/doomintermission.pas  intermission screen
code/doomfinale.pas     finale text, end pictures, bunny scroller, cast call
code/doomstates.pas     vanilla's state table (frames, code pointers) and thing rows, generated by tools/make_states.py
code/doomdehacked.pas   DeHackEd patches: BEX strings, things, frames, code pointers, ammo, par times
code/doomwipe.pas       the screen melt
code/doommenu.pas       Doom's menu (M_* graphics): title pages, main, episode, skill, load / save, Read This
code/gameviewmenu.pas   title screen: Doom menu and options
code/gameviewplay.pas   viewport, navigation, input; the 2D layer comes from data/play.castle-user-interface
code/doomworldstatus.pas  the game's state as published properties (the inspector)
data/play.castle-user-interface  the play view's HUD, texts and screens: a CGE editor design
data/menu.castle-user-interface  the title screen, Doom's menu and the Options panel: a CGE editor design
code/doommaptransform.pas  TDoomMapTransform: a Doom level built from a WAD inside a design ("Doom Map" in the editor)
code/gameviewdesign.pas  --autotest MAPCOMPONENT: shows data/mapcomponent.castle-user-interface, a design with that component

Freedoom 版权所有 (c) 2001-2024 Freedoom 项目贡献者,BSD 许可证(参见 data/wads/COPYING.txt)。Castle Game Engine 为 LGPL,带有静态链接例外。音乐的 OPL3 模拟器是 Nuke.YKT 开发的 Nuked OPL3,LGPL 2.1 或更高版本:它不属于此仓库,而是由 tools/build_nuked_opl3.sh 构建到 data/lib/ 中(CI 为软件包执行此操作,许可证文本放在旁边)作为游戏在运行时加载的共享库,因此你可以将其替换为自己的构建,或删除它以使用内置的 FM 合成器。

来源:Hacker News · github.com