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)
© Copyright 2024 Paperzz