ブラウザで3Dゲームを1本作り切るまで — 構成の選び方と、つまずいた3つの不具合

2026年9月26日・約3,200字

「A旋状のバリア」は、HTMLファイル1枚で動くブラウザゲームです。ゲームエンジンは使わず、3D描画にthree.js、音はすべてブラウザの音声機能で合成しています。この記事では、個人で1本のブラウザゲームを作り切るまでに何を選び、どこでつまずいたかを書きます。

なぜブラウザゲームにしたか

選択肢としては、UnityでPC向けに出す、スマホアプリにする、ブラウザで出す、の3つがありました。ブラウザを選んだ理由は単純で、URLを送るだけで遊んでもらえるからです。インストールも審査もなく、思いついた改善をその日のうちに反映できます。個人開発で一番失われやすいのは勢いなので、反映までの距離が短いことを最優先にしました。

構成

役割使ったもの
3D描画three.js(WebGL)
音Web Audio API(すべてコードで合成)
保存localStorage(ベストスコアと設定)
配信Cloudflare Workers の静的アセット
ランキングCloudflare D1(SQLiteベースのデータベース)
オンライン対戦WebRTC(PeerJS)

ビルド工程はありません。HTMLファイルを書き換えてアップロードすれば、それが本番です。開発中はローカルでファイルを開くだけで動きます。

円形の盤面をどう作るか

ブロック崩しを円形にする場合、ブロックは「扇形の板」になります。three.jsには扇形のジオメトリがないので、自分で頂点を並べて作ります。半径の内側と外側、開始角度と終了角度を受け取り、厚みを持たせた立体にする関数を1つ用意すれば、あとは角度を変えて並べるだけです。

当たり判定は3Dの物理計算ではなく、極座標で判定しています。ボールの位置から中心までの距離と角度を求め、その距離がブロックの輪の内側と外側の間にあり、角度がブロックの占める範囲に入っていれば衝突、という単純な判定です。

const r = Math.hypot(ball.x, ball.y);
const th = Math.atan2(ball.y, ball.x);
// 輪の内外に入っているか → 角度が一致するか
if (r > ring.r1 && r < ring.r2) {
  for (const brick of ring.bricks) {
    if (Math.abs(wrap(th - ring.rot - brick.tc)) <= brick.hw) hit(brick);
  }
}

この方式の利点は、ブロックの輪が回転していても計算が変わらないことです。回転角を引くだけで判定できます。

一番つまずいたところ

ボールが止まる

公開後に報告をもらった不具合です。キャッチでボールをバリアに貼り付けた状態でマルチボールを取ると、増えたボールが「止まっているボールのコピー」として生まれ、速度ゼロのまま盤面に居座りました。動かないので落ちることもなく、残機も減らず、進行が止まります。

直し方は2つです。コピー元が止まっている場合は中心方向へ新しい速度を与えること、そして保険として、速度がほぼゼロのボールや外周を延々と周回しているボールを検出して中心側へ向け直すことです。「ありえない状態」を検出して勝手に直す仕組みを入れておくと、想定外の経路で同じ症状が出ても進行不能になりません。

iOSの長押しで拡大鏡が出る

スマホで操作していると、長押ししたときに文字選択の拡大鏡が出てしまいました。ページ全体に選択無効の指定をしていたのですが、iOSではボタンやキャンバスがその指定を継承しません。すべての要素に対して個別に指定し、あわせて触れた瞬間の既定動作を止める必要がありました。ただし止めすぎるとボタンが反応しなくなるので、対象を絞る判断が要ります。

メニューの文字がホイールに重なる

画面の高さから逆算して文字サイズを決めていたのですが、項目が増えると計算より実際の高さが上回り、操作用のホイールに重なりました。最終的に、表示した直後に実際の高さを測って、収まらなければ収まるまで縮める方式に変えました。計算で予測するより、描画後に実測するほうが確実です。

音をすべてコードで作る

音源ファイルは1つも使っていません。効果音もBGMも、Web Audio APIで波形を組み立てています。ファイルサイズが増えず、著作権の心配もなく、曲の途中で転調させるといった操作も自由にできます。

BGMは10曲入っていますが、データとしては音符の配列と、それを音に変える関数の組み合わせです。たとえばパイプオルガンの音は、基音に加えてオクターブ上と12度上の倍音を重ねることで作っています。実際の楽器の構造をまねると、それらしい音になります。

作り終えてから気づいたこと

公開して人に触ってもらうと、自分では気づかない問題が次々に出ます。操作方法が伝わらない、最初の画面が静かすぎて何のゲームか分からない、序盤が難しくてやめてしまう。どれもコードの問題ではなく、最初の30秒の問題でした。

結局、タイトル画面で自動的にゲームが動くデモを流し、操作方法を図で示し、序盤を易しくするという改修を後から入れました。最初からそうしておけばよかった、というのが一番の学びです。

これから作る人へ

「A旋状のバリア」を遊ぶブラウザですぐ遊べます・登録不要