前回までのあらすじ
前回は、第2弾「おでかけ!わすれもの大作戦」の本編に着手し、エンジンの拡張と素材の発注を経て、絵の位置がズレるたびに描き直す非効率さに気づき、「壊れない構造にする」という設計判断にたどり着いたところまで書きました。窓や家具を座標を持つオブジェクトとして扱うdecorativeフラグの誕生です。
今回は、その新しい設計を実際に大きめのアセットバッチで試したら、次々と壁にぶつかった回です。最終的には本編第1弾(釣りルート)が完成するところまでたどり着きます。
第1章:新アセットバッチ17点、そして最初の透過バグ

新しい設計方針に合わせて、「床・壁だけ」のシンプルな背景2点に加えて、装飾用の家具(窓枠・カーテン・ベッド・机・本棚・おもちゃ箱・ラグ・空)8点、玄関ドア本体1点、細かい小物6点、合計17点を新規に発注し、納品してもらいました。config.jsも「シェルとなる背景の上に、decorativeオブジェクトを重ねていく」という構成に全面的に書き換えています。
実際に組み込んで確認したところ、玄関のドアがゲーム中でうっすらと背景色が透けて見える不具合が見つかりました。調べてみると、「アルファ先掛け(premultiplied alpha)」という現象が原因でした。本来の色に透明度を掛け算した値が、そのままRGBの値として保存されてしまっていて、本来白いはずの部分が黒っぽく沈んで見えていたのです。色チャンネルを補正するスクリプトで対応し、これで直ったはずでした。
第2章:直したはずなのに、まだ透けていた——もう一段深いバグ

ところが、確認してもらったところ「ドアはまだ透過したまんまだよ」という再指摘がありました。アルファチャンネルを画像として可視化してみると、想定していたものとは違う光景が見えてきます。扉の輪郭線(黒い線)の部分だけが不透明で、その内側にあるはずの白い塗り面が、丸ごと透明になっていたのです。色を補正するだけでは直らないはずです——そもそも色自体が存在していなかったのですから。
原因は、白い塗りの部分が背景と誤認され、背景除去の処理でまるごと抜き取られてしまっていたことでした。対応として、輪郭線で囲まれた「本来閉じているはずの透明領域」を検出して塗りつぶす処理を実装しました。考え方としては、画像の外周から到達できる透明領域だけを「本物の背景(透過させたい部分)」と判定し、外周から到達できない孤立した透明領域は「塗り忘れの穴」として塗りつぶす、というものです。修正後、実際にゲーム上でピクセルの値を直接確認し、今度こそ完全に直ったことを確かめました。
同じ手法で、残り13点のアセットも念のため診断しています。window-frame.pngは窓ガラスの部分が「穴」として検出されましたが、そこは背後の空の絵が見えるのが仕様通りだったため、対応は不要と判断しました。一方toybox.png(開いた蓋の内側)には同じ系統の実際の不具合が見つかったものの、見た目への影響が小さいため、今回は対応せず申し送り事項として残しています。
第3章:「隣の部屋」発言を、自分で誤解していた話

見た目の修正が一段落したところで、「オブジェクトが隣の部屋にまとまってる、こっちに移動して」という指示がありました。これを、部屋のシーンの中の左右(柱の左右)という意味だと解釈し、その通りに配置を変更しました。
ところが「本棚・エサ・バケツはドアのある画面の方に移動するってことだよ」という訂正が入ります。実際に指していたのは、同じ部屋シーンの中の左右ではなく、「自分の部屋シーン」と「玄関シーン」という、まったく別のシーン間の移動のことでした。当時は部屋シーンに家具やアイテムが集中していて、玄関シーンには扉しか無いという偏りがあったのを指していたのです。
改めて、本棚・エサ・バケツ、それに付随して帽子も、実際に玄関シーンへ移動しました。両方のシーンをまたいだ「拾う→玄関でクリア」という一連の流れも、あらためて確認しています。
第4章:編集モードで装飾オブジェクトが掴めない理由

「編集モードにしてもクリックできるものしか反応しない、棚も動かしたい」という報告も入りました。調べてみると、decorativeオブジェクトに設定していたpointer-events: none——通常プレイ中にクリックできないようにするためのCSS指定——が、配置編集モードの最中もそのまま効いてしまっていて、ドラッグ操作そのものを受け付けない状態になっていたことが原因でした。
配置編集モードのときだけpointer-eventsを復活させるCSSを追加して対応しました。実際にドラッグイベントを発火させて、オブジェクトのx・y座標が正しく変わることを確認しています。新しく追加した機能(decorativeフラグ)が、既存の別の機能(配置編集モード)と静かに衝突していた一例でした。
第5章:最終レイアウトを反映して、仕上げ

配置編集モードで作った最終的なレイアウトのJSON(部屋シーン・玄関シーン、それぞれ1本ずつ)を受け取り、config.jsにそのまま反映しました。作業用に立てていたmeta.debug: trueも、忘れずにfalseへ戻しています。
最後に、5点すべてのアイテムの取得から、玄関シーンでの必須3点判定、クリア画面まで、両方のシーンをまたいだ一連の動作を通しで確認し、問題ないことを確かめました。これで、本編第1弾(釣りルート)がようやく完成です。
🎮 今回のバージョン
decorativeフラグによる新しい構造、二段構えの透過バグの修正、玄関シーンへの家具の再配置まで、すべて反映した最終版です。ぜひ最後まで遊んでみてください。
💬 読者へのヒアリング
toybox.pngの蓋の内側にまだ小さな透過の粗が残っています。気づいた方がいたら、それも含めて感想を聞かせてもらえると嬉しいです。
まとめ&次回予告
今回は3つの教訓が残りました。1つ目は、見た目上「直った」ように見えても、ピクセルの値を直接調べるまで真の原因を誤認し続けてしまうことがあるということ。色の補正だけで満足していたら、輪郭線だけ残って中身が透明という、もう一段深い不具合を見逃したままでした。2つ目は、「こっち」「隣の部屋」のような指示語は、話している側が見ている画面や文脈に依存するということ。自分の推測だけで配置を決め打ちせず、曖昧さが残る指示は確認するか、実装後すぐに検証できる状態にしておくことで、手戻りのコストを小さくできます。3つ目は、pointer-events: noneのような小さな指定が、後から追加した別の機能と静かに衝突することがあるということ。新機能を追加したら、既存の似た機能と組み合わせたテストもセットで行うべきでした。
本編第1弾(釣りルート)はこれで完成しましたが、escape-game-template配下に残っている旧おでかけ素材の整理や、プール・虫取りルートの追加はまだ手つかずです。次はどちらに進むか、考えていきます。
次回:第8話「釣りルートの次、どうする?」


コメント