Chilla Games 開発記 — AIと一緒にブラウザゲームを3本作った話
チンチラのリンちゃんが主人公のブラウザゲーム3本をAI(Claude)と3日で開発。当たり判定の設計変更、仕様の誤解、確率分布によるゲームバランス設計など、AI協働開発のリアルな体験談。
はじめに
ちらりんブログに「ゲームコーナー」を作りました。 うちのチンチラ、リンちゃんが主人公のブラウザゲームを3本。
コンセプトは 「2000年代の携帯ゲームにインスピレーションを得た」 ブラウザゲーム。あのシンプルで中毒性のあるゲーム体験を、リンちゃんの世界観で作りました。
- チラ走 — 横スクロールランナー
- Chilla Jump — 縦スクロールクライミング
- Chilla Up — タワークライム(パワーゲージ式ジャンプ)
技術スタックは TypeScript + Canvas 2D API。ゲームエンジンもフレームワークも使わず、外部依存ゼロ。esbuild でバンドルして Hugo のサイトに組み込んでいます。
で、これを 3日で3本リリース しました。AI(Claude Code)との協働開発です。
この記事は、その開発過程で起きた「リアルなハマりポイント」と「AIとの協働で学んだこと」をまとめたものです。AIが万能に見えるこの時代に、AIにできること・できないことが具体例で伝わればいいなと思います。
チラ走 — 当たり判定の沼にハマった話

最初に手をつけたのが「チラ走」。横スクロールランナーです。 リンちゃんが走り続けて、穴を飛び越え、障害物を避ける。シンプルなルール。
……のはずだった。
「穴をくり抜く」という設計判断
AIに「地面に穴が空いていて、落ちたらゲームオーバー」と伝えたところ、実装はこうなりました。
地面を一枚のベタ塗りとして描画し、そこから「穴」の範囲を除外する
つまり 「穴をくり抜く」 方式。地面が基本で、穴は「地面がない領域」として表現されています。
一見合理的に見えます。でも、当たり判定のコードを書こうとした瞬間に地獄が始まりました。
修正サイクル v1〜v7、そしてそれ以降
当たり判定のバグが 何度修正しても直らない。
- v1: 壁をすり抜ける
- v2: 左壁でなぜかゲームオーバーになる
- v3: 穴の上で着地判定が発生する(空中に立てる)
- v4: 穴の左端だけすり抜ける
- v5〜v7: 上記の組み合わせが形を変えて再発
AIは毎回「修正しました」と言って、ピンポイントで条件分岐を追加してくる。でも1つ直すと別の場所が壊れる。モグラ叩きです。
根本原因 — データ構造の設計ミス
7回目あたりで、私はコードを読むのをやめて データ構造を見直しました。
問題はコードのバグではなく、そもそもの設計にありました。
「穴をくり抜く」方式では、「穴」という概念がデータに存在しない。
地面は「画面幅いっぱいのベタ塗り」として存在していて、穴は「描画しない領域」。でも当たり判定は「何かがある場所」に対して行うもの。存在しないものとの衝突判定を正しくやるのは、コードが複雑になるのが当然です。
発想の転換 — 「穴ではなく地面に注目する」
私が出した結論は 「穴ではなく、地面ブロックを配置する」 でした。
【Before: 穴くり抜き方式】
地面: ████████████████████████████████
穴: ↑ここを除外 ↑
判定: 「穴の範囲外かつ地面の高さ」→ 条件が複雑
【After: ブロック配置方式】
ブロック: ████ ████ ████████ ████
判定: 「ブロックの上にいるか」→ 単純な矩形判定ブロック方式に変えた瞬間、当たり判定は 数行で実装できました。各ブロックは {x, y, width, height} を持っていて、プレイヤーの矩形と重なっているかを調べるだけ。
// ブロック方式の当たり判定(概念)
const onGround = blocks.some(block =>
player.x + player.width > block.x &&
player.x < block.x + block.width &&
player.y + player.height >= block.y &&
player.y + player.height <= block.y + TOLERANCE
);v1〜v7 の修正サイクルで費やした時間より、設計変更後の実装のほうがはるかに短かった。
教訓: 同じ修正が3回失敗したら、コードではなく設計を疑え
AIは 「与えられたアプローチの中で最善の修正」 を出すのが得意です。でも 「アプローチ自体を変える」 という判断は苦手。穴くり抜き方式の中で条件分岐を追加し続けることはできても、「この方式自体が間違っている」とは言ってくれません。
これがこの記事で一番伝えたいことかもしれません。
Chilla Jump — 物理計算とゲームバランス

2本目は「Chilla Jump」。縦スクロールクライミングです。 自動ジャンプ + 左右移動のシンプルな操作で、ひたすら上を目指す。
このゲームでハマったのは 物理計算とスプライトの問題 でした。
物理的に到達不可能な足場
実装初期、テストプレイで「どう見ても届かない足場」が出てきました。
原因を調べたら、数式が合っていなかった。
JUMP_VELOCITY = -720 px/s(初速)
GRAVITY = 1800 px/s²
最大到達高度 = v² / (2 * g)
= 720² / (2 * 1800)
= 518400 / 3600
= 144 px一方、足場の最大ギャップ(maxGap)は 180px に設定されていました。
物理的に144pxしか飛べないのに、180px先に足場を置いたら 絶対に届かない。ゲームとして成立しません。
これは単純な計算ミスですが、AIは maxGap と JUMP_VELOCITY を別々のモジュールで設定していたため、両者の整合性チェックが抜けていました。人間がプレイして「届かない」と気づかなければ、そのままリリースしていたかもしれません。
スプライトのアスペクト比問題
もう1つ厄介だったのが スプライト画像のサイズ。
リンちゃんのスプライト run-up1.png のサイズは 85 x 247px。極端な縦長です。
これをそのまま使うと、キャラクターの表示高さが足場ギャップより大きくなり、見た目上は足場に触れているのに当たり判定が発生しない、あるいはその逆が起きます。
解決策として、スプライトの種別(走り・ジャンプ上昇・ジャンプ下降)ごとに 表示サイズを個別に計算 する方式にしました。元画像のアスペクト比を維持しつつ、ゲーム内での当たり判定サイズは統一する。見た目とロジックの分離です。
4タイプの足場と難易度テーブル
Chilla Jump には4タイプの足場があります。
| 足場タイプ | 挙動 | 登場スコア |
|---|---|---|
| 通常 | 乗ると跳ねる | 最初から |
| 壊れる | 一度乗ると消える | 500点〜 |
| 動く | 左右に移動 | 1000点〜 |
| バネ | 通常の2倍の高さまで飛べる | 1500点〜 |
スコアに応じて出現確率を変える 難易度テーブル を設計しました。この部分はAIに「スコア帯ごとの出現確率を配列で定義して」と明確に指示すれば、きちんと実装してくれます。
AIへの指示が「明確な仕様」になっているかどうかで、出力品質が大きく変わる好例です。
Chilla Up — AIの仕様誤解と確率分布設計

3本目は「Chilla Up」。パワーゲージ式ジャンプのタワークライムです。
このゲームの開発では 仕様の伝え方 について大きな学びがありました。
仕様誤解事件 — 元ゲームの操作体系を取り違えた
AIに「自動ジャンプ + 左右移動のタワークライムを作って」と指示したところ、出てきたのは 意図と全く違う操作体系のゲーム でした。
ん? と思ってよく見ると、私の指示が悪かった。
意図していた操作体系:
- 左右移動 → 自動(キャラが勝手に往復する)
- ジャンプ → 手動(パワーゲージでタイミングと強さを決める)
私が伝えたこと:
- 「自動ジャンプ + 左右移動」
AIは素直に「自動でジャンプして、左右は手動で操作する」と解釈しました。しかし意図していたのは 自動と手動が逆 の操作体系だったのです。
ここで学んだのは、ゲームの仕様を伝えるときは 「何を操作するか」 と 「何が自動か」 を明確に分けて書くこと。
【曖昧な指示】
「自動ジャンプ + 左右移動」
【明確な指示】
- 操作: ジャンプ(パワーゲージ式、長押しで強く飛ぶ)
- 自動: 左右移動(壁に当たると反転して往復する)たった数行の違いですが、出てくる実装は全く別物になります。
足場配置の縦密集問題
Chilla Up では足場をランダムに配置するのですが、初期実装では 足場が縦に積み上がる 問題がありました。
横位置がランダムなので、たまたま同じX座標付近に連続して配置されると、ジャンプしなくても上に進めてしまう。ゲームとして成立しません。
最初の対策は「直前の足場と横位置が重ならないようにする」というもの。AIが提案してくれた方法です。
でもこれだと 3段おきに同じ位置に戻る パターンが発生しました。
足場1: 左
足場2: 右(足場1と重ならない → OK)
足場3: 左(足場2と重ならない → OK、でも足場1と同じ位置)
足場4: 右(足場3と重ならない → OK、でも足場2と同じ位置)
→ 結果: 左右交互に並ぶだけ。ジグザグに登れてしまう多段階確率分布制御
私が考えた解決策は 多段階の確率分布制御 でした。
n+1段目との重なり率: 最大20%
n+2段目との重なり率: 最大35%
n+3段目との重なり率: 最大50%
n+4段目との重なり率: 最大65%直近の足場ほど重なりを厳しく制限し、離れた足場とは緩やかに許容する。これで 単純なジグザグパターンが崩れ、プレイヤーはちゃんとジャンプの方向を考える必要が出てきます。
AIにこの方式を伝えたら実装自体はスムーズでした。でも この設計自体を思いつくのはAIではなかった。
「足場が重ならないようにして」という指示には応えられる。でも「何段先まで、どの程度の重なりを許容するか」という ゲームの面白さに直結する設計 は、実際にプレイして「これは面白くない」と感じた人間のフィードバックから生まれたものです。
共通のハマりポイント
3本のゲームに共通して遭遇した、地味だけど時間を食う問題たちです。
Canvas と DOM の相互作用
Hugo のテンプレートで生成される HTML と、ゲーム側の JavaScript が想定するコンテナIDが一致しない。game-container と gameContainer のような微妙な不一致で、Canvas が表示されない。
さらに、Canvas の上に DOM のボタン(リスタートボタンなど)を重ねると、タッチイベントが Canvas に伝播してしまい、ボタンを押したつもりがゲーム内の操作として処理される問題も起きました。event.stopPropagation() で解決しますが、Canvas とDOM を混在させる設計では常に意識が必要です。
esbuild の outfile 名と HTML の参照先不一致
esbuild でバンドルした JS ファイルの出力名と、HTML 側の <script src="..."> が一致していない。ゲームごとに chira-run.js、chilla-jump.js、chilla-up.js と命名しているので、どこかでタイポすると無言で動かなくなります。
ブラウザキャッシュ問題
ゲームの修正をデプロイしても、ブラウザのキャッシュで古いJSが使われ続ける。「バグが直ってない」と思って何度もコードを確認した結果、単にキャッシュだった――という、古典的だけど毎回やる失敗。
AIとゲーム開発 — 得意なこと・苦手なこと
3本のゲームを開発して見えてきた、AIとの協働における得手不得手をまとめます。
AIが得意だったこと
- Canvas 2D API の描画コード —
fillRect、drawImage、clearRectの組み合わせをスラスラ書く - requestAnimationFrame のゲームループ — deltaTime の計算、FPS制御など、定型パターンの実装が速い
- キーボード/タッチの入力ハンドリング — イベントリスナーの登録、モバイル対応のタッチ判定
- esbuild の設定 — TypeScript のバンドル設定、watch モードの構成
- 足場生成のアルゴリズム — 仕様が明確であれば、複雑なロジックもきちんと実装できる
要するに 「何を作るか」が明確に定義されていれば、実装は速くて正確。
AIが苦手だったこと
- データ構造の根本的な設計変更 — 穴くり抜き方式の中での修正は得意だが、「この方式自体をやめよう」とは言えない
- ゲームバランスの調整 — 数値の計算はできても、「これが面白いか」の判断は人間にしかできない
- 仕様の曖昧さの解消 — 「自動ジャンプ」に複数の解釈がある場合、どちらが正しいか聞き返すことはあっても、文脈から推測する精度は高くない
- 多段階の確率分布設計 — 「重ならないように」は対応できるが、「何段先まで、どの確率で」という段階的な設計は人間の発想から生まれた
協働のコツ
この3本の開発を通じて、AIとのゲーム開発で意識すべきことが見えてきました。
- 3回同じ修正が失敗したら設計を見直す — AIはアプローチ内の最適化は得意だが、アプローチの転換は人間の判断
- 仕様は「操作」と「自動」を明確に区別する — 曖昧な指示は曖昧な実装になる
- ゲームバランスは必ず自分でプレイして確認する — 数値の整合性は計算で検証できるが、「面白さ」はプレイしないとわからない
- AIの実装力 x 人間の設計判断 = 最速の開発 — どちらか片方では成立しない
まとめ
3日で3本のブラウザゲームを公開できたのは、間違いなくAIとの協働があったからです。 Canvas の描画コード、ゲームループ、入力処理、足場生成アルゴリズム――これらを1人で全部書いていたら、3日では絶対に終わりません。
でも、AIだけでは「面白いゲーム」にはならない。
データ構造の選択を誤れば、いくらコードを修正しても当たり判定は正しく動かない。物理パラメータとレベルデザインの整合性は、人間がプレイして初めて検証できる。足場配置の確率分布は、「遊んでみてつまらない」というフィードバックから設計が始まる。
AIは最高の実装パートナーだけど、設計者は人間。
この役割分担がうまくハマったとき、個人開発のスピードは劇的に上がります。
ゲームは下のリンクから遊べます。リンちゃんと一緒に走って、跳んで、登ってみてください。
Chilla Games: https://chillablog.chillarin39.com/games/
コメント