このチュートリアルでは、弾幕(だんまく)システムを実演するサンプルゲーム「BulletHellSample」の構造と内部メカニズムを説明します。
◆ ゲーム概要
このゲームでは、500 HP のボスを、ショット と ボム を使って倒します。
これはサンプルプロジェクトのため、ボスを倒すとゲームは終了します。
操作方法
- 矢印キー:移動
- Zキー:ショット
- Xキー:ボム
グレイズ や ボムによる弾消し といった、一般的な弾幕ゲームのメカニクスが実装されています。
ゲームシーン構造
ゲームは単一のシーン test_scene.tscn で構成されています。
シーン遷移はありません。
オブジェクト構造
プレイヤー
player.tscn がプレイヤーキャラクターのシーンです。
以下の子ノードを持ちます:
GrazeObject.tscn:グレイズ検出を担当player_hit_checker.tscn:ダメージ(ヒット)検出を担当
敵
enemy.tscn が敵(ボス)のシーンです。
以下の子ノードを持ちます:
damage_checker.tscn:ダメージ検出を担当
機能実装の詳細
敵の弾パターン
敵は単純に一定時間間隔で弾パターンを発射します。
パターンは以下の通りです:
- 加速する全方位弾
- 移動と組み合わせたショットガン風パターン
- ステージ端からプレイヤーを狙って分裂する弾
- 全方位弾グループを組み合わせた花形パターン
- 方向変更弾を使ったシンプルな幾何学パターン
弾パターンには繰り返し再生される効果音が必要なため、AnimationPlayer ノード経由で AudioStreamPlayer の音を再生する形で実装しています。
これは、現在適切なサウンドアセットが用意されていないための暫定的な対応です。
理想としては、各弾パターンごとに適切な効果音を用意し、直接再生すべきです。
- 現在の弾システムでは、アクティブな弾生成を停止する手段がありません。そのため、敵が倒された後でもすでに生成が始まった弾はそのまま発射され続けます。
将来のアップデートで弾停止メカニズムを追加し、この問題を修正する予定です。
それまでは、繰り返し処理を使わず、手動で繰り返しを制御する状態分離のロジックにすることで回避できます。
プレイヤーの通常ショットパターン
プレイヤーは1つの状態内で4種類の異なる弾パターンを同時に発射します。
現在のところ、明示的に方向を指定して連射弾を発射することはできません。
この問題を回避するため、システムは非常に遠方のグローバル座標に向かって弾を発射し、実質的に方向指定発射を模倣しています。
- 明示的な方向指定で発射できるようにするアップデートを計画中です。
グレイズシステム
グレイズは、プレイヤーの子ノードとして GrazeObject.tscn を配置することで実装されています。
このオブジェクトは、プレイヤーのヒットボックスよりも広い衝突領域を持ちます。
敵弾と衝突した際には:
- グレイズ粒子を発生
- スコアを増加
ダメージ処理
プレイヤーと敵の両方のダメージ処理は、別々の子オブジェクト を用いて実装されています。
これには主に2つの理由があります:
- ダメージイベントによって現在実行中の状態が中断されることを防ぐため
- グレイズ と ダメージ のヒット検出を明確に分離するため
- ACTION GAME MAKER では、HitArea2D がルートノード以下のすべての HitArea と衝突をチェックするため、子ノードのヒットボックスも検出されます。
この問題は、ヒット領域を子ノードではなく子オブジェクトとして生成することで回避できますが、本プロジェクトでは衝突位置を視覚的に確認しやすくするため、子ノードを使用しています。
弾レイヤー設定
レイヤーは以下のように設定されています:
- プレイヤー:レイヤー1
- 敵:レイヤー2
- グレイズ検出:レイヤー3
弾のレイヤー:
- 敵弾:レイヤー1と3
- プレイヤー弾:レイヤー2
ボムの実装
ボムは弾パターンではなく、通常の弾として実装されています。
bomb.tscn がボムのシーンです。
機能:
-
画面全体をカバーする衝突領域
-
衝突した弾を消去
-
消去した弾を10%の確率でスコアアイテムに変換
-
攻撃ヒットボックスにより敵自体にダメージを与える
-
弾をスコアアイテムに変換する処理はオブジェクト生成を伴うため、比較的重い処理です。
変換率を100%に設定するとパフォーマンス問題が発生します。
この問題に対する対策は現在検討中です。
スコアアイテム
オブジェクト生成の処理コストを軽減するため、スコアアイテムは GDScript を用いて実装されています。
- シーン:
score_test.tscn - 動作:
- プレイヤーに向かって移動
- 一定距離内に入ると消滅
- 指定された変数を増減
Scoreノードのインスペクター で値をカスタマイズできます:
- PickUpRadius:衝突検出距離
- PullSpeed:移動速度
- Group:向かう対象グループ
- Project Variable:変更するプロジェクト変数の名前
- Variable Add:加算量