2D当たり判定超入門

2D当たり判定超入門
この講演の対象者
• これからゲームを作ろうとしてるプログラマ
– 当たり判定の実装とコツを学べるかも?
• プログラマ以外のゲーム制作者
– 当たり判定がどうなってるか何となく理解できる
– バグも見つけやすくなるかも?
• すでに経験のある人
– かなり入門的なんで暇かも
超基本
円の当たり判定
弾とキャラクターの衝突などに使う
弾とキャラクターの衝突などに使う
円の交差判定方法は?
• 円Aの中心から円Bの中心までの距離が、
円Aと円Bの半径より小さければ交差している
• 円の中心同士の距離は、ピタゴラスの定理
(三平方の定理)を使う。
三平方の定理
C
B
A
Aの2乗+Bの2乗 = Cの2乗
こんなイメージ
半径の和<斜辺
⇒ 交差していない
半径の和>斜辺
⇒ 交差している
計算式
(cx1‐cx2)^2 + (cy1‐cy2)^2 ≦ (r1+r2)^2
• 左辺が円の中心同士の距離の2乗
• 右辺は2つの円の、半径の和の2乗
• 2乗してるのは、左辺をsqrt(平方根) するよりも
右辺を2乗するほうが高速なため
点と円
(px‐cx)^2 + (py‐cy)^2 ≦ r^2
(点のX座標-円の中心X座標)の2乗
+(点のY座標-円の中心Y座標)の2乗
≦ 円の半径の2乗
片方が半径0の円になったようなもの。
さっきの内容が分かっていれば非常に単純
こんなイメージ
円の半径<斜辺
⇒ 交差していない
円の半径>斜辺
⇒ 交差している
矩形の当たり判定
弾とキャラクターの衝突などに使う
(0, 0) (640, 0) (0, 480) (640, 480) ※左上を(0, 0)とするスクリーン座標で
矩形0の左<矩形1の右 かつ
矩形0の上<矩形1の下 かつ
矩形0の右>矩形1の左 かつ
矩形0の下>矩形1の上
矩形0・矩形1の衝突判定式
Left0 < right1 && top0 < bottom1 &&
right0 > left1 &&
bottom0 > top1
矩形の当たり判定
• 比較演算だけなのでかなり高速
• だいたい、以下の2つのパターンが多い
– 左, 上, 右, 下 でデータを持つ
– 左, 上, 幅, 高さ でデータを持つ
• 簡単なゲームならこれだけで充分
超基本終了
• ここまでに説明した判定処理だけでも、2D
ゲームは充分作れます。
• まずは作ってみて、どうしても複雑なことがし
たくなったら、別の判定方法を勉強しましょう。
ベクトルの利用
ベクトルを使うと何ができる?
• アクションゲームを簡単に作れます
• 2Dゲームであれば、前述の円・矩形の判定と、
ベクトルさえ分かっていればほとんどのゲーム
を作れます
その前に
ベクトルのおさらい
(分かる人は飛ばして下さい)
ベクトルとは?
• 大きさと方向を持った、線みたいなもの
• 2次元ベクトルなら、(X方向, Y方向)で方向を、
表す
• ベクトルAは、A と表現することが多い
• ベクトルAの大きさは、|A| のように表現
※本資料では、上の矢印は省略しています
(PC上だといちいち書くのが面倒なので)
2次元ベクトルの例
※左上(0,0)を正とするスクリーン座標系
(5, 10)
(10, 0)
(‐10, 10)
(‐5, ‐5)
ベクトルの大きさ
• 三平方の定理を使う。
• 斜辺の長さ=ベクトルの大きさ
ベクトルA = (4,3) なら、大きさは 5
5
3
4
単位ベクトル
• 大きさが1のベクトルを、単位ベクトルと呼ぶ
• ベクトルの各成分(2次元ならX, Y)を、そのベクト
ルの大きさで割ると単位ベクトルが算出される
• 大きさが0のベクトルを、ゼロベクトルと呼ぶ
(3,4) のベクトルなら、単位ベクトルは
(3÷5,4÷5) = (0.6,0.8)
ベクトル同士の加減算
• ベクトル同士の加減算は、それぞれの
成分同士で行われる
(1,2) + (3,5) = (1+3, 2+5) = (4,7)
(5,4) - (5,2) = (5-5, 4-2) = (0,2)
ベクトルに通常の数を掛ける
• ベクトルに通常の数を掛ける場合は、
各成分にその値を掛ける
(1,2) × (5,2) = (1*5, 2*2)= (5, 4)
内積(ドット積)の公式
• ベクトルA(x0, y0)と、ベクトルB(x1, y1)の
内積(A・B)は、
A・B = x0*y0 + x1*y1 = |A||B| Cosθ
外積(クロス積)の公式
• ベクトルA(x0, y0)と、ベクトルB(x1, y1)の
外積(A×B)は、
A×B = x0*y1 - x1*y0 = |A||B| Sinθ
この図を覚えてください!
|A|
|A|Sinθ
θ
|A|Cosθ
2Dゲームではこれだけ覚えておけば充分です
内積・外積の公式を変形させて使います
DirectXでは?
• D3DXVECTOR2 という、2次元ベクトルを表す
構造体が用意されている
// (10, 20) のベクトルインスタンスを生成
D3DXVECTOR2 vec(10, 20);
// 大きさを算出
float length = sqrt(vec.x*vec.x + vec.y*vec.y);
// ヘルパ関数を使う場合
float length = D3DXVec2Length(&vec);
DirectXでは?(内積・外積)
D3DXVECTOR2 vec0, vec1;
// 内積
float dot = vec0.x*vec1.x + vec0.y * vec1.y;
// ヘルパ関数を使う場合
float dot = D3DXVec2Dot (&vec0, &vec1);
// 外積
float cross = vec0.x*vec1.y – vec1.x * vec0.y;
ここから
ベクトル利用法
開始
点と線分の距離
レーザーとの衝突判定や
地形にめり込んだ際の押し出し距離
に使う
この距離だけ
左に押し戻す
地形にめり込んだ際の押し出し距離
押し出す場合は、
押し出す距離 × 押し出す方向の単位ベクトル
で、X, Y それぞれの方向の押し出し量が算出される
この距離だけ
斜面のベクトルを90度
反時計回りさせた方向に押し戻す
1.点と直線の距離
• 2点A・Bを通る直線と点Pの距離を出す
• 点線の部分が距離
⇒Sinなので外積を使う
P
|AP|Sinθ
θ
A
B
ベクトルAP とベクトル ABの外積は、
AP×AB = AP_X*AB_Y – AB_X*AP_Y
= |AP||AB| Sinθ
点線部は、APとABの外積 ÷ ABの大きさ
|AP||AB| Sinθ ÷ |AB|
P
|AP|Sinθ
θ
A
B
プログラムだとこんな感じ
// 線分のベクトル
D3DXVECTOR2 ap(px – ax, py – ay);
D3DXVECTOR2 ab(bx – ax, by – ay);
// 外積
float cross = ap.x* ab.y – ab.x * ap.y;
// A == B だと、0除算になるので注意
float result = fabs(cross) / D3DXVec2Length(ab);
2.点と線分の距離
• このような場合には、前述の方法でいいが
P
A
B
2.点と線分の距離(2)
• このような場合、点と線分の距離は
点線ではなくAPである
P
A
B
• PがABの範囲内かどうかで場合分けが必要
• Cosθ > 0 なら、点Pは点Aの右側にある
• Cosθ < 0 なら、点Pは点Aの左側にある
※ Bについても同様の判定を行うこと
P
A
θ
|AP|Cosθ
⇒Cosなので内積を使う
ベクトルAP とベクトル ABの内積は、
AP・AB = AP_X*AB_X + AP_Y*AB_Y
= |AP||AB| Cosθ
|AP|, |AB| は正なので、内積の結果が負なら、
点Pは点Aより左側である。
(コサイン(Cos)は、90度~270度が負)
P
A
θ
|AP|Cosθ
負
B
正
レーザーと円の当たり判定
1. レーザーを線分として、円の中点との距離を出す
2. 距離からレーザーの厚みと円の半径を引いて、
その値が0以下なら衝突している
斜面に立つ
斜面に立つ
• 外積を使うのが簡単
• 点線部を外積で算出し、キャラクターをその
高さに合わせる(ABのY座標に加算)
P
θ
A
B
斜面はめんどくさい!
• 低い等身の自機を扱う場合、ギリギリに
立てないとプレイヤーが違和感を感じる
• しかし斜面では、体の中央に高さを合わせない
と違和感がある
• 平面から歩行して斜面にさしかかった場合、
下が穴か斜面かで判定を分けなければならない
○
×
点がベクトルの
どちら側に
あるか
地形にめり込んでいるかどうか調べる
• このようにベクトルで地形を保持している場合、
ベクトルの右側ならめり込んでいる
地形にめり込んでいるかどうか調べる
点が線分のどちら側にあるか
AP と ABの外積 = |AP||AB| Sinθ
を利用
• Sinθ > 0 なら、点PはABの左側にある
• Sinθ < 0 なら、点PはABの右側にある
(サイン(Sin)は、180度~360度が負)
正
P
負
|AP|Sinθ
θ
A
B
線分同士の交差
例えば、すり抜け防止などに使える
今までの、矩形や円の判定だと、弾が早すぎたり、
敵が小さすぎたりしてすり抜けることもある
直前のフレーム
現在のフレーム
直前の位置と現在の位置を結ぶ
直前座標から現在座標へのベクトルで交差判定
1. 線分が交差しているかどうか
• 線分が交差している場合は、互いの線分が、
線分の左右に端点を持つ状態である
端点が同じ側にあれば交差していない
4つの端点に対して、線分のどちら側
にあるのかを判定すればいい
• 線分ABと線分CDなら、
(AB×AC )* (AB × AD) <= 0.0 &&
(CD ×CA) *(CD × CB ) <= 0.0
• 左右にあれば、外積のどちらかは正でどちら
かは負なので、積が0以下になる。
2. 線分が交差する場合の交差座標
• 線分ABの、①:②の比がわかれば、交点の
座標が算出できる。
交点 = A + ベクトルAB*① / (①+②)
A
①
C
D
②
B
外積を使って比を算出
①:② =CAとCDの外積:CBとCDの外積
A
①
C
D
②
B
計算方法については終わり
• 楕円や多角形、 軸平行でない四角形
などもあるが、複雑なのでここでは割愛。
• どうしても必要になったら以下のサイトなどで
調べて下さい。
• 使わなくても割となんとかなります。
• ○×(まるぺけ)つくろーどっとコム
– http://marupeke296.com/
ケーススタディ
ケーススタディ
• 自分がアクションゲームを作った際の一例
• このやり方が正解とは限りませんので、自分なり
のやり方があればそれでかまいません
• 完全に我流なので、もしかしたらm9(^Д^)プギャー
なやり方かも
• 参考にする程度でいいです
画像に当たり判定をセットすると楽
• キャラクターや弾のクラスではなく、
画像クラスが当たり判定を保持している
同じキャラでも画像によって異なる判定
• 緑色の判定に当たったら、弾を防ぐ
• 赤色の判定に当たったらダメージ
• 弾を撃っているときは、弾を防ぐ用の緑色の
判定が無い
プレイヤーの近接攻撃を画像から取得
• 緑色の部分が攻撃判定
• 赤色の部分が当たり判定
開発中の凡ミスとか(1)
• 左右反転時に、当たり判定も反転させる
のを忘れていた
↓ こんな感じに・・・
開発中の凡ミスとか(2)
• スライディング時 と 通常時の当たり判定
が違っててすり抜けた
立ち状態で壁ギリギリに居て、スライディングしたらすり抜けた
開発中の凡ミスとか(3)
• ギリギリで垂直ジャンプしたら上の足場
に乗ってしまった
• 右辺のX座標=上辺右端のX座標なため、
引っかかってしまったのが原因
立ち状態で壁ギリギリに居て、ジャンプしたら乗ってしまった
開発中の凡ミスとか(4)
• 押し出し時の処理を、自機の座標に加
算して押し出し続けていたら、float の演
算誤差ですり抜けてしまった
• 押し出し処理は、加算するのでなく壁の
位置に合わせてセットしたほうがいい
関連書籍
•
ゲーム開発のための
数学・物理学入門
• ゲームで使いそうな、高校レベルの数学、物理
学の基礎を扱う
• リファレンスとして使いやすい構成の本。持っ
ていると便利。
• 各項には公式の簡単な説明+ソースコード例
が書いてある。
• いちいちポンド、ヤードなどから、メートル,グラ
ム法に単位を直しているのが分かりづらくて難
ゲームプログラミング
のための
リアルタイム衝突判定
•
•
•
•
上級者向け
本格的に衝突判定を学びたいならオススメ
ただ・・・高い。 8,400円する
学生は学校の図書館にリクエストだ!
DirectX入門書
• マスタリングDirectXプログラミング
• DirectX ゲームグラフィックス プログラミング
• DirectX の入門書ならこの2冊が分かりやすく
てオススメ
•
シューティングゲーム
プログラミング
• ウインドウの生成、DirectX の初期化、キー
入力、サウンド再生、タスク処理など、
一通りの処理が実装されている。
• この本のソースコードを読んで理解するだ
けで、ある程度簡単なゲームなら作れる。
• 初めて作る人は目を通してみては
•
シューティングゲーム
アルゴリズムマニアックス
• 時期狙い弾、N‐WAY弾、分裂弾・・・と、STG のアルゴリズムを色々扱っている。
• シューティング作ってみたい人は読んでみ
るといいかも。
• この著者もこの辺まではまともに本を書い
ていますね・・・
•
アクションゲーム
アルゴリズムマニアックス
• アクションゲームの資料は少ないから期待して
買ったわけですが・・・
• 正直ひどい。即投げ捨てたくなった。
• 色々な2Dアクションの「○○っぽい動作」を実装
しているが、フラグや計算が異なるだけで似た
ような処理の連続。ソースだらけのページ稼ぎ。
• 汎用的な書き方もできてないので使いづらい
•
弾幕 最強のシューティ
ングゲームを作る!
• 「○○な感じの弾幕」を延々と載せてある
構成の本。
• 弾幕ゲーを作ってみたい人は読んでみて
もいいかも
使用した素材
• 当たり判定の説明時に扱った画像は、サーク
ル様の許可を得た上で使用しております。
• 湍(サークル新雅)
• The Idol MegaM@ster(サークルGAPCOM)