開発ブログ
ポケット箱庭の作りと技術スタック:システム構成図と、それぞれを選んだ理由
ポケット箱庭は、スマホのブラウザだけで動く3Dの建築ゲームです。この記事では、それがどんな部品でできているかを、システム構成図と技術スタックの一覧で説明します。あわせて、それぞれを選んだ理由と、公開してから作りながら変えたことをまとめました。
先に:3つの方針
- 預かるものを最小にする:作品も手持ちも、基本はスマホのブラウザの中に置きます。サーバーに置くのは、利用者が「作品を送る」を選んだときの作品データだけです。
- 無料の枠のなかで続けられる:サーバーを借りて動かし続けるのではなく、ブラウザの力と、無料で使える配信の仕組みを組み合わせています。
- 小さく、標準的に:エンジニアではない運営者が AI といっしょに作って、そのあとも自分で直していくので、凝った仕組みより、広く使われていて情報が多い部品を選びます。
システム構成図
ポケット箱庭の中身は、大きく3つに分かれます。箱庭を持って描くのはスマホのブラウザの中、静的ファイルの配信と小さな処理を受け持つのがCloudflare、広告やフォームなどは外部のサービスです。
ふだんの遊びは、最初にアプリのファイルを Cloudflare から受け取ったあと、ほとんどスマホの中だけで完結します。Cloudflare に何かを送るのは、「作品を送る」で短いリンクを作るときと、遊び方の記録(開いた・ブロックを置いた・10秒いた、のような出来事の種類)を匿名で送るときだけです。
箱庭のデータと描き方
箱庭は横64×奥行き64×高さ32のマスで、1マスに「素材」と「形」を詰めています。描くときは、これを16×16×16のかたまり(チャンク)32個に分けて、ブロックを置いたかたまりだけを作り直します。かたまりの中では、空気や透けるブロックと接している面だけを集め、同じブロックが並ぶ面は1枚の四角にまとめて(greedy meshing)、スマホでも軽く動くようにしています。詳しい話は「ブラウザだけで3Dの箱庭を動かすしくみ」に書きました。
ソースコードは TypeScript と Worker をあわせて約8,000行です。主な役割は次のとおりです。
- 箱庭のデータ:
world.ts(マスの保持)、mesher.ts(面をまとめて形にする)、surfaces.ts(ブロックの見た目) - 操作と視点:
input.ts(タップ・ドラッグ)、camera.ts、walker.ts(歩くモード)、compass.ts - 保存と共有:
storage.ts・backup.ts(保存と書き出し)、codec.ts(圧縮してリンクの文字にする)、share.ts・short-link.ts - 光と空:
lighting.ts(昼・夕日・夜)、sky.ts(雲・カラス・星) - 遊びの進み方:
progress.ts(レベルとお題)、inventory.ts(手持ち)、weekly.ts(今週のお題) - サーバー側:
worker/index.js(受け付けの入り口)、worker/share.js(短縮リンク)
公開の流れ
GitHub に変更を push すると、Cloudflare が自動でビルドします。main なら本番に、それ以外のブランチならブランチごとのプレビューURLに出ます。このサイトの記事や機能も、まずプレビューで見て確かめてから、本番に出しています。
技術スタック一覧
「役割:使っているもの」の順に、選んだ理由を添えています。
- 言語:TypeScript 5(厳格モード)
ブロックの種類・向き・手持ちなど、数字の取りちがいが起きやすいので、型で早めに見つけられるようにしたかった。AI が書いたコードの安全網にもなる - 3D描画:three.js 0.170(WebGL)
WebGL を直接書くのは大変。情報や実例が多く、スマホのブラウザでも影や光る素材まで描ける - ビルド:Vite 6
設定が少なく速い。Cloudflare 側はnpm run buildを実行するだけで済む - 圧縮:fflate 0.8.3(deflate)
小さなライブラリで、作品をリンクにするときに文字数を約3分の1にできた。バージョンを固定して使っている - 保存:localStorage + バックアップファイル(JSON)
サーバーもアカウントもいらず、作品を預からないので個人情報の心配が少ない。ブラウザの保存が消えるときの備えに、ファイルへの書き出しも用意した - オフライン:Service Worker(手書き)
ライブラリなしで小さく書ける。ページはネット優先、アプリ本体のファイルは控え優先にして、更新がすぐ届くようにした - 動画:MediaRecorder(ブラウザ標準)
サーバーで動画を作らず、画面の描画をそのまま録画する。費用がかからず、作品のデータも外に出ない - 配信・小さなサーバー処理:Cloudflare Workers(静的ファイル+Worker)
静的ファイルの配信と、短縮リンク・遊び方の記録のような小さな処理を、1つの場所で動かせる。無料の枠で足り、独自ドメインと、ブランチごとのプレビューも使える - 短縮リンクの保存:Workers KV
作品を「番号 → 作品データ」で置くだけなので、データベースほどの仕組みはいらない。読むことが多く書くことは少ない用途に合う - 遊び方の記録:Workers Analytics Engine
Cookie を使わず、1回の訪問ごとの使い捨ての番号で集計できる。個々の記録は約3か月で消える - アクセス解析:Cloudflare Web Analytics
Cookie を使わず、利用者を個人として識別しない - 広告:Google AdSense・H5 Games Ads
無料で続けるための収入源。読み込みは設定(環境変数)で切り替えられる作りで、メニューを開いたときなど、遊びのじゃまにならない場面だけに出す - ご意見・要望:Google フォーム
自前で入力欄とサーバーを作らず、メールアドレスも集めずに受け付けられる - ソース管理・公開:GitHub + Cloudflare Workers Builds
main に push すると自動で本番に出る。それ以外のブランチはプレビューURLに出るので、本番に出す前に確かめられる
作りながら変えたこと
最初から全部を決めていたわけではありません。公開してからの10日ほどで、使いながら分かったことをもとに、次のように変えてきました。
- 保存:作品は封印せず、手持ちとレベルだけ封印(10月22日)。手持ちやレベルを保存データの書きかえで増やされるのを防ぐため、読みにくくして署名をつけています。ただし作品には、このしるしをつけません。将来ブロックや機能が増えたときに、古い作品が読めなくなるのを避けるためです。保存データには版番号をつけ、知らない項目は読み飛ばすようにしています。これは手軽な書きかえを防ぐためのもので、ブラウザだけで動くアプリでは、すべてを防ぐことはできません。
- 共有:URLに埋め込む方式から、短縮リンクへ(10月22日〜28日)。最初は作品のデータをそのままURLに入れていました。圧縮の方法を deflate に変えて長さが約3分の1になりましたが、大きな作品はチャットで途中で切れました。そこで、作品のデータだけをサーバー(Workers KV)に預けて、8文字ほどの短いリンクにしました。写真は、関係のない画像を置かれないように預かりません。作品の大きさと、同じ接続元から1分に作れる回数には上限をつけています。
- リンクのカード画像:サーバーで描くのをやめて、共通の画像に(10月28日)。作品ごとのカード画像をサーバーで描く試作も作りましたが、1枚あたりの処理時間が、無料の Worker の上限(10ミリ秒)を超えてしまいました。有料にしてまで作るほどの優先度ではないので、無料のまま、サイト共通の画像にしました。共有が増えたら、有料にして作品ごとの絵を足す候補として残しています。
- 確認画面:ブラウザ標準をやめて、アプリ内のカードへ(10月22日)。iPhone の Safari で標準の確認画面が出ない問題が起きたためです(「iPhoneのSafariで確認画面が出なかった話」)。
- 計測:Cookie を使わない方法だけ。利用者数は Cookie を使わない Cloudflare Web Analytics で、遊んでもらえたかは使い捨ての番号の匿名の記録で見ています。IPアドレスや端末の情報は記録に残さず、個々の記録は約3か月で消えます。内容はプライバシーポリシーに書いています。
- 共有の作品は「見るだけ」で開き、アレンジするかを選べる(10月22日)。共有された作品をそのまま遊びに使えてしまわないように、受け取った側は見るだけで開き、「アレンジする」を押したときに、自分の手持ちで足りるかを確かめてから開く流れにしました。
AI といっしょに作る進め方
katatedake は、エンジニアではないプロダクトマネージャーが、AI といっしょに作っています。役割は、おおまかに次のように分けています。
- 人:何を作るか、何を優先するかを決める。実機(とくに iPhone)で触って確かめる。公開してよいかを判断する。
- AI:案を出し、コードを書き、調べものや文章を書く。変更は小さな単位にまとめて、確認用のプレビューをつけて出す。
プレビューで確かめてから公開する流れが、この進め方を支えています。AI が書いたものを、そのまま本番に出さずに済むからです。部品を標準的なものに絞っているのも、人が読んで判断できる大きさに保つためです。
これからの課題
- 無料の枠の限界:Workers KV は無料の枠で書き込みが1日1,000回までなので、短いリンクがたくさん作られるようになったら、有料にするか、作り方を見直す必要があります。
- 作品ギャラリーの拡充:作品のデータをアプリのコードに載せない方針のため、ギャラリーは短いリンクの作品を並べる形にしています。
- 実機での確認:iPhone の Safari のように、端末によって動きが変わる部分は、これからも実機で確かめていきます。
おわりに
ポケット箱庭は、ブラウザの力と、無料で使える配信の仕組みを組み合わせた、小さな構成でできています。作りながら変えたところも含めて、ここに書いておくことで、同じようにひとりで何かを作りたい人の参考になればうれしいです。分かりにくいところや、気になることがあれば、お問い合わせから教えてください。
ポケット箱庭で遊ぶ無料・登録不要・スマホのブラウザで遊べます