WindowsのペイントでDOOMが動く「DoomPaint」とは?Azure CTOが作った35fps動作の仕組みを解説
本記事にはアフィリエイト広告(Amazon・楽天市場等)のリンクが含まれています。
Azure CTOが作った35fps動作の仕組みを解説
出典:GitHub「markrussinovich/DoomPaint」 / Tom’s Hardwareにもとづきます(2026年8月3日時点)。
「まさかWindowsの標準アプリでゲームが動くわけがない」と思う人も多いはずですが、DoomPaintは実際にMicrosoft Paintのキャンバスが毎秒何度も更新され、キーボードで移動や攻撃ができます。見た目としては本当にペイント上で『DOOM』が動いているように見えますが、その裏側の仕組みは一般的なゲームの表示方法とはまったく異なります。
結論からいえば、DoomPaintはペイントへ『DOOM』のゲームエンジンを移植したものではありません。別のプログラムで動いている『DOOM』の映像を、Windowsのクリップボード経由で1フレームずつペイントへ貼り付け、ペイントを特殊な外部モニターとして利用する仕組みです。
この記事では、DoomPaintがどのように映像を表示しているのか、なぜクリップボードだけでゲームとして成立するのか、Ctrl+Zでゲームを巻き戻せる理由まで、公式リポジトリの情報にもとづいて解説します。
目次
要点まず何が起きたか
Microsoft AzureのCTO兼テクニカルフェロー、マーク・ルシノビッチ氏が2026年8月2日、GitHubで「DoomPaint」を公開しました。ゲーム処理は研究用ライブラリ「ViZDoom」が担当し、完成した映像をDIB形式の画像としてクリップボードへ渡し、Microsoft Paintへ貼り付けて表示します。ゲームデータには再配布可能なシェアウェア版DOOM1.WADが同梱され、プログラム本体はMITライセンスでGitHub上に公開されています。

基本情報DoomPaintとは|開発者とゲームデータのライセンス
DoomPaintは、Microsoft Paintを『DOOM』のディスプレイとして使用するWindows向けの実験的なプログラムです。ゲームの処理には、研究やAI開発などにも利用される「ViZDoom」が使われています。ViZDoomがゲームの進行、敵の動き、当たり判定、プレイヤー操作などを処理し、完成した各フレームの画像をMicrosoft Paintへ送ります。
ゲームデータには、再配布可能なシェアウェア版の「DOOM1.WAD」が含まれています。そのため、別途『DOOM』を購入していなくても、シェアウェア版に収録されたエピソード1をプレイできます。シェアウェア版に含まれないマップについては、オープンソースの『DOOM』互換ゲームデータ「Freedoom」が利用されます。製品版のdoom.wadやdoom2.wadを所有している場合は、指定のフォルダへ配置して音楽データなどを利用することも可能です。DoomPaintのソースコードはGitHubで公開されており、プログラム本体にはMITライセンスが適用されています。ただし、同梱されているDOOM1.WAD、Freedoom、OpenALなどには、それぞれ異なるライセンスが適用されます。
役割分担ペイント自体はDOOMを処理していない
DoomPaintの仕組みで最も重要なのは、Microsoft Paintが『DOOM』のゲーム処理を行っているわけではないことです。敵の位置、プレイヤーの移動、銃撃、ダメージ計算、マップの描画といった処理は、すべてViZDoom側で実行されます。Microsoft Paintが担当するのは、ViZDoomから受け取った画像をキャンバスへ表示することだけです。
通常のPCゲームでは、ゲームエンジンが作った映像をDirectXやVulkanなどのグラフィックスAPIを通して画面へ表示します。一方、DoomPaintでは、ゲームエンジンが作った映像をWindowsのクリップボードへ入れ、コピーした画像としてペイントへ貼り付けます。DoomPaintの作者も、ペイントはゲームを描画しているものの、ゲームの計算処理は行っていないと説明しています。つまり、DoomPaintは「ペイントへの完全移植」というより、ペイントを特殊な外部モニターとして利用する仕組みです。
DoomPaintでは、最初にViZDoomがバックグラウンドで『DOOM』を起動します。このとき、ViZDoom自身のゲームウィンドウへ映像を表示するのではなく、ヘッドレス状態でゲームを動作させます。ヘッドレスとは、プログラムの処理は実行するものの、通常の画面を表示しない動作方式です。ゲームエンジン側は『DOOM』本来の1秒間35ティックで動作し、ペイントへの貼り付けが遅い環境でも、実際に経過した時間に応じてゲームを進める設計になっています。そのため、表示フレームレートが低下しても、ゲームそのものがスローモーションになるとは限りません。
転送方式各フレームをクリップボードへ格納する
ViZDoomが生成したフレームは、Windowsで画像をコピーするときに使われるDIB形式へ変換されます。DIBは「Device Independent Bitmap」の略で、Windowsアプリ間でビットマップ画像を受け渡すときに利用されるデータ形式です。DoomPaintは、各フレームをDIBとしてWindowsのクリップボードへ公開したうえで、ペイントに対してCtrl+Vの貼り付け操作を送信します。ペイント側から見ると、ユーザーが普通の画像をコピーしてキャンバスへ貼り付けた場合と大きく変わりません。
DoomPaintはこの処理をゲームの進行に合わせて繰り返します。最初のフレームを貼り付け、次のフレームが完成したら新しい画像を貼り付け、さらに次の画像を貼り付けるという処理を高速で繰り返すことで、静止画の連続が動画のように見えます。
技術的な壁単純なコピペでは動かなかった問題とOLEによる解決
DoomPaintは、一見するとクリップボードの画像を繰り返し交換するだけで実現できそうに見えます。しかし、通常のクリップボード操作で毎フレーム画像を書き換えると、ペイント側の読み込みが完了する前に、次のフレームによってクリップボードのデータが消される問題が発生しました。Microsoft Paintは、貼り付け操作を受け取った瞬間にすべての画像データを読み終えるわけではなく、内部では非同期で画像を取得してキャンバスへ反映します。ペイントが前のフレームを読み取っている途中でDoomPaintがクリップボードを空にすると、ペイントが必要としていた画像データまで解放され、貼り付け処理に失敗してエラーが表示されていました。画像サイズやPC性能によって貼り付け時間が変化するため、一定時間待ってから次のフレームを送る方法だけでは、問題を完全には防げませんでした。
この競合を解決するため、DoomPaintではWindowsの「OLE(Object Linking and Embedding)」機能が利用されています。OLEはWindowsアプリ間でオブジェクトやデータを交換するための仕組みです。DoomPaintは毎回クリップボードを空にして画像を入れ直すのではなく、IDataObjectというオブジェクトを一度だけクリップボードへ登録します。ペイントが画像を必要とすると、登録されたIDataObjectのGetDataを呼び出し、DoomPaintはその時点で利用できる最新フレームのデータを返します。クリップボードの所有者となるオブジェクトは参照カウントによって管理されるため、ペイントが前の画像を読み取っている途中でもデータが突然無効になりません。GetDataが呼び出されたことは、ペイントがフレームを受け取ったという完了通知としても利用され、DoomPaintはペイントの処理能力を超える速度で画像を送り続けることもありません。
代替手段Ctrl+Vが効かない場合はメニューから貼り付ける
DoomPaintは基本的に、疑似的なCtrl+V入力を送って各フレームをペイントへ貼り付けます。ただし、Microsoft PaintのバージョンやWindows環境によっては、プログラムから送られたCtrl+Vが認識されないことがあります。そこでDoomPaintは起動時に貼り付け方法をテストし、Ctrl+Vが正常に機能する場合はそのまま使用し、失敗する場合はWindowsの「UI Automation」を使って、ペイントの編集メニューから貼り付けを選択します。メニュー経由の貼り付けは安定していますが、各フレームで編集メニューが一瞬表示されるため、Ctrl+Vよりも画面上の動きが目立ちます。通常はメニューを開かないCtrl+V方式が優先され、必要な環境だけがUI Automation方式へ切り替わります。
アンドゥの正体Ctrl+Zで巻き戻せる理由
DoomPaintでは、それぞれのフレームが単なる画面表示ではなく、ペイント上の実際の編集操作として扱われます。ペイントへ画像を貼り付けると、画像は選択状態のままキャンバスへ配置されます。次の画像を貼り付けると、前の選択範囲が確定し、新しい画像が選択状態になります。DoomPaintはこの挙動を利用し、フレームを確定させるための追加クリックやEscキーを送らず、次の貼り付けによって前のフレームを確定させています。
各フレームがペイントの編集操作として記録されるため、Ctrl+Zを押すと直前に貼り付けたフレームへ戻れます。ゲーム内で倒された後にCtrl+Zを何度も押せば、ペイントのキャンバスだけは倒される前の映像まで巻き戻せます。ただし、ViZDoom側のゲーム状態そのものが巻き戻るわけではありません。DoomPaintの説明では、この動作を「時間を巻き戻す」と表現していますが、実際にはペイントの編集履歴を逆方向へたどって、過去のゲーム画面を表示している仕組みです。また、貼り付けられたフレームは実際にキャンバスへ配置された画像であるため、ペイントの保存機能を使えば、表示中の『DOOM』の画面を一般的なPNG画像として保存することもできます。
性能の上限フレームレートと解像度の関係|最大35fps
オリジナルの『DOOM』は、ゲーム内部が1秒間35ティックで進行します。DoomPaintもViZDoomを35Hzで動作させているため、理論上の表示上限は毎秒35フレームです。実際のフレームレートは、『DOOM』側の35Hzと、使用しているPCでペイントが画像を貼り付けられる速度のうち、遅い方に制限されます。DoomPaintは、ペイントが前のフレームを読み終えたことと、ゲームエンジン側で新しいフレームが完成したことの両方を確認してから次の貼り付けを行うため、PC性能に応じて動作速度が自然に決まります。
DoomPaintでは、640×400、640×480、320×200、320×240の解像度を選択できます。標準設定は640×400ですが、クリップボード経由で転送する画像のピクセル数が多いため、PCによっては貼り付け速度が低下します。320×200へ変更すると総ピクセル数が4分の1になり、ペイントが処理するデータ量も大幅に減るため、『DOOM』本来の35Hzに近い速度で表示しやすくなります。320×200はオリジナル版『DOOM』の内部解像度で、当時のCRT表示に近い4対3の画面比率で見たい場合は320×240を選択できます。『DOOM』自体のゲーム処理は非常に軽いため、負荷になりやすいのはViZDoomの3D描画よりも、各フレームを画像へ変換してクリップボードへ渡し、ペイントへ貼り付ける処理です。高解像度で35fpsに届かない場合は、まず320×200または320×240を試すのが現実的です。
操作方式キー入力の処理|低レベルキーボードフックとアプリ切り替え時の一時停止
DoomPaintをプレイしている間、アクティブなウィンドウはMicrosoft Paintです。そのままWASDや矢印キーを押すと、本来はペイントの選択範囲が動いたり、メニューが操作されたりします。DoomPaintでは「WH_KEYBOARD_LL」と呼ばれるWindowsの低レベルキーボードフックを利用し、ペイントが前面に表示されている間だけ、ゲーム操作に使うキーを捕捉します。捕捉した入力はViZDoomへ渡され、Microsoft Paint側には届かないように処理されます。
WとSまたは上下キーで前後移動、AとDまたは左右キーで旋回し、QとEで左右へ平行移動します。CtrlまたはFで攻撃し、Spaceでドアやスイッチを操作します。Shiftは走る操作、F12は終了操作です。PowerToysなど別のユーティリティがCtrlキーを捕捉する環境や、リモートデスクトップ、仮想マシンでCtrlキーが正しく届かない環境を考慮し、攻撃にはFキーも割り当てられています。
低レベルキーボードフックがゲームキーを捕捉するのは、Microsoft Paintが前面にある場合だけです。Alt+Tabなどで別のアプリへ切り替えると、DoomPaintはゲームを一時停止します。クリップボードも、ゲーム中に別のアプリが使用する可能性を考慮して管理されており、ユーザーが別のアプリへ切り替えて何かをコピーすると、DoomPaintは一時的にクリップボードの所有権を失います。ペイントへ戻って次のフレームを表示するときに、DoomPaintが再びクリップボードを取得する設計です。
サウンド効果音と音楽にも対応
DoomPaintは、映像だけでなく効果音と音楽も再生できます。銃声や敵の効果音はViZDoomからOpenALを通して出力されます。音楽はViZDoomから直接再生されるわけではなく、DoomPaintがWADファイルからステージの音楽データを取得し、『DOOM』のMUS形式からMIDIへ変換したうえで、WindowsのMIDI機能を使用して再生します。別のアプリへ切り替えてゲームを一時停止すると、音楽も一緒に停止します。起動オプションを指定すれば、すべての音を無効にしたり、効果音だけを残して音楽を停止したり、音楽の音量を変更したりできます。
導入方法DoomPaintを動かすにはPythonが必要
DoomPaintのリポジトリにはrun.batが用意されています。Windows PCへソースコード一式を保存し、Pythonを利用できる状態でrun.batを実行すると、初回起動時にPythonの仮想環境が作成され、必要なライブラリが自動的にインストールされます。使用される主なライブラリはViZDoom、NumPy、Pillow、pywin32、pywinauto、pycawです。ViZDoomがゲームを動かし、PillowやNumPyが画像データを扱い、pywin32やpywinautoがWindowsとMicrosoft Paintを操作します。pycawはWindowsのオーディオセッション制御に使用されます。
run.batを実行するとMicrosoft Paintが開き、ペイントを前面にしたままキーボードで操作します。一般的な完成済みPCゲームのように、インストーラーを実行するだけのソフトではなく、GitHubからソースコードを取得し、Python環境を用意する必要があるため、PC操作に不慣れな人には少し難しい可能性があります。また、作者個人のGitHubリポジトリで公開されている実験的なプロジェクトであり、WindowsやMicrosoft Paintへ正式に追加された機能ではない点にも注意してください。公式な最低スペックや推奨スペックは設定されていませんが、GPU性能より、CPU性能、Windowsの動作状況、Microsoft Paintのバージョン、クリップボード処理の速度などが影響すると考えられます。
背景なぜDOOMはさまざまな機器へ移植されるのか
『DOOM』は1993年に登場したFPSで、ゲームエンジンのソースコードは1997年に公開されました。現在はid SoftwareのGitHubでもソースコードが公開されています。比較的単純な入出力環境でも動作させやすく、ゲーム画面のピクセル出力とキー入力を別の機器やアプリへ接続することで、通常はゲーム用途を想定していない環境にも移植できます。電卓、家電、組み込み機器、ブラウザ、ターミナルなど、さまざまな環境で『DOOM』を動かす試みが続いてきました。
DoomPaintもその流れにあるプロジェクトですが、単にペイントのウィンドウの上へ別のゲーム画面を重ねているわけではありません。各フレームを本当にペイントへ貼り付け、編集履歴に残し、ペイントの保存機能で画像として保存できるところが特徴です。クリップボード、OLE、IDataObject、UI Automation、低レベルキーボードフック、Windowsオーディオといった既存の機能を組み合わせ、ペイントをゲーム画面として利用しています。DoomPaintは一見すると技術者の冗談ですが、Windowsアプリ間のデータ交換、非同期処理、入力フック、フレーム同期など、一般的なアプリ開発にも関係する技術が詰まっています。
Q&Aよくある質問
総括まとめ|Windowsの仕組みを正しく悪用した実験プロジェクト
DoomPaintは、Microsoft Paintそのものへ『DOOM』を移植したプログラムではありません。ViZDoomがバックグラウンドでゲームを処理し、生成された各フレームをDIB画像としてWindowsのクリップボードへ送り、Microsoft Paintのキャンバスへ連続して貼り付けています。通常のクリップボード処理で発生するデータ競合は、OLEのIDataObjectを利用して解決し、ペイントが画像を読み取ったことを確認してから次のフレームを送るため、PC性能に合わせて貼り付け速度が自動的に調整されます。
キー入力は低レベルキーボードフックで捕捉され、ペイントには送らずViZDoomへ渡されます。映像だけでなく、銃声、敵の効果音、ステージ音楽にも対応し、各フレームがペイント上の編集操作として残るため、Ctrl+Zで過去のゲーム画面へ戻ったり、現在のフレームをPNG画像として保存したりできる点もDoomPaintならではの特徴です。
ペイントが『DOOM』を計算しているわけではありませんが、ペイントを実際の表示装置として使い、最大35fpsでプレイ可能にしたWindows技術の実験として、完成度の高いプロジェクトといえます。

