バトルシステム設計¶
スコープ注記: 本ドキュメントはバトルシステムの設計ドキュメントである。 現時点では§1(effect_offsets 座標系ルール)のみを定義している。 ターン進行、ダメージ計算等のバトルルールは v0.2.0 以降で§として追加予定。
§1 effect_offsets 座標系¶
SkillData.effect_offsets: Array[Vector2i] の座標系ルールを定義する。
スキルの効果範囲をグリッド上で表現するための共通規約であり、TargetResolver が本規約に従ってオフセットを絶対グリッド座標に変換する。
座標系の定義¶
原点¶
相対座標方式 — 術者の位置を (0,0) とする。
- スキル定義が配置位置に依存しない(同じオフセットがどのマスでも同じ意味)
- 絶対座標方式では「隣接味方を回復」を最大9パターン定義する必要があり非現実的
軸の方向¶
| 軸 | 正方向 | 定義 | 根拠 |
|---|---|---|---|
x |
前方(敵側) | x+ = forward |
「前に攻撃する」= x+ が直感的 |
y |
下方(行番号増) | y+ = down |
StageData の index = y * 3 + x(左上 (0,0))および Godot スクリーン座標系と整合 |
y 軸
↓ (y+)
┌──────┬──────┬──────┐
│(0,0) │(1,0) │(2,0) │ ← 行0(上段)
├──────┼──────┼──────┤
│(0,1) │(1,1) │(2,1) │ ← 行1(中段) ※ (x,y) 表記
├──────┼──────┼──────┤
│(0,2) │(1,2) │(2,2) │ ← 行2(下段)
└──────┴──────┴──────┘
列0 列1 列2
(前衛) (中衛) (後衛)
→ x+ (forward / 敵方向)
注意:
Vector2iは(x, y)の順。オフセットVector2i(1, 0)は「前方1マス」、Vector2i(0, 1)は「下方1マス」。
target_side ごとの基準点¶
SkillData.target_side によって、オフセットの基準点と解決先グリッドが異なる。
ALLY(味方対象)¶
| 項目 | 値 |
|---|---|
| 基準点 | 術者の位置 |
| 解決先 | 自軍グリッド |
(0,0) の意味 |
術者自身 |
例: buffer_01 が (col=1, row=1) に配置、隣接4方向バフ
offsets = [Vector2i(-1,0), Vector2i(1,0), Vector2i(0,-1), Vector2i(0,1)]
解決結果(自軍グリッド上の絶対座標):
(0,1), (2,1), (1,0), (1,2) ← 上下左右の4マス
ENEMY(敵対象)— 行相対・列固定方式¶
| 項目 | 値 |
|---|---|
| 基準点 | (術者と同じ行, 敵前衛列) |
| 解決先 | 敵軍グリッド |
(0,0) の意味 |
術者と同じ行の、敵前衛(列0)にいる敵 |
x+は敵陣の奥方向(前衛→中衛→後衛)- 術者の列位置は基準点に影響しない(前衛でも後衛でも同じオフセットで同じ敵を狙う)
例: attacker_01 が行1から単体攻撃
offsets = [Vector2i(0,0)]
基準点 = (col=0, row=1) ← 敵前衛列・同行
解決結果 = (0,1) ← 敵グリッドの前衛・行1
例: attacker_03 が行1(中段)から列全体攻撃
offsets = [Vector2i(0,-1), Vector2i(0,0), Vector2i(0,1)]
基準点 = (col=0, row=1)
解決結果 = (0,0), (0,1), (0,2) ← 敵前衛列の全3行
※ 行0(上端)に配置した場合:
基準点 = (col=0, row=0)
offsets (0,-1) → (0,-1) ← グリッド外 → 無視
解決結果 = (0,0), (0,1) ← 2体のみヒット
→ 配置位置(行)によって効果範囲が変わる = 配置パズル
ALLY と ENEMY の基準点の違い(まとめ)¶
| target_side | 基準点 | (0,0) |
術者の列位置の影響 |
|---|---|---|---|
| ALLY | 術者の位置 | 自分自身 | 列・行ともに影響する |
| ENEMY | (術者の行, 敵前衛列) | 正面の敵前衛 | 行のみ影響。列は不問 |
設計根拠:
- PRD #33 のユースケース記述(「同行の最前列の敵」)と直接対応
- 列の配置判断は「安全性(被弾リスク)」に一本化され、シンプルな位置パズルを維持
- スキル定義が術者の列位置に依存しないため、データの可搬性が高い
グリッド境界ルール¶
1スキル = 1グリッド¶
1つのスキルは target_side で指定された1つのグリッドのみに作用する。
自軍と敵軍の両方に同時作用するスキルは MVP では存在しない。
将来的に必要になった場合は、スキルに複数の効果エントリを持たせる拡張で対応する。
グリッド外オフセットの処理¶
解決後の絶対座標がグリッド範囲(0≤x≤2, 0≤y≤2)を超える場合、そのオフセットは 無視(スキップ) する。
- エラーにしない: グリッド端の配置で効果範囲が自然に狭まる挙動は、配置パズルとして意図的
- TargetResolver の責務: グリッド外座標を除外し、有効な座標のみを返す
パッシブスキルでの扱い¶
パッシブスキルもアクティブスキルと同じ座標系・同じ effect_offsets を使用する。
| パッシブ種別 | offsets 例 | target_side | 解決タイミング |
|---|---|---|---|
| オーラ型(隣接バフ) | [(-1,0), (1,0), (0,-1), (0,1)] |
ALLY | バトル開始時 + 配置変更時 |
| トリガー型(反撃) | [] |
— | イベント発生時(BattleEngine) |
| 自己バフ型 | [(0,0)] |
ALLY | バトル開始時 |
トリガー型パッシブの特殊扱い¶
トリガー型パッシブ(例: 被弾時に反撃)の対象は、グリッド位置ではなく イベントコンテキスト(「攻撃してきた敵」)から決定する。
effect_offsetsは空配列[]TargetResolverは空配列を受けた場合「位置解決不要」として扱う- 対象の解決は BattleEngine のイベント処理ロジックが担う
実装ガイドライン¶
TargetResolver の責務¶
- 術者の位置と
target_sideから基準点を算出 effect_offsetsの各要素を基準点に加算し、絶対グリッド座標を得る- グリッド範囲外の座標を除外
- 有効な座標の配列を返す
# 疑似コード
func resolve(caster_pos: Vector2i, offsets: Array[Vector2i],
target_side: SkillData.TargetSide) -> Array[Vector2i]:
if offsets.is_empty():
return [] # トリガー型パッシブ等、位置解決不要
var origin: Vector2i
match target_side:
SkillData.TargetSide.ALLY:
origin = caster_pos
SkillData.TargetSide.ENEMY:
origin = Vector2i(0, caster_pos.y) # 敵前衛列・同行
var results: Array[Vector2i] = []
for offset in offsets:
var pos := origin + offset
if _is_in_grid(pos):
results.append(pos)
return results
各スキルの具体的なオフセット定義は data/skills/*.tres を参照。自動生成されたユニット一覧でスキルの効果・対象を確認できる。
参照リンク¶
| ドキュメント | リンク |
|---|---|
| スキルシステム PRD | #33 |
| バトルシステム PRD | #32 |
| SkillData Resource 実装 | scripts/data/skill_data.gd |
| StageData Resource 実装 | scripts/data/stage_data.gd |
| GDD §3 バトルシステム概要 | docs/gdd.md |
| ユニットシステム設計 | docs/design/unit_system.md |
変更履歴¶
| 日付 | 変更内容 |
|---|---|
| 2026/02/17 | 初版作成(effect_offsets_coordinate.md として) |
| 2026/02/22 | battle_system.md にリネーム。§1 として再構成。壊れた参照リンクを修正 |