オンラインのPCゲームをプレイしたことはありますか?
最近はクロスプラットフォーム対応がどこにでもあり、考えることなくほぼどんなデバイスでもゲームに飛び込めます。
でも、ほんの数年前に「PCゲーム」と聞けば、ほとんどの場合Windows専用という意味でした。
ものすごく長いダウンロードとインストールを待って、ようやくゲームを起動する——そんな儀式を、私たちの多くはあまりにもよく覚えています。
今回は、2003年のWindows専用オンラインTPSであるGunZ: The DuelをWebAssemblyとWebGLでブラウザに完全に持ち込みました。
ダウンロード不要。インストール不要。
やることは、Google Chromeでページを開くだけです。
たぶん私だけかもしれませんが、かつてはセットアップに何時間もかかったゲームを……リンクをクリックするだけで遊べるのって、ちょっと魔法みたいじゃないですか?
ちなみに:元のソースコードにはほとんど手を入れていません。新しいコードの約99%はAIが書きました。
この記事では、GunZをブラウザへ移植する技術的な道のりと、AIコーディング支援がゲームを変えるまで「不可能だと考えられていたこと」の実例を両方紹介したいと思います。
GunZ: The Duel — 今や完全なWebゲーム
GunZは韓国のMAIET Entertainmentによって開発されました。その特徴的なゲームプレイ——壁走り、空中コンボ、空中で剣と銃を切り替える——は、非常に独自でした。当時、私はそれに夢中になっていました。
2007年にソースコード一式(C++クライアント+サーバ)が流出し、それ以来コミュニティが維持し続けています。
このゲームは20年以上前のものです……そして誰もが「ブラウザで動かす」ことに成功したことはありませんでした——これまでは。
目を疑うほどのGunZ:https://gunz.sigr.io/
リンクを開いてそのまま遊ぶだけ。Windowsは不要です。Linux、macOS、iPhone、Android——ほぼ何でも動きます(ただし、モバイルで本気でプレイするのは……難しいですが)。
これは「なんとか動く」や「似たように見える」デモではありません。
2003年当時とまったく同じように動く、完全なオリジナルゲームです。
この投稿では以下を扱います:
- どうやって実現したのか
- 20年経った今、なぜやろうと思ったのか
- これまでの失敗のすべて
これまでの失敗と、完全なブラウザ移植への道のり
失敗に終わったこれまでの試み
これはブラウザ版GunZへの挑戦が初めてではありません。
数年前に、JavaScript + Three.jsで最初から作り直そうと試みました:
https://github.com/LostMyCode/three-gunz
マップの描画は動くようになりましたが、ゲームエンジン全体を作り直すのは圧倒的に大変でした。このプロジェクトは静かに終了しました(気になるなら、レポジトリはまだ残っています)。
WebAssemblyルート
GunZはほとんどがC++で書かれています。
C++をEmscriptenでWebAssemblyにコンパイルできることは皆知っているので、理屈の上では簡単なはずですよね?
違いました。
GunZは非常にWindowsに依存しています。レンダリング、オーディオ、入力——あらゆるところでWindows固有のAPIを呼び出しています。レンダリングエンジンはDirect3D 9を直接使っています。
Emscriptenは、Direct3Dの呼び出しを魔法のようにブラウザが理解できるものに変換してはくれません。
そのため、真面目な移植には、レンダリングコードを何千行も書き換えてWebGLを使う必要がありました。
そんなの手作業でやるわけがありません。
だからこそ、このプロジェクトは何年もの間「理論上は可能だけど、完成する前に死ぬだろう」というカテゴリに留まりました。
そしてAI時代がやってきた
ずっとこう考えていました。「C++のソースは存在する……使えさえすれば。」
自分で移植するのはできませんでした。でも、AIが大変な部分を書いてくれたらどうでしょう?
強力なコーディングエージェントが信頼できるようになってきたことで、ようやく試してみる決心がつきました。
使ったのは2つのツールです:
- Google Antigravity(AI Proプラン — ¥2,900/月)
- Claude Code(Max 5xプラン — $100)
まずはGoogle Antigravityから始めました。
AIが対応したこと:
- 巨大なC++コードベースの解析
- Windows APIへの依存をすべて見つけること
- Direct3Dの呼び出しの抽象化
- Emscripten向けにビルドシステムを修正すること
AIが巨大なレガシーコードベースを、日ではなく数時間で理解してリファクタリングするのを見たのは、正直ぶっ飛びました。ある晩、友達と飲みに出て…帰ってきたら、その作業は完了していました。今までで初めて感じたあの高揚感。
Googleのプランは最高でした—しかし、Googleが突然レート制限を厳しくしました。この規模のプロジェクトなら、週次のクォータに即座に引っかかります。
そこで、Claude Codeに切り替えました($100 Max 5xプラン)。
$100ティアでも制限に当たるのではと怖かったのですが—当たりませんでした。クォータの減り方はほとんど動きません。Antigravityで1週間止まっていたバグが、数時間で直りました。
Windowsへの依存を取り除いた方法 — リアルタイムのDirect3D → WebGL変換
最大の障害はレンダリングエンジンでした。何万行ものコードが、すべてDirect3D 9を直接呼び出していました。
すべての呼び出しを書き換えるのは正気の沙汰じゃない。
完全なトランスパイラを作るのも現実的ではありませんでした。
そこで、代わりにこうしました:
「ゲームがこれまで通りDirect3Dを呼び続けるなら、その代わりに、あらゆるコマンドをその場でWebGLへ変換すればよくない?」
まさにそれを作りました。
https://github.com/LostMyCode/d3d9-webgl
ゲームとグラフィックスAPIの間に翻訳レイヤーを挿入しました。
元のゲームコードは100%そのままにしました。
| アプローチ | 意味すること | 問題 |
|---|---|---|
| ゲームコードを手動で書き換える | D3D9の呼び出しをすべてWebGLへ変更する | 変更は数万件—保守不能 |
| トランスパイラを作る | D3D9 → WebGLを自動変換する | セマンティクスの違いにより不可能 |
| 翻訳レイヤー | WebGLを出力するD3D9互換API | ラッパーを実装するだけで済む |
この方法なら、元のゲームに手を加えずに、最大のWindowsへの依存を取り除けました。
(繰り返しますが、主にAntigravityとClaudeがやってくれました—これらのAIは恐ろしいほど優秀です。)
興味があれば、D3D9→WebGLラッパーについて別に詳しく掘り下げて書きました:
私が移植しなければならなかった「その他すべて」
レンダリングが最も大変でしたが、それだけではありませんでした。
ネットワーク:サーバーはブラウザ内で動く
この部分は誰もが驚きます。
私は元のC++サーバーもWebAssemblyにコンパイルし、同じブラウザタブ内でWeb Workerとして実行しています。
実際のネットワークパケットの代わりに、クライアントとサーバーはpostMessageで通信します。
すべてが1つのタブ内でローカルに動作します。
プレイヤーデータ、ステータスなどはSQLite + IDBFS(IndexedDB)で保存されるので、タブを閉じても進行状況が残ります。完全にサーバーレスのゲームサーバーです。
もちろん、他の人とオンラインで遊ぶために、WebSocket経由で実サーバーに接続することもできます。
サウンド:FMOD → Web Audio API(1,260行)
元のゲームはFMODを使っていました。私はそれを完全にWeb Audio APIに置き換え、3Dの空間オーディオ(PannerNode)、BGMのストリーミング、距離によるカリング、そしてゲームが必要とするその他すべてを再実装しました。
入力:ブラウザのイベントをWin32メッセージに変換
私はキーボード/マウスのブラウザインベントを、元のエンジンが期待するまさにそのWin32メッセージ(WM_KEYDOWN、WM_MOUSEMOVE、WM_CHARなど)に変換します。
マウス捕捉にはPointer Lock API、ログイン用テキスト入力にはHTMLの<input>オーバーレイも必要でした。
ファイルシステム&アセット読み込み:2段階 + キャッシュAPI
GunZのアセットはカスタムの.mrsアーカイブに保存されています。
まず7つの重要ファイルを読み込み、次に残り(武器、マップなど)をバックグラウンドでストリーミングします。
キャッシュAPIにより、2回目以降の訪問は即座です。
ゲームデータの最適化(これが延々と大変だった)
すべてがネットワーク経由で届く必要があるので、私はデータを縮める作業に何週間も費やしました。
(デフォルト → v2 → … → v10)というふうにバージョンを作り続け、読み込み時間が許容できるところまで持っていきました。
最大の効果は?すべての効果音をWAVからOpusに変換したことです。
44.3 MB → 5.30 MB — 88%の削減。
| 項目 | WAV(Waveform Audio) | Opus |
|---|---|---|
| 圧縮 | なし(リニアPCM) | 非可逆(非常に効率的) |
| 音質 | 完璧(生) | 優秀(特に低ビットレート時) |
| ファイルサイズ | 巨大 | 小さい |
| 遅延 | ゼロ | 非常に低い(5〜26 ms) |
| ブラウザ互換性 | 普遍的 | モダンブラウザ&モバイル |
| ライセンス | 完全に無料 | ロイヤリティフリー |
結果は?10秒未満でプレイを開始できます。
すべてのアセットはS3 + CloudFrontから配信されるので、世界のどこからでも高速に読み込まれます。
最後に
ときには、ただ正しいタイミングを待つ必要がある
正しい瞬間を待つことが重要でした。
私はほとんどWebGLやDirect3Dのことを知りませんでした。もしこれを5年前にやっていたら、私は諦めていたでしょう。
でもAI時代になって、ようやく可能になりました。
ありがとう、Antigravity。ありがとう、Claude Code。この二人は伝説です。
当時GunZを遊んでくれたすべての人へ
できるだけ多くの昔のプレイヤーに、この懐かしさをもう一度味わってほしい――インストール不要で、クリックしてすぐに遊べます。
もし楽しんでいただけたなら、ぜひ共有してください!
そしてはい、Discordコミュニティもあります:
https://discord.gg/ABG8JxuBQm
20年後、子どもの頃のゲームが<canvas>タグの中で動いています。
クリックひとつで昔のゲームをWebに呼び戻すという夢が、ちょうど正しいタイミングで現実になりました。
こうしたことにワクワクして熱中する開発者ならもちろん、昔の栄光の日々をもう一度味わいたい人であっても——ぜひ一度試してみてください。
最後まで読んでくれてありがとうございます!
さあ、そのリンクをクリックして壁をぶち壊しにいってください。
- Whiplash GunZ Discord: https://discord.gg/ABG8JxuBQm
- 今すぐプレイ!: https://gunz.sigr.io/





















