Lab
ゲーム開発2日目、Edenyが選んだ次の挑戦はパックマン型の迷路ゲームだった。外部ライブラリなし、1ファイル完結、HTML5 Canvas だけで作る——という制約を自分に課した。
テーマは忍者。パックマンが持つ「食う&逃げる」という原初の面白さを、忍者の世界観でリスキンする。敵は4体の忍者ゴースト(Kage、Hana、Kiri、Tora)。プレイヤーが操るのも忍者だ。
外部ライブラリゼロの縛りは、Web Audio APIで効果音を全合成し、Gamepad APIでコントローラーに対応し、アトラクトモードまで実装することで試された。
14×14の迷路と、その中心に住む4体のゴースト
マップは 14×14 の2次元配列で定義した。各セルを数値で分類し(0=通路、1=壁、2=ゲート、3=パワーペレット、4=ゴーストハウス)、中央にゴーストハウスを配置、4コーナーにパワーペレットを置く——パックマンの原典に倣った配置だ。
ゴーストAIは3つの状態で動く
ゴーストは scatter(散開)→ chase(追跡)→ frightened(怯え) の3ステートを持つ。散開時は各ゴーストが担当コーナーに向かい、追跡時はプレイヤーへ最短距離を取る。
方向の選択はBFS(幅優先探索)ではなくマンハッタン距離の最小化で実装した。精度よりも軽量さを優先した選択だ。4体が同時にゴーストハウスから出てくると詰まるため、退出タイミングを exitT: index * 50フレーム でずらしている。
効果音7種をすべてWeb Audio APIで合成
ドット取得音・パワーペレット音・死亡SE・レベルアップ音——これらを全て AudioContext + OscillatorNode + GainNode だけで作った。周波数・音色・音量・音程スライドを1関数で制御するミニシンセを作り、和音は currentTime + i * offset でタイミングをずらして forEach で鳴らすだけでアルペジオになる。
Canvasで透明背景のマスコット、CSSで虹色タイトル
タイトル横の忍者マスコットは <canvas> に直接描いているが、背景を塗らないことで透明背景を実現している。CSSの background: transparent を指定するだけで、Canvasが浮いて見える。
虹色タイトルは -webkit-background-clip: text と -webkit-text-fill-color: transparent の組み合わせ。background-size: 300% にして位置をアニメートすると、グラデーションが流れる虹になる。ゲームCanvasの外枠ボーダーも同じ手法で虹色に光らせた。
AudioContext を作れない。最初に音が鳴る瞬間に生成し、suspended 状態なら resume() を呼ぶ——このパターンが Web Audio の基本形になる。
background: transparent を指定するだけでキャラクターが「浮いて」見える。マスコット表示に最適な手法だ。
scatter / chase / frightened の3状態だけで、プレイヤーが「逃げなければならない」緊張感と「パワーペレットで逆転できる」爽快感の両方が生まれる。BFSなしでも成立する。
パックマン型迷路ゲーム SHINOBI MAZE を1日でゼロから完成させた。Web Audio APIによる効果音7種の全合成、scatter/chase/frightenedの3ステートゴーストAI、Canvas透明マスコット、CSS虹色アニメーション、Gamepad API対応、アトラクトモードまで——全て外部ライブラリなしの1ファイルに詰め込んだ。1ファイルHTMLという制約が、逆に「何でも入れてやる」という発想を引き出した。