みなさん PC のオンラインゲームはプレイしたことがありますか?
最近では環境に依存せずクロスプラットフォーム対応のゲームも多いですが、昔は PC ゲームといえば windows のみ対応で長い長いダウンロードとインストール作業をしてようやく遊べるようになるのが普通でした。
今回私は2003年にリリースされた Windows 専用のオンラインTPS「GunZ: The Duel」を、WebAssembly と WebGL を使ってブラウザ上で動くようにしました。
ダウンロード・インストールは不要!
やることはただ1つ。 Google Chrome でページを開くだけ。
私だけかもしれませんが、当時は何時間もかけてダウンロード・インストールしてようやく遊べたゲームを ただサイトを開くだけ でプレイできたら感動しませんか?
また今回、ほとんど既存のソースコードを変えておらず、新規で必要な実装の 99% を AI に作業させることで 人間では途方もない作業だから数年規模の実装 とされているところ わずか3週間程度 で実現できました。
GunZ のブラウザ移植を題材に、その技術面や、これまで不可能だったことが AI によって実現できた例としてご紹介できればと思います。
GunZ The Duel を WEB ゲームとして移植した
GunZ は韓国の MAIET Entertainment が開発し、日本でも GameOn が運営していたオンラインゲームです。壁を蹴って飛び、剣と銃を切り替えながら空中で戦う独特のアクションが特徴で、私も昔プレイしていました。
2007年頃にソースコード(C++ のクライアント/サーバー全コード)がリークし、以降コミュニティがソースコードをメンテナンスしてきました。
20年以上の歴史があるのですが、誰も成し遂げたことのなかったブラウザで動作させるというのを実現し公開しました。
リンクを開けばすぐに遊べます。 windows である必要すらありません。Linux, MacOS, iPhone, Android あらゆる端末で動作します(スマホでプレイは無理がありますが笑)
「一部移植できた」「それっぽいのを作った」... ではありません。 元のゲームと完全に同じように動作します。今回はゲーム全体をフルで移植しました。
- どうやって実現したのか?そこに至るまで
- なぜ 20 年前のゲームをこのタイミングで?
- 過去の失敗
などすべてお話できればと思っています!
過去の失敗とブラウザ完全移植を成し遂げるまで
過去の失敗
実はブラウザで GunZ を動かす試みはこれが初めてではなくて。
以前、JavaScript と Three.js を使って1からブラウザ版を作ろうとしたことがある。
マップの描画までは動いたが、ゲームエンジン全体を再実装する壁は高く、プロジェクトは頓挫しました。(リポジトリは今も残っている)。
ブラウザ移植の別のアプローチ
GunZ のソースコードはほぼすべてが C++ で書かれている。
そして、知っている人もいると思いますが C++ で書いたコードをブラウザで動かすことは可能です。Emscripten を使って C++ コードを WebAssembly (wasm) にコンパイルすることができます。
これを使えば GunZ もさくっと wasm に!...とはいきません。
タイトルの通り、 GunZ は べったり windows 依存のゲーム なのです。
windows 用のゲームはレンダリングなどの処理に windows 固有の Direct3D などの API を呼びます。これがあると、もちろんブラウザにはそんな API はないので Emscripten をもってしてもブラウザで動作させるのは 不可能 です。
Direct3Dは、3Dグラフィックスを描画するためのAPIである。マイクロソフトが提供するマルチメディアAPIセットDirectXの一部であり、様々なWindows(主にWindows 95以上)で動作し、さらに、家庭用ゲーム機であるXboxシリーズ(初代Xbox、Xbox 360、Xbox One、Xbox Series X/S)のグラフィックスAPIのベースでもある。略称としてD3Dがよく使われる。 ― wikipedia
基本的にプラットフォーム固有の依存がないものしか WebAssembly へのコンパイルはできないんですね。
つまり Direct3D に依存したゲームを移植するのであれば、ブラウザでも動作するような WebGL などの描画命令に書き直すことは避けられないのです。 これは理論上可能でも学習時間も入れたら途方もない工数です。
そんな作業やってられるわけない!!!
てなわけで長いこと「理論上はできるけど、それで寿命を迎えそうだから手を出さない」状態で数年が過ぎました。(three-gunz で GunZ のマップだけ移植してから約4,5年の期間が空いています)
AI の時代が来た
「C++ のソースコードがあるんだから、どうにかしてブラウザで動かせるんじゃないか?」とずっと思っていました。
自力で移植するなんて途方もない ── そう思って手が出なかったが、AI がコーディングの領域でも力を発揮するようになった今なら実現できるんじゃないか。
自分で書けないなら全部 AI に書かせればいいんじゃない?
そう考えて、ついに本格的に完全移植プロジェクトを始動させることにしました。
使ってみたのは以下の2つ
- Google Antigravity (AI Pro プラン 3000 円)
- Claude Code (Max 5x プラン 100 ドル)
最初は Google Antigravity で開発を始めました。
Antigravity では、主に以下のような作業を AI に任せていました。
- 巨大な C++ コードベースの解析
- Windows API 依存箇所の洗い出し
- Direct3D 呼び出しの抽象化
- Emscripten でコンパイルするためのビルド修正
人間がやると数日かかりそうな 「コードベース全体を理解して修正箇所を洗い出す作業」 を、AI がかなりの速度で進めてくれるのは正直かなり衝撃でした。
友人と飲みに行ってる間に作業が進んで終わっているという初めての感動体験をくれたのは Antigravity でした。
Google AI Pro の月額 3,000 円は破格で、1日中動かしてもクオータ上限が全然気にならなかった ── 途中で Google が上限を引き締めるまでは・・・
Google さんさすがにマズイと思ったのか途中でレート制限を厳しくしたんですよね。そりゃ GunZ みたいな企業が開発した規模のソースコードで作業させたら速攻で週次制限に引っかかるようになりました。
次に使ってみたのが Claude Code です。
Pro プランは絶対クオータ上限に到達しそうと思って思い切って 100 ドルの Max 5x プランをサブスク。
これがすごくてクオータも全然減らないし(というか使い切れないw)、 Antigravity で1週間くらい詰まっていたバグを数時間で解決してくれた。
windows 依存を剥がした方法は? Direct3D の命令をリアルタイムで WebGL に変換!
先ほども説明したとおり windows でしか使えない Direct3D の描画命令をどうにかしてブラウザでも動くものに置き換えないといけなかったわけですが。
これは企業が作った大規模なゲームです。
個人の趣味プロジェクトではなく、企業が開発・運営していた商用ゲームのコードベースであり、レンダリングエンジンだけで数万行。3Dモデル描画、マップ描画、UI描画、エフェクト ── すべてが Windows 専用の描画API(Direct3D 9)を直接呼んでいます。
当然、 Direct3D で描画している処理をすべて置き換えるのは途方もないしバグが起きる可能性も高い。
「じゃあ Direct3D の呼び出しを全部そのままにして命令を全部リアルタイムで WebGL に変換すればいいんじゃね?」
って思って作りました! D3D9 の命令呼び出しをそのまま WebGL 変換してブラウザで描画できるラッパー。
以下のように Direct3D のメソッド呼び出しをしていても書き換えずにそのまま WASM にして WEB で動かせる。
| アプローチ | 内容 | 問題 |
|---|---|---|
| ゲームコードを直接書き換え | 全ての D3D9 呼び出しを WebGL に変更 | 数万行の改変、上流追従が不可能に |
| 自動変換ツール | D3D9→WebGL のトランスパイラを作る | API の意味的な違いを機械的に変換できない |
| 翻訳レイヤー | D3D9 と同じ API を持つ WebGL ラッパーを作る | ラッパーの実装コストのみ |
ゲーム側は一切触らず、ゲームと描画APIの間に「翻訳レイヤー」を挟むアプローチ ですね。
この D3D9 to WebGL ラッパーによってゲーム側の描画実装を全く変えずに、最大の windows 依存を取り除くことに成功しました。
自分で作ったんじゃなくて Antigravity と Claude Code のエージェントが頑張ってくれました。この子たち、なんでもできるやん!
(簡単そうに書いてますが、ちゃんと描画できる状態になるまで何週間か費やしています)
この D3D9 変換部分については別で記事書いてるのでよかったら読んでみてください。
描画以外の移植
描画が最大の課題だったのは確かです。しかし、 GunZ をブラウザで動かすには描画以外にも乗り越えるべき壁がいくつもありました。それについてもいくつか紹介します。
ネットワーク:ゲームサーバーもブラウザの中で動いている
冒頭にも書きましたが、このプロジェクトで一番驚かれるのはこの部分かもしれません。
ゲームサーバーも 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段階ロード + Cache API
ゲームのアセットは .mrs という GunZ 独自アーカイブ形式で配布されています。これらを Emscripten の MEMFS に配置し、2段階でロードするようにしました。
具体的には、起動に必須な7つのみを起動前にロードし、装備パーツなどの追加アセットはバックグラウンドでダウンロードします。ブラウザの Cache API を使うことで、2回目以降はネットワークアクセスなしで起動できるようになっています。
ゲームデータの最適化
ブラウザで動かすということは当然ゲームに必要なデータはネットワークから取得する形になります。
本来ならローカルのファイルを読み取るのを GET リクエストを飛ばして必要なゲームデータを持ってくるというのに変える必要があります。
そのため、何をどのタイミングでロードするかを適切に調整しないとゲームを起動する前のデータ DL で数分かかるという状況になります。
これを避けるためにゲームデータのサイズを削ったり、必要最低限のファイルのみを事前にロードするなどの最適化作業を地道にやる必要がありました。
ゲームデータ(mrs)のサイズを減らす方法を考えて作るの繰り返し
↓ 徐々にファイルサイズを削ったバージョンのゲームデータを作っている(default -> v2 ... v9 -> v10)
音声フォーマット変換が効果大
ちなみに効果大きかったのは効果音の音声ファイルの変換です。
すべて wav 形式だったので opus 形式に変換したところ約 44.3 MB から 5.30 MB に!ファイルサイズをトータルで 88% もカットしたことになります。
| 項目 | WAV (Waveform Audio) | Opus |
|---|---|---|
| 圧縮方式 | 非圧縮 (リニアPCM) | 可逆/非可逆圧縮 (主に非可逆) |
| 音質 | 極めて高い (原音そのもの) | 高い (圧縮率に対して非常に高音質) |
| データ容量 | 非常に大きい | 非常に小さい |
| 遅延 (レイテンシ) | ほぼゼロ | 非常に低い (5ms〜26.5ms) |
| 互換性 | 非常に高い (ほぼ全ての機器) | 高い (モダンなブラウザ、スマホ等) |
| ライセンス | 制限なし (オープン) | 制限なし (オープン、ロイヤリティフリー) |
| 主な用途 | 音楽制作、マスタリング、保存用 | ネット通話、ストリーミング、Web |
これは実際プレイして体感してみて欲しいのですが 10 秒以内にはプレイできる状態になる と思います。
アセットデータのダウンロード速度が安定することはマストなので、 S3 + Cloudfront の構成で CDN 経由でどのリージョンでも高速にデータを取得できるようにしました。
さいごに / 振り返り
やはりその時が来るまで待つのも重要
実は私はほとんど・全くといっていいくらい WebGL, Direct3D など 3D ゲームに関する知識はありません。やはり AI 時代であるこの時まで待ってから実行したのがカギだったと思います。そう、ずっとこの時を待っていた。
AI なしでは絶対にこの GunZ 移植計画は成し遂げられなかったでしょう。
ありがとう Antigravity, ありがとう Claude Code, よくやったぞ。
GunZ を昔プレイしていた方へ
懐かしの GunZ がダウンロードしなくても動くこの感動を他のプレイヤーたちにも届けたいのでぜひ広めてもらえると嬉しいです!
まとめ
20年前のゲームが、ブラウザの <canvas> の上で動いている。子供の頃に遊んだゲームを Web で蘇らせるというロマンは、思いがけずこの時になって実現するに至りました。
技術の面で興味を持ってくれる人、あの頃のゲームがクリックするだけで遊べる感動を共感できる人、そんな人たちに届いたらいいなと願っています。
ここまで読んでいただいてありがとうございました。ぜひ Discord コミュニティもやっているので参加してみてください!















Comments
ちゃんと読んでないけど、ソースコード使ってゲーム再公開とかしていいの?
公式が公認ならいいけどダメならヤバそう
Let's comment your feelings that are more than good