Windows 11的畫圖應用裏玩DOOM:通過劫持剪貼板實現,效果驚人好

核心亮點

微軟 Azure CTO Mark Russinovich 開發併發布了一個名爲 DoomPaint 的開源項目,能夠在 Windows 11 的 MS Paint 中運行真正的 DOOM 遊戲。與常見的"DOOM 可以在任何地方運行"的梗不同,這次 Paint 並不是在"運行"遊戲,而是作爲遊戲畫面的顯示器——通過劫持 Windows 剪貼板實現。

項目背景

Russinovich 表示:"Paint 渲染遊戲,但不計算遊戲。Paint 什麼都不計算。Paint 從未計算過任何東西。這就是這個玩笑的精髓。"

該項目在 GitHub 上開源,使用真正的 ViZDoom 引擎(基於 ZDoom 的分支,專爲 AI 和強化學習研究構建),以無頭模式渲染每一幀,然後通過 Windows 剪貼板將畫面粘貼到 Paint 的畫布上。

更令人驚訝的是,項目具備:

  • 完整的鍵盤控制

  • 工作正常的音效

  • 真正的 MIDI 配樂

  • 幀率最高可達 DOOM 原生 35 FPS,最低則降至"電子表格級別"

如何運行 DoomPaint

安裝步驟

  1. 訪問  github.com/markrussinovich/DoomPaint 下載項目 ZIP 文件,或使用 Git 克隆

  2. 確保 PC 上已安裝 Python

  3. 解壓文件夾,雙擊運行 run.bat

  4. 首次啓動時會自動創建虛擬環境並安裝依賴,等待完成

  5. 安裝完成後 MS Paint 會自動打開

  6. 保持 Paint 窗口處於焦點狀態,即可開始遊戲

默認控制鍵位

技術原理深度解析

與早期"Paint 中的 DOOM"嘗試的區別

過去兩天 headlines 暗示這是首次實現,但實際上 早期的嘗試通常是在單獨窗口運行遊戲,然後通過鏡像或屏幕捕獲將畫面投射到 Paint 中——本質上還是在正常玩 DOOM,只是同時在別處顯示一份拷貝。

DoomPaint 的工作方式完全不同:

  • 沒有第二個 DOOM 窗口

  • Paint 的畫布是遊戲唯一的顯示器

  • 每個按鍵輸入都通過 Paint 傳遞

引擎與資源

  • 引擎:ViZDoom(可渲染而不打開窗口)

  • 默認分辨率:640×400,最高 35 FPS

  • 低分辨率模式:320×200(DOOM 1993 年原生分辨率),幀率更高

  • 第一關資源:shareware DOOM1.WAD(包含關卡和 Bobby Prince 原創配樂)

  • 後續地圖:回退到 Freedoom(BSD 許可的替代 WAD)

核心技術挑戰與解決方案

1. 剪貼板競態條件

問題:Paint 異步讀取剪貼板。如果每秒清空並寫入新數據數十次,可能在 Paint 還在讀取上一幀時清空剪貼板,導致 Paint 拋出"無法完成操作"的模態對話框,中斷粘貼並卡住遊戲。

解決方案:在 clipserve.py 中,Russinovich 停止使用重寫剪貼板的方式。Windows 允許應用程序將剪貼板作爲引用計數的 OLE 數據對象擁有,使用 OleSetClipboard 配合自定義 IDataObject,通過 GetData 調用來提供字節數據。

DoomPaint 爲整個會話發佈一個這樣的對象,並原地更新它提供的幀字節,無需清空或重寫剪貼板。由於對象是引用計數的,正在進行的讀取會繼續有效,競態條件不再發生。每個 GetData 調用還兼作"幀已被消費"的信號,遊戲用它來調節節奏——僅在 Paint 確認讀取了上一幀後才發佈下一幀。

2. 不竊取鍵盤輸入的粘貼觸發

DoomPaint 在啓動時自測兩種觸發粘貼的方式,選擇在該 Paint 構建上有效的方式:

首選方法:直接發送合成的 Ctrl+V 按鍵,不打開菜單,不會攔截遊戲鍵。

備選方法:如果某些 Paint 構建靜默吞掉合成 Ctrl+V,則通過 Paint 的 UI Automation 菜單觸發粘貼——較慢但更可靠,會短暫打開 Edit 菜單。

3. 浮動選擇與撤銷歷史

粘貼的幀以浮動選擇的形式來到 Paint,這就是運行片段中顯示的效果。

下一幀的粘貼會自動提交上一幀的浮動選擇,無需 Russinovich 添加任何單獨的提交或扁平化操作——這就是每幀都成爲 Paint 撤銷歷史中永久步驟的原因。

有趣副作用:Ctrl+Z(撤銷)兼作倒帶按鈕,因爲每幀粘貼都是 Paint 歷史中的獨立撤銷步驟,所以死亡後按幾次 Ctrl+Z 可以"撤銷死亡"。

4. 防止遊戲鍵與 Paint UI 交互

需要低級別的 Windows 鍵盤鉤子 WH_KEYBOARD_LL,在 Paint 處於焦點時攔截每個遊戲鍵,阻止其到達 Paint。沒有這個鉤子, stray 的箭頭鍵可能關閉打開的粘貼菜單,使幀傳輸凍結數秒。

5. 聲音系統

音效:通過 OpenAL 從 ViZDoom 輸出。Russinovich 換用了更新的 OpenAL-Soft 1.24 版本,因爲 ViZDoom 自帶的老版本在會話中途切換音頻輸出設備(如插入耳機)時不會跟隨默認音頻設備。

音樂:由於 ViZDoom 剝離了 ZDoom 內置的音樂播放,單獨的模塊從 WAD 文件中提取原始音樂數據,在需要時從 Doom 的 MUS 格式轉換爲 MIDI,然後通過 Windows MIDI 音序器循環播放。

自修複音頻 bug:項目還自我修復了一個非確定性的 Windows 音頻 bug——設備可以打開並看似正常工作,但實際上靜默輸出完全靜音。DoomPaint 在啓動時重置一次聲音系統以防萬一,然後在遊戲過程中監控輸出,如果檢測到開火卻沒有聲音,會在數秒內觸發第二次重置。

保存與文件

  • 隨時保存文件會生成當前幀的 PNG 圖像,因爲 Paint 無法知道它正在渲染的是 1993 年的視頻遊戲!

  • 運行需要 Python,run.bat 會自動構建虛擬環境並安裝依賴

  • 第一關無需單獨購買 DOOM,但將完整的 doom.wad 或 doom2.wad 放入項目的 wad 文件夾可解鎖後續地圖的完整配樂

AI 輔助開發:Fable 5 的功勞

Russinovich 在 LinkedIn 帖子中宣佈該項目時寫道,他一直在使用 Claude Fable 5 進行嚴肅的研究工作,發現它比 Opus 4.8 有明顯改進,並補充說這個 Doom-in-Paint 項目是他在同一天早上"爲了好玩"用它構建的。DoomPaint 的 GitHub 提交歷史顯示了 AI 編碼工具的真實貢獻。

雖然是一個有趣的項目,但 DoomPaint 必須解決:

  1. Windows 中的真實競態條件

  2. 逆向工程 Paint 的未文檔化剪貼板行爲

  3. 繞過音頻驅動 bug

這體現了微軟員工將 AI 模型視爲足夠快的原型工具,可以在業餘時間進行真正的系統工作——這也是微軟一直在押注的 AI 趨勢,特別是 AI 代理執行越來越嚴肅的工程工作。

總結

DoomPaint 是一個看似荒誕但技術精湛的項目,它展示了:

  1. Windows 剪貼板的強大能力 — 可以承載實時遊戲引擎數據

  2. 系統級編程的複雜性 — 競態條件、鉤子、COM 對象引用計數

  3. AI 輔助開發的潛力 — 從概念到可運行原型的時間大幅縮短

  4. 經典遊戲的永恆魅力 — DOOM 誕生 30 多年後仍在激發創新

正如 Russinovich 所說:Paint 什麼都不計算,但它可以顯示一切。

更多遊戲資訊請關註:電玩幫遊戲資訊專區

電玩幫圖文攻略 www.vgover.com