FIREWALL DRAW — 技術ドキュメント

← 2110 Lab ◀ ゲームに戻る

プロジェクト概要

FIREWALL DRAW はマウスで壁(ファイアウォール)を描いてCPUを守るタワーディフェンスゲーム。Phaser 3 で構築され、ブラウザ上で動作する。

ゲーム内容

マウスドラッグで壁を描き、四方から侵入するウイルス(敵)からCPUを防衛。10ステージ構成、各ステージに複数ウェーブ。

難易度

ノーマル / ハードの2難易度。ハードは壁の長さ制限・敵数増加・CPU HP減少。

永続化

localStorageにセーブ。復活の呪文(Base64)でデータ共有可能。オンラインランキング対応。

技術スタック

技術バージョン用途
Phaser3.80.0ゲームフレームワーク(CDN読み込み)
JavaScriptES6+実装言語
localStorageWeb APIセーブデータ永続化
Fetch APIWeb APIランキングAPI通信
Cloudflare Workers-ホスティング + ランキングAPI

設計上の特徴

オフライン対応設計
file:// プロトコルでも動作するよう、3段階のフォールバック戦略を採用:
1. 画像 → AssetManager がプレースホルダーを動的生成
2. JSON → DefaultData.js のハードコードデータを使用
3. SE → 静かにスキップ(エラーなし)
イベント駆動のシーン間通信
GameScene と UIScene は並列実行され、Phaserのイベントシステムで疎結合に通信。

フォルダ構造

firewall-draw/ ├── index.html ← メインHTML ├── wrangler.json ← Cloudflare Workers設定 │ ├── js/ │ ├── main.js ← エントリーポイント・Phaser設定 │ ├── AssetManager.js ← アセット管理・プレースホルダー │ ├── PlaceholderConfig.js ← プレースホルダー設定 │ │ │ ├── data/ │ │ └── DefaultData.js ← JSONフォールバック用データ │ │ │ ├── utils/ │ │ ├── SaveManager.js ← localStorage・復活の呪文 │ │ ├── SoundManager.js ← SE再生(存在チェック付き) │ │ └── RankingManager.js ← ランキングAPI通信 │ │ │ └── scenes/ ← Phaserシーン(11個) │ ├── BootScene.js ← 起動・ローディング │ ├── PreloadScene.js ← 全アセット読み込み │ ├── TitleScene.js ← タイトル・難易度選択 │ ├── StageSelectScene.js ← ステージ選択(2x5) │ ├── BriefingScene.js ← 敵情報表示 │ ├── GameScene.js ← メインゲームプレイ │ ├── UIScene.js ← HUD(並列実行) │ ├── ResultScene.js ← リザルト画面 │ ├── RankingScene.js ← ランキング表示 │ ├── HelpScene.js ← ヘルプ(3ページ) │ └── DataScene.js ← データ管理・復活の呪文 │ ├── assets/ │ ├── images/ │ │ ├── backgrounds/ ← 背景画像 │ │ ├── enemies/ ← 敵スプライト(10種) │ │ ├── cpu/ ← CPUキャラ(5種×4表情シート + 汎用4種) │ │ └── ui/ ← UIパーツ │ ├── audio/ │ │ ├── bgm/ ← BGM(未実装) │ │ └── sfx/ ← 効果音(17個) │ └── data/ │ ├── enemies.json ← 敵定義 │ ├── walls.json ← 壁定義 │ └── stages.json ← ステージ定義 │ ├── css/ │ └── style.css ← スタイル │ └── docs/ └── index.html ← このドキュメント

ファイル役割一覧

マネージャークラス

ファイル役割
AssetManager.js画像存在チェック → プレースホルダー自動生成。ボタン・HPバーの統一生成
PlaceholderConfig.js各敵・UI・壁のプレースホルダーパラメータ(色・形・サイズ・ラベル)
SaveManager.jslocalStorage保存/読み込み、マイグレーション、復活の呪文(Base64)
SoundManager.jsSE再生(存在チェック・連打制限50ms)、音量・ミュート管理
RankingManager.jsCloudflare Workers APIへのスコア送信・ランキング取得(タイムアウト8秒)

データ

ファイル役割
DefaultData.js難易度設定・キャラクター5種・敵10種・壁5種・ステージ10個・アップグレード4種のフォールバック
enemies.json敵パラメータ定義(HP、速度、報酬、特殊能力)
walls.json壁パラメータ定義(ダメージ、色、解放条件)
stages.jsonステージ定義(ウェーブ構成、敵出現パターン)

スクリプト読み込み順序

index.html での読み込み順(依存関係に基づく):

<!-- 1. Phaser本体(CDN) -->
<script src="https://cdn.jsdelivr.net/npm/phaser@3.80.0/dist/phaser.min.js"></script>

<!-- 2. グローバル定数・デフォルトデータ -->
<script src="js/data/DefaultData.js"></script>

<!-- 3. ユーティリティ(依存なし) -->
<script src="js/utils/SaveManager.js"></script>
<script src="js/utils/RankingManager.js"></script>
<script src="js/utils/SoundManager.js"></script>

<!-- 4. アセット管理 -->
<script src="js/PlaceholderConfig.js"></script>
<script src="js/AssetManager.js"></script>

<!-- 5. シーン(11個) -->
<script src="js/scenes/BootScene.js"></script>
... (計11ファイル)

<!-- 6. エントリーポイント(最後) -->
<script src="js/main.js"></script>

アーキテクチャ

全体構成

┌─────────────────────────────────────────────────────┐
│  index.html                                         │
│  └── main.js  (GAME_CONFIG / GameData / Phaser起動) │
└─────────┬───────────────────────────────────────────┘
          │
    ┌─────┴─────────────────────────────┐
    │          マネージャー層             │
    │  ┌──────────┐  ┌──────────────┐   │
    │  │AssetMgr  │  │ SoundMgr     │   │
    │  │画像+PH   │  │ SE再生       │   │
    │  └──────────┘  └──────────────┘   │
    │  ┌──────────┐  ┌──────────────┐   │
    │  │SaveMgr   │  │ RankingMgr   │   │
    │  │localStorage│ │ API通信      │   │
    │  └──────────┘  └──────────────┘   │
    └─────┬─────────────────────────────┘
          │
    ┌─────┴─────────────────────────────┐
    │            シーン層                 │
    │                                    │
    │  Boot → Preload → Title            │
    │                    ├→ Help          │
    │                    ├→ Data          │
    │                    └→ StageSelect   │
    │                        └→ Briefing  │
    │                            └→ Game  │
    │                      ┌─────┤ ┌────┐ │
    │                      │UI(並列)│    │ │
    │                      └─────┘ └────┘ │
    │                            └→Result │
    │                              └→Rank │
    └─────┬─────────────────────────────┘
          │
    ┌─────┴─────────────────────────────┐
    │           データ層                  │
    │  DefaultData.js  ←→  *.json       │
    │  PlaceholderConfig                 │
    └───────────────┬───────────────────┘
                    │
    ┌───────────────┴───────────────────┐
    │          外部サービス               │
    │  localStorage   Cloudflare Workers │
    │  jsDelivr CDN (Phaser 3.80.0)     │
    └───────────────────────────────────┘

シーン遷移

Boot
Preload
Title
StageSelect
Briefing
GameScene
Result
Ranking
並列実行: GameScene 起動時に scene.launch('UIScene') で UIScene を並列起動。イベント駆動で通信。

Title からの分岐:

Title
HelpScene
Title
DataScene

マネージャーパターン

AssetManager(インスタンス型)

各シーンで new AssetManager(scene) として生成。画像の存在チェックとプレースホルダー自動生成を一元管理。

const assetManager = new AssetManager(this);

// 画像があればSprite、なければGraphicsでプレースホルダー
const sprite = assetManager.getSprite(x, y, 'enemy_bug', config);

// UIボタン生成・HPバー生成
const button = assetManager.createButton(x, y, 'btn_start', config);
const hpBar  = assetManager.createHPBar(x, y, width, height);

SaveManager(静的クラス)

全シーンから SaveManager.method() でアクセス。localStorageを使ったセーブデータ管理。

SoundManager(インスタンス型)

SE再生前に3段階チェック:

play(key) 呼び出し
  ├─ ミュート状態? → return null
  ├─ 連打制限(50ms以内)? → return null
  ├─ cache.audio.exists(key)? → return null
  └─ 再生成功 → Sound オブジェクト返却

RankingManager(静的クラス)

Cloudflare Workers APIとの通信。AbortControllerで8秒タイムアウト。

POST /submit    → スコア送信
GET  /rankings  → トップ20取得

グローバル状態

GAME_CONFIG(定数)

GAME_CONFIG = {
  WIDTH: 800,  HEIGHT: 600,
  UI_TOP_HEIGHT: 50,  UI_BOTTOM_HEIGHT: 50,
  GAME_AREA_TOP: 50,  GAME_AREA_BOTTOM: 550,
  CPU_X: 400,  CPU_Y: 300
}

DIFFICULTY_SETTINGS(定数)

パラメータノーマルハード
壁の最大長さ300px200px
敵数倍率x1.0x1.5
CPU HPステージ定義値定義値 - 2(最低1)

フォールバック戦略

同期ルール: assets/data/*.jsonDefaultData.js は常に同じ内容を維持すること。
対象正常時失敗時
画像textures.exists(key) → Sprite生成AssetManager が Graphics API でプレースホルダー描画
JSONcache.json.get(key) → データ使用DEFAULT_DATA のハードコードデータ使用
SEcache.audio.exists(key) → 再生静かにスキップ(エラーなし)

シーン詳細

#シーン主な役割遷移先
1BootScene最小ローディング表示→ Preload
2PreloadScene全アセット読み込み + エラー記録→ Title
3TitleSceneタイトル画面・難易度選択→ StageSelect / Help / Data
4StageSelectSceneステージ選択(2x5グリッド)→ Briefing
5BriefingScene敵情報表示 + キャラ選択 + コインアンロック→ GameScene
6GameSceneメインゲームロジック→ Result
7UISceneHUD層(GameSceneと並列)-
8ResultSceneクリア/ゲームオーバー結果→ Ranking / Title
9RankingSceneオンラインランキング→ Title
10HelpSceneヘルプ(3ページ)→ Title
11DataScene復活の呪文・データ管理→ Title

GameScene(メインゲームロジック)

初期化

// シーン間データ受け取り + アップグレード + キャラクター補正反映
const charMods = CHARACTER_DATA[charId].modifiers;
this.maxWalls = Math.max(1, 3 + upgrades.wall_count + charMods.maxWalls);
this.wallDuration = Math.max(2000, 5000 + (upgrades.wall_duration * 1000) + charMods.wallDuration);
this.wallDamageMultiplier = 1 + (upgrades.wall_damage * 0.2) + charMods.wallDamageMultiplier;
this.cpuMaxHp = stageData.cpuHp + (upgrades.cpu_hp * 2) + charMods.cpuHp;

壁描画システム

マウスダウン → ドラッグ開始地点記録
マウスムーブ → ライン描画(最大長制限あり)
マウスアップ → 壁オブジェクト生成
  ├─ 物理ボディ設定(静的)
  ├─ タイマー(wallDuration後に消滅)
  ├─ 壁タイプ別の色・エフェクト
  └─ SE再生(draw_wall)

イベント発火

イベントタイミングデータ
cpuDamagedCPU被ダメージ時{ hp, maxHp }
scoreChangedスコア変動時{ score }
waveClearedウェーブクリア時{ wave, totalWaves }

UIScene(HUD並列実行)

GameSceneと並列実行。イベント購読でUI更新:

gameScene.events.on('cpuDamaged', (d) => this.updateHP(d.hp, d.maxHp));
gameScene.events.on('scoreChanged', (d) => this.updateScore(d.score));
gameScene.events.on('waveCleared', (d) => this.updateWave(d.wave, d.totalWaves));
要素位置内容
HPバー上部左CPU残りHP(色変化あり)
スコア上部中央現在スコア
ウェーブ上部右寄りWave 2/5 形式
ミュート右上S/M 切り替えボタン
ポーズ右上ポーズボタン → 音量調整(5段階)+ 再開/リトライ/タイトルへ
壁選択下部解放済み壁タイプ切り替え

ゲームデータ

キャラクター(5種類)

ステージ開始前のブリーフィング画面で選択可能。スタンダード以外はコインで解放。

ID名前タイプ壁数壁持続CPU HP壁ダメコスト
standardスタンダードバランス型±0±0±0±0無料
fortressフォートレス耐久型±0-1秒+3±0200
multicoreマルチコア壁攻勢型+1±0-2±0300
chronoクロノ持久型-1+2.5秒±0±0400
strikerストライカー攻撃型±0±0-2x1.4500

キャラクター画像

各キャラクターは512×512pxの2×2グリッドスプライトシートで管理。各セル256×256pxのうち中央250×250pxを表示領域として使用。

フレーム位置表情HP条件
0左上happy70%以上
1右上worried50〜70%
2左下scared25〜50%
3右下critical0〜25%
フォールバック: キャラスプライトシート未配置の場合 → 汎用cpu_*画像 → Graphicsプレースホルダー(3段階)

敵データ(10種類)

基本敵(Phase 1)

ID名前HP速度報酬特殊能力
bug_small小型バグ10805なし
bug_medium中型バグ256015なし
wormワーム1512010なし(高速)
trojanトロイの木馬504030なし(高HP)
ransomランサムウェア805050なし(最高HP)

特殊敵(Phase 2)

ID名前HP速度報酬特殊能力
bomberボマー208025壁に触れると爆発して壁を破壊
shieldシールド1510035最初の壁ダメージを無効化
spawnerスポナー405040撃破時に小型バグを複数生成
stealthステルス1212030一定間隔で透明化
dasherダッシャー258030突然加速して壁をすり抜ける

壁データ(5種類)

ID名前ダメージ特殊効果解放コスト
basic基本壁 #00aaff 10-最初から無料
fire炎の壁 #ff6600 15DoT 3/秒ステージ3300
ice氷の壁 #00ffff 5減速 80%ステージ5500
thunder雷の壁 #ffff00 20-ステージ7700
poison毒の壁 #9900ff 8DoT 5/秒ステージ101000

ステージデータ(10ステージ)

ST名前CPU HP報酬Wave数
1はじまりの防衛101004
2二方向からの脅威101504
3炎の壁を手に入れろ122005
4高速侵入者102505
5氷結防衛線153005
6爆破工作員123506
7雷撃防壁154006
8ステルスの脅威124507
9総力戦185007
10最終防衛2010008

ウェーブ構造の例(ステージ1)

{
  id: 1, name: "はじまりの防衛",
  cpuHp: 10, reward: 100, targetWalls: 15,
  waves: [
    { enemies: "bug_small:5",  spawnInterval: 1500, directions: ["right","top"] },
    { enemies: "bug_small:8",  spawnInterval: 1200, directions: ["right","top","left"] },
    { enemies: "bug_small:5,bug_medium:2", spawnInterval: 1000, directions: ["right","top","left"] },
    { enemies: "bug_small:8,bug_medium:3", spawnInterval: 800,  directions: ["right","top","left","bottom"] }
  ]
}

アップグレード(4種類)

ID名前最大Lvコスト推移効果
wall_duration壁持続時間5100→200→400→800→1600壁の消滅時間を延長
wall_damage壁ダメージ5150→300→600→1200→2400ダメージ+10%/Lv
wall_count同時壁数2500→1500同時設置数+1
cpu_hpCPU HP5100→200→400→800→1600最大HP+2/Lv

セーブデータ構造

{
  normal: {
    clearedStages: [1, 2, 3],
    highScores: { 1: 1500, 2: 2000, 3: 800 }
  },
  hard: {
    clearedStages: [],
    highScores: {}
  },
  coins: 2500,
  unlockedWalls: ["basic", "fire"],
  unlockedCharacters: ["standard", "fortress"],
  upgrades: {
    wall_duration: 2, wall_damage: 1,
    wall_count: 1, cpu_hp: 2
  },
  selectedCharacter: "fortress"
}
復活の呪文: セーブデータを Base64 エンコードした文字列。テキストとして共有・復元可能。

アセット一覧

背景画像

title_bg
title_bg.png
タイトル画面背景
bg1
bg1.webp
ゲーム画面背景
thumbnail
thumbnail.webp
サムネイル画像

敵スプライト(10種類)

bug_small
bug_small
小型バグ
HP:10 / 速度:80 / 報酬:5
bug_medium
bug_medium
中型バグ
HP:25 / 速度:60 / 報酬:15
worm
worm
ワーム
HP:15 / 速度:120 / 報酬:10
trojan
trojan
トロイの木馬
HP:50 / 速度:40 / 報酬:30
ransom
ransom
ランサムウェア
HP:80 / 速度:50 / 報酬:50
bomber
bomber
ボマー
HP:20 / 壁を爆破
shield
shield
シールド
HP:15 / 初撃無効
spawner
spawner
スポナー
HP:40 / 撃破時分裂
stealth
stealth
ステルス
HP:12 / 透明化
dasher
dasher
ダッシャー
HP:25 / 突進

CPUキャラクター スプライトシート(5種)

各キャラクター別の2×2グリッドスプライトシート(512×512, 表示領域250×250/セル):

standard_sheet
standard_sheet
スタンダード
バランス型
fortress_sheet
fortress_sheet
フォートレス
耐久型
multicore_sheet
multicore_sheet
マルチコア
壁攻勢型
chrono_sheet
chrono_sheet
クロノ
持久型
striker_sheet
striker_sheet
ストライカー
攻撃型

CPU表情 汎用フォールバック(4段階)

キャラスプライトシート未配置時に使用される汎用画像:

cpu_happy
cpu_happy
HP 70%以上
元気
cpu_worried
cpu_worried
HP 50〜70%
不安
cpu_scared
cpu_scared
HP 25〜50%
怯え
cpu_critical
cpu_critical
HP 0〜25%
危機

UIパーツ

title_logo
title_logo
タイトルロゴ
btn_start
btn_start
スタートボタン
btn_retry
btn_retry
リトライボタン
btn_title
btn_title
タイトルへ戻る
btn_pause
btn_pause
ポーズボタン
arrow_warning
arrow_warning
敵接近警告
icon_wall_basic
icon_wall_basic
基本壁アイコン
icon_wall_fire
icon_wall_fire
炎の壁アイコン
icon_wall_ice
icon_wall_ice
氷の壁アイコン
hp_bar_bg
hp_bar_bg
HPバー背景
hp_bar_fill
hp_bar_fill
HPバー充填

効果音(17個)

カテゴリキータイミング
draw_wall壁描画完了
draw_cancel壁キャンセル
hit壁にヒット
kill撃破
bomber_explodeボマー爆発
shield_breakシールド破壊
spawner_spawn / stealth_toggle / dasher_dash特殊能力発動
進行cpu_damageCPU被ダメージ
wave_start / wave_clearウェーブ開始・クリア
stage_clearステージクリア
game_overゲームオーバー
UIbutton_click / button_hoverボタン操作
coin_reward / new_recordコイン獲得・新記録

JSONデータファイル

ファイル内容フォールバック
assets/data/enemies.json敵10種の定義DEFAULT_DATA.enemies
assets/data/walls.json壁5種の定義DEFAULT_DATA.walls
assets/data/stages.json10ステージの定義DEFAULT_DATA.stages

プレースホルダーシステム

画像ファイルが存在しない場合、AssetManager が Phaser の Graphics API でプレースホルダーを動的生成。パラメータは PlaceholderConfig.js で定義。

形状用途
circle敵キャラクター色付き円 + ラベル
rectUI要素・ボタン色付き矩形 + ラベル
triangle警告マーク色付き三角形

敵プレースホルダー色

敵IDサイズ
bug_small24px
bug_medium32px
worm28px
trojan36px
ransom40px
bomber28px
shield30px
spawner34px
stealth26px
dasher28px

依存関係マトリックス

ファイル依存先
main.jsDefaultData, SaveManager
GameScene.jsAssetManager, SoundManager, SaveManager, DefaultData, GameData, DIFFICULTY_SETTINGS, CHARACTER_DATA
UIScene.jsAssetManager, SoundManager, GameScene.events, GAME_CONFIG
BriefingScene.jsSoundManager, SaveManager, CHARACTER_DATA, DIFFICULTY_SETTINGS
ResultScene.jsAssetManager, SoundManager, SaveManager, RankingManager
RankingScene.jsRankingManager, DefaultData
PreloadScene.jsDefaultData(フォールバック時)
TitleScene.jsSaveManager, AssetManager, SoundManager
StageSelectScene.jsSaveManager, AssetManager, SoundManager
AssetManager.jsPlaceholderConfig
SaveManager.jslocalStorage API
RankingManager.jsFetch API
SoundManager.jsPhaser Sound Manager