📅 2026年04月08日 18:16
The tech behind words.zip (infinite mmo word search game) - words.zip の技術解説(無限 MMO ワードサーチ)
魅惑の無限キャンバスを支える“種(seed)だけで再現する”技術 — オフラインでも動く協調型ワードサーチの作り方
要約
words.zip は「座標のハッシュ+1つの辞書」で無限の文字盤を生成し、Firestore の“チャンク”設計と OffscreenCanvas+Web Worker による事前ラスタライズで軽快な協調体験を実現している。
この記事を読むべき理由
無限キャンバスや大規模リアルタイム協調アプリを作りたい人にとって、帯域・課金・レンダリング問題を現実的に解決した設計が学べるため。日本語など多言語対応やモバイル回線での実装にも応用しやすい実践的パターンが詰まっています。
詳細解説
- スタック
- フロントは静的ホスティング。バックエンドは Firebase + Cloud Functions(monkeys.zip の Supabase/Postgres とは対照的)。Firebase のリアルタイム購読は強力だが、ドキュメント当たり QPS・サイズ・コストに注意する必要がある。
- 文字生成(プロシージャル)
- 全文字盤をサーバに保持しない代わりに「単一の seed」と座標ハッシュ(改変した MurMurHash)でその位置の文字を決定。英語の頻度に重みづけして選ぶため、クライアントはオフラインでも任意地点を再現可能で、帯域・ストレージが劇的に節約できる。
- 辞書最適化
- 外部辞書を採用し、長さ <3 / >12 の単語を削除。gzip 後で約 600KB 程度に収まり、ほぼ固定でキャッシュ可能。隠し実績(惑星名など)も追加している。
- 単語保存とチャンク化(Firestore)
- 見つかった単語は即座に submitWord 関数で検証後、128×128 文字の「チャンク」ドキュメントに格納。各単語は開始セルに紐づけられるため、ユーザーが見ている領域のみ購読すればよく、読み取りコストを爆発させない。もし単語ごとにドキュメント化していたら数千読み取りが発生していた可能性がある。
- コンパクトな符号化
- 単語は座標列を保存せず、「開始位置 + 方向の整数配列」で表現(例: [3,3,1] が「下、下、右」)。これでチャンクサイズが約35%削減され、さらにフロントで同じ“形”を再利用できるため描画コストも削減できる。
- フロントのチャンク設計とスケール戦略
- Google Maps 的な多解像度チャンク(8セル〜256セル)を用いて、ズームレベルに応じた事前レンダリングビットマップをキャッシュ。最遠では数百万文字が一望できるが、低解像度では3x3ピクセル文字やノイズで代用するトリックを使う。
- OffscreenCanvas + Web Worker によるラスタ化
- チャンク描画をワーカー内で OffscreenCanvas にレンダライズし ImageBitmap としてメインスレッドへ渡す。これによりメインスレッドの入力処理をブロックせず、パンやズームが引っかからないスムーズな UX を実現する(遅さは「タイルが一時的に鮮明でない遅延」として現れる)。
実践ポイント
- 小さな seed ベースのプロシージャル生成はオフライン対応と帯域削減に有効。言語特性(日本語は文字数多・可変幅)を考慮してアルファベット向け手法をそのまま使わないこと。
- Firestore を使うなら「領域チャンク化(例: 128×128)」+「単語の方向符号化」で読み取り・コストを抑える。
- フロントはチャンク単位で事前レンダリングし、OffscreenCanvas を Web Worker で使って ImageBitmap を返すパターンを採ると描画ジャンクが激減する。
- 辞書は用途に応じてトリミング/圧縮して配布(gzipped ≲ 1MB が理想)。日本語辞書は形態素解析や文字セットの扱い(UTF-8バイト増)を考慮する。
- Firebase のドキュメント単位 QPS・サイズ・請求モデルに注意。スケールしたら Cloud Functions や分割設計、あるいは別の DB(Postgres 等)への切替を検討する。
以上のアーキテクチャは「無限」「協調」「低帯域・低遅延」を両立させる良い教科書です。日本語のワードサーチ化やモバイル向けローカル最適化にも応用できます。