AIとゼロから作る脱出ゲーム開発日記 第6話:絵を直すたびに描き直すのをやめて、壊れない構造にした話

Claude Codeのターミナル画面と、グリッドが重なった玄関の背景、座標を持つ窓のアイコンが浮かぶ様子を描いたデスクのイメージ画像。 開発日記

前回までのあらすじ

前回は、「同じエンジンから全く違うゲームが作れます」というAIの断言を鵜呑みにせず、実際にコードを監査し、最小限のミニテストで検証したところまで書きました。ロジック層は思っていた以上にデータ駆動化されていた一方、画面の文言には取り残しが見つかり、それを直すところまでが前回の内容です。

今回は、その検証結果を踏まえて、第2弾「おでかけ!わすれもの大作戦」の本編に実際に着手した回です。エンジンの拡張、素材の発注、そして納品後に待っていた地味な直しの繰り返しの果てに、設計そのものを見直すことになりました。

第1章:監査で見つけた穴を、実際にエンジンへ実装

前回の監査で「設計だけ決めて、今は着手しない」としていたエンジン拡張を、ここで実際に実装しました。3つの機能です。

1つ目はobj.requiresItemsという配列指定です。出口(exit)タイプのオブジェクトで、複数のアイテムを選択操作なしで一括判定できる代替モードです。既存のobj.requiresItem(単一アイテムを選択してからクリックする方式)はそのまま残し、オブジェクトごとにどちらか一方を選べる設計にしました。

2つ目はobj.invisible: trueです。画像やプレースホルダーの描画を一切スキップする、当たり判定専用のオブジェクトです。背景画像にすでに扉が描き込まれているようなケースで、その上にさらに別の絵を重ねたくない場合に使います。

3つ目はGAME_CONFIG.ui.inventoryIconです。所持品欄に表示する装飾アイコン(リュックなど)を指定できるオプションで、指定が無ければ何も表示されない完全なオプトイン仕様にしています。

実装後、「密室からの脱出」側のconfig.jsは一切変更せずに動作確認し、見た目も挙動も1文字・1pxも変わっていないことを確認しました。この段階で、本編用にouting-mini-testとは別の独立フォルダodekake-gameを新設し、ここを実際に発展させていく方針にしています。outing-mini-testは、前回のブログ記事に埋め込んだ状態のまま、凍結スナップショットとして残してあります。

第2章:本編素材の発注、そして危なかったライセンス

エンジン側の準備が整ったところで、OpenMontageに釣りルート一式(背景3点・オブジェクト6点・音源2点、計11点)を発注しました。「特定の作品を模倣しない、丸みのある子供向けアニメ調」という画風の指定は、この時点からはっきり明記しています。

納品の過程で、候補に挙がっていたBGMが最初「非商用ライセンス」の楽曲だったことが分かりました。これはOpenMontage側が自ら気づいて、商用利用可能なCC-BY/CC0の別候補に差し替えてくれています。念のため、Freesoundの実際のページを直接開いてライセンス表記を目視でも確認し、問題なしと判断しました。テンプレートとして販売することを考えると、ここで気づけたのは大きかったです。

これで本編第1弾(釣りルート)のプレイアブル版が、ひとまず形になりました。

第3章:納品後の絵の直しラリー

実際にゲーム画面で確認してみると、2つの問題が見つかりました。1つは玄関の背景で、扉の両脇が外の通りに向かって開けっぴろげになっていて、「玄関」というより外の風景に見えてしまっていたこと。もう1つは釣り竿で、形が崩れてしまっていて「リングの束」にしか見えない状態でした。

修正を依頼し、扉の両脇を壁にして、上部に外の街並みが見える窓を追加してもらい、釣り竿はリール・糸・釣り針がちゃんと分かる形に描き直してもらいました。

ところが、直った窓の位置を背景画像にピクセルグリッドを重ねて実測してみると、窓の右端と扉枠の左端の隙間がわずか10〜30pxしかなく、「壁に食い込んで見える」という当初の見立てがそのまま的中していることが分かりました。

第4章:「絵を直す」から「壊れない構造にする」への方針転換

ここで、窓の位置がズレるたびに背景画像そのものを作り直す、という直し方をずっと繰り返していることに気づきました。窓や家具は、あくまで背景に描き込まれた1枚絵の一部で、それ自体が座標を持つオブジェクトではありません。そのため、位置調整のたびに絵をまるごと再生成する必要があったのです。

そこで方針を転換しました。「床と壁以外は、全部オブジェクト化してしまえば、位置調整はconfig.jsの座標を変更するだけで済む」という考え方です。これに合わせて、エンジンにobj.decorative: trueというフラグを新しく追加しました。前章のinvisible(当たり判定のみで描画なし)とちょうど対になる、「描画のみで当たり判定なし」のオプトイン機能です。クリックやホバーのリスナーを一切登録しないので、窓や家具をどれだけ大量に置いても、ゲームのロジックには一切影響しません。

実機で、装飾オブジェクトをクリックしても何も起きないこと、既存のアイテム取得の操作は今まで通り動作することを確認しました。これで、次に窓や家具の位置がズレても、絵を描き直してもらう必要はなく、数値をいじるだけで直せる体制が整いました。

🎮 今回のバージョン

※このバージョンは、実は第7話時点のものです。第6話が扱っている時点(decorativeフラグ実装直後)のアセットは、後日別作業で同名ファイルごと上書きされてしまい、当時の状態を正確には復元できないため、第7話の完成版をここに先行配置しています。

今回のバージョンは、まだ見た目の作り込みが工事中の状態です。釣りルートは最初から最後まで遊べますが、背景はまだ「1枚絵+修正の繰り返し」だった頃の状態のままです。次回、このdecorativeフラグを本格的に使った作り直しに入ります。

💬 読者へのヒアリング

玄関の窓の位置など、細かい違和感に気づいた方がいたら教えてください。次回、大幅に作り直す予定なので、今のうちに気になった点を教えてもらえると参考になります。

まとめ&次回予告

監査で見つかった穴をエンジンに実装し、本編素材を発注し、届いた絵の細かい位置ズレに何度も付き合った結果、「絵を直す」のではなく「壊れない構造にする」という、今回のエンジン改修の中でも大きな設計判断にたどり着きました。

次回は、この新しい設計を実際に大きめの新アセットバッチ(17点)で試します。ただ、そう簡単には終わりませんでした。二段構えの透過バグ、指示の言葉の行き違い、編集モードの思わぬバグと、次々に壁が現れることになります。


次回:第7話「新しい構造で作り直したら、今度は別の穴が次々見つかった話」

コメント

タイトルとURLをコピーしました