「シンプルな戦略ゲームを、スマホで動かしたい」


そんな思いつきから始まったこのプロジェクト。
実は、AI(Claude)と対話しながら短時間で完成させることができました。
1. 最初はシンプルな戦略ゲーム
最初のバージョンは、3種類のユニット(アサルト、スナイパー、サポート)だけのシンプルなもの。
マップは12×10マス、各ユニットが移動して攻撃して、敵を全滅させたら勝ち。

これだけでも動くゲームにはなります。
1.1. レイアウトを調整
スマホ画面に収まるように、Canvas座標の計算を修正したり、CSSでレスポンシブ対応したり。地味だけど大事な作業です。タッチイベントとクリックイベントの両方に対応させて、画面サイズに応じてCanvasがスケールするように調整しました。
また、各ユニットを色分けするのではなく固有のSVGアイコンを割り当てました。
これだけでかなり見やすくなります。
色は、陣営を分けるのに使います。
ステータス表示も3×2のグリッドレイアウトに変更。
HP、移動力、射程、攻撃力、防御力、速度が一目で分かるようになりました。
マップサイズも10×12タイル、各タイル32pxに変更。
これでスマホでもちゃんと遊べるようになりました。
1.2. カウントタイムシステムを導入
普通のターン制だとユニットを選択して行動という操作の流れが単調になってしまうので、カウントタイム(CT)システムを導入しました。
速度の速いユニットは何度も行動できるし、遅いタンクは重厚だけど手数が少ない。画面上部には次の8ユニット分の行動順が表示されて、戦略を練りやすくなりました。
1.3. 操作系をスムーズに
操作方法も何度か改善しました。
最初は「待機」ボタンがあったんですが、もっと直感的にしたくて、行動中のユニットをタップしたら待機に。
さらに、移動フェーズで自分のユニットをタップすると、移動せずに攻撃・回復フェーズに進めるようにしました。
これで「その場から狙撃」みたいな戦術が使えます。
また、他のユニットをタップしたら情報表示にしました。
ただし、攻撃・回復フェーズ中に他のユニットをタップしても情報表示はしません。
1.4. ダメージ表示とテンポ
ゲームのテンポも重要です。
攻撃と反撃が一瞬で終わると、何が起きたか分かりませんでした。
攻撃、反撃、回復を同時に処理せず、0.3秒ウェイトを入れて、ダメージはユニットの上に数字で表示するようにしました。
赤い数字でダメージ、緑の数字で回復。
浮き上がるアニメーション付きで1秒間表示されます。
範囲攻撃だけは例外で、複数のダメージを同時に表示します。
そうしないとテンポが悪くなるので。
攻撃の流れはこうです。
- メイン攻撃でダメージ表示 → 0.3秒待機
- センチネルのAOEなら範囲ダメージを同時表示 → 0.3秒待機
- 反撃があればダメージ表示 → 0.3秒待機
この待機時間のおかげで、戦闘の様子が追いやすくなりました。
1.5. ユニットの多様化
3種類のユニットだと、やっぱり戦略性が限られます。
最終的に12種類のユニットを実装しました。
- アタッカー系のアサルトとデュエリスト。
- 遠距離系のスナイパーとマークスマン。
- サポート系のメディックとコントローラー。
- タンク系のタンクとブルーザー。
- 機動系のスカウトとフランカー。
- スペシャリスト系のエンジニアとセンチネル。
各ユニットには固有の特殊能力があります。
例えばセンチネルは範囲攻撃ができて、メイン対象だけじゃなく隣接する敵にも50%のダメージを与えます。
タンクやコントローラーは隣接する味方に防御ボーナスを与える「シールド」能力を持っています。
2. ゲームの仕様
ゲームの主な特徴をまとめておきます。
2.1. コアシステム
CTターン制で、各ユニットが速度に応じて順番に行動します。
マップは10×12マスで、4種類の地形(平地、森、山、川)があります。
プレイヤーは6体、敵は8体のユニット。
初期配置は味方が左上、敵が右下です。
2.2. 操作方法
移動フェーズでは、青い範囲をタップして移動するか、自分のユニットをタップして移動なしで攻撃フェーズへ。
他のユニットをタップすると情報が見られます。
攻撃・回復フェーズでは、赤い範囲の敵を攻撃するか、緑の範囲の味方を回復(メディックのみ)します。
自分のユニットをタップすると待機です。
2.3. 戦術要素
地形による移動コストと射線遮蔽。
移動なしで攻撃すると狙撃ボーナス。
反撃は1ターンに1回まで。
通常ユニットは最も近い敵しか狙えないけど、スナイパーとマークスマンは自由に選択可能。
シールド能力とコントローラーの自動回復。
この辺の要素が組み合わさって、かなり戦略的なゲームになりました。
3. 戦闘システム
戦闘システムに、いくつかルールを追加しました。
3.1. 攻撃対象の制限
通常ユニットは、射程内の最も近い敵しか選べないようにして、ただしスナイパーとマークスマンは今まで通り選べるようにしました。
これで前衛・後衛の概念がはっきりしました。前衛がいる限り、後衛を直接狙うのは難しい。
でもスナイパーとマークスマンだけは狙撃が可能。
この制限のおかげで、タンクの価値が上がりました。
3.2. 反撃の制限
最初は何度でも反撃できたんですが、これだと強すぎるので、反撃は1ターンに1回までにしました。
こうすることで、集中攻撃の価値が上がりました。
1体のユニットに複数で攻撃すれば、2回目以降は反撃を受けずに一方的に攻撃できます。
また、スナイパーは反撃できない代わりに、超射程と高火力を持っています。
3.3. 狙撃ボーナス
「移動せずに攻撃した場合、ダメージ×(1+距離)/2のボーナスを付けたい」
例えば、攻撃力50のスナイパーが距離3から動かずに狙撃すると、50×(1+3)/2=100のボーナスダメージ。
合計150ダメージです。
これはかなり強力。
その場から攻撃するか、移動して位置を変えるか。
この選択が戦略の幅を広げます。
3.4. 地形システムと射線遮蔽
「地形を4種類にして、移動コストと「射線遮蔽」の概念を追加しました。
平地は移動コスト1。
森も移動コスト1だけど、射線を遮蔽します。
山は移動コスト2で、これも遮蔽効果あり。
川は移動コスト3で、戦線を分断する役割を果たします。
「射線遮蔽」は、射程2以上の攻撃では、弾道の経路上にある森や山1つにつき攻撃力が5減ります。
遠距離攻撃を回避する時には、陣地を確保することが重要になったわけです。
4. 特殊能力の実装
各ユニットの特殊能力も、実際に動作するように実装しました。
4.1. シールド能力
タンクとコントローラーは、隣接する味方に防御ボーナスを与えます。
タンクは+5、コントローラーは+5。
複数のシールドユニットが隣にいれば、ボーナスは累積します。
ユニット情報を見ると、防御力のところに「15 (+5)」みたいに表示されるので、効果が分かりやすいです。
4.2. コントローラーの自動回復
コントローラーは、行動終了時に隣接する負傷した味方を10回復します。
これは自動発動。
緑の数字がポップアップして、じわじわ回復していく様子が見えます。
メディックの回復は30で、意図的に使うもの。
コントローラーの回復は10で、自動的に発動するもの。
この使い分けが面白いです。
4.3. センチネルの範囲攻撃
センチネルが攻撃すると、メイン対象に加えて隣接する敵全員に50%のダメージを与えます。
密集している敵に対して特に有効です。
ただし、範囲攻撃の対象にもシールドボーナスは適用されるので、タンクの近くにいる敵を攻撃しても、あまりダメージは出ません。
5. キャラクター選択システム
毎回違う戦略を試せるように、敵のユニット8体をランダムに生成して、それを見てから味方6体を選べるようにしました。
つまり、敵の編成を見てから対策を練れるわけです。
敵にタンクが多ければ高火力ユニットを多めに、敵に遠距離が多ければ高速ユニットで接近戦を挑む、みたいな。
キャラクター選択画面では、まず敵の編成がプレビューされます。
それを見ながら、12種類のユニットカードから6体を選択。
選んだユニットはバッジで表示されて、クリックすれば削除もできます。
6. ファイル分割とコード整理
最初は1つのHTMLファイルに全部詰め込んでいたんですが、さすがに管理しづらい。
最終的な構成は以下のようになりました。
index.html(1.6KB) – HTMLの構造だけstyles.css(5.4KB) – 全スタイル定義constants.js(3.5KB) – ゲーム定数とユニット定義game-state.js(8.1KB) – ゲーム状態管理とターン制御ui.js(9.3KB) – 描画とキャラクター選択画面battle.js(8.5KB) – 戦闘システムと操作ai.js(2.0KB) – 敵AImain.js(0.3KB) – イベントリスナーとゲーム起動
各ファイルの役割が明確になって、後から見直すのも楽になりました。