Appearance
第19回 地形との衝突解決
1 / 4 重なり検知と位置補正の違い
このステップの目的
矩形同士が重なっているかを調べる「検知処理」と、めり込みを解消する「位置補正処理」の違いを理解し、軸分離によって位置補正を行う理由を学びます。
Overlaps() と位置補正の違い
第04回で作成した Rect::Overlaps() は、2つの矩形が重なっているかどうかを判定する関数でした。
Rect.hcpp
constexpr bool Rect::Overlaps(const Rect& other) const
{
return x < other.x + other.width &&
x + width > other.x &&
y < other.y + other.height &&
y + height > other.y;
}弾が敵に命中したかを調べる処理では、重なりの有無(true / false)のみで十分です。
しかし、地形との衝突判定では「重なっている事実」に加えて、**「どちらの方向へ何ピクセル押し戻せばめり込みを解消できるか」**という情報が必要になります。Overlaps() の真偽値だけでは、適切な押し戻し方向と量を特定できません。
斜め移動を同時に解く場合の問題点
斜め方向の移動後に、重なり量(めり込み深さ)が最も浅い方向へ押し戻すアルゴリズムを検討してみます。
この方法には、移動の意図と異なる軸へ押し戻される問題があります。
例えば、壁の側面に沿って落下している最中に、壁の角へわずかに接触したとします。このとき、垂直方向のめり込み量が水平方向のめり込み量よりも小さい場合、「上方向へ押し戻す」と判定されてしまいます。その結果、壁に触れた瞬間にキャラクターが上方へ押し出される不自然な挙動が発生します。
軸分離による衝突解決
この問題を避けるため、**「移動と衝突解決をX軸とY軸に分離して順番に処理する(軸分離)」**アプローチを採用します。
- X軸の移動と衝突解決:
まず水平方向にのみ移動します。この段階で壁ブロックと重なった場合、水平方向の移動によるめり込みであることが明確なため、水平方向に押し戻します。 - Y軸の移動と衝突解決:
水平方向の位置補正が完了した状態から、垂直方向に移動します。この段階で床や天井と重なった場合、垂直方向の移動によるめり込みであることが明確なため、垂直方向に押し戻します。
移動と衝突解決を軸ごとに分離することで、押し戻し方向の曖昧さが解消され、角の接触時にも安定した挙動が得られます。
チェックリスト
- 単なる重なり判定(
Overlaps)と位置補正(Resolve)の違いを説明できる - 斜め移動を同時に最短距離で押し戻そうとした場合に生じる問題(上方への意図しない押し戻し)を理解している
- 「横移動 → 横補正」の後に「縦移動 → 縦補正」を行う軸分離の仕組みを説明できる