1

私は Flixel をベースにゲームを開発しています。必要なのは、線 (具体的には点 A から点 B への線) に沿った衝突をチェックする方法です。これを説明する最良の方法は、ある船から別のオブジェクト (またはラインに重なっていない場合は空間内のポイント) に向けてレーザー ビームを発射していることです。物に当たるまでだけ線が届くようにしたい。線がオブジェクトにぶつかっている線に沿った場所を数学的/プログラム的に判断するにはどうすればよいですか?

線の長さを測定し、衝突するまでポイントをチェックすることもできますが、それを決定する数学的な方法があると確信している場合、すべてのフレームを実行するにはオーバーヘッドが多すぎるように思えます。

編集: ライン自体との衝突についてオブジェクトをチェックする前に、最初に、ラインのバウンディング ボックス内にないオブジェクトをすべて除外します。一番右の点、および一番下の点の y。これにより、ライン衝突チェックがいくつかのオブジェクトに制限されます。

もう一度編集: 私の質問はまだ完全に明確ではないようです。申し訳ありません。解決策のいくつかはおそらくうまくいくでしょうが、私は単純でできれば数学的な解決策を探しています。また、「長方形」と言うときは、回転可能な長方形ではなく、x 軸と y 軸に固定された側面を意味します。したがって、90 度または -90 度でない限り、線は幅 0 の長方形ではありません (0 度が画面の右側を指していると仮定します)。

これが私が見つけようとしているものの視覚的表現です: ライン衝突検出

4

4 に答える 4

6

線分 (AB) があり、その線分が動いていることを収集しました。線分が別の線分 (船など) と衝突するポイントを知りたいと考えています。

したがって、数学的には、2 つの線がいつ交差するかを確認し (平行でない限り、2 つの線は常に交差します)、交差する点が画面上にあるかどうかを確認する必要があります。まず、線分を次のような線の方程式に変換する必要があります。

typedef struct {
    GLfloat A;
    GLfloat B;
    GLfloat C;
} Line;

static inline Line LineMakeFromCoords(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {
    return (Line) {y2-y1, x1-x2, (y2-y1)*x1+(x1-x2)*y1};
}

static inline Line LineMakeFromSegment(Segment segment) {
    return LineMakeFromCoords(segment.P1.x,segment.P1.y,segment.P2.x,segment.P2.y);
}

次に、それらが交差するかどうかを確認します

static inline Point2D IntersectLines(Line line1, Line line2) {
    GLfloat det = line1.A*line2.B - line2.A*line1.B;
     if(det == 0){
    //Lines are parallel
            return (Point2D) {0.0, 0.0};  // FIXME should return nil
     }else{
            return (Point2D) {(line2.B*line1.C - line1.B*line2.C)/det, (line1.A*line2.C - line2.A*line1.C)/det};
     }  
}

もちろん、船のすべての線分に対して線分をテストする必要があります.

数学はすべてウィキペディアにあります。詳細情報が必要な場合はそこを確認してください。

編集:

コメントをフォローアップするためのアドオン:

前と同じように、長方形の 4 つのセグメントすべてに対するセグメントの衝突をテストすると、次の 3 つのケースのいずれかが得られます。

  1. 衝突/衝突ポイントが画面上にない (衝突テストは線分ではなく線に対して行われることを忘れないでください。線は平行でない限り常に交差します)、欠落しているプレーヤーを挑発します :-)
  2. 1回の衝突、描画/やりたいことは何でもあなたが求めているセグメントはAC(C衝突点)になります
  3. 2 つの衝突。以下のコードのようなものを使用して、結果の各セグメント (A-C1) と (A-C2) のサイズを確認し、サイズが最も小さいものを保持します。

    static inline float SegmentSizeFromPoints(Vertice3D P1, Vertice3D P2) {
         return sqrtf(powf((P1.x - P2.x),2.0) + pow((P1.y - P2.y),2.0));
    }
    

衝突を処理する際の注意点は、実行する必要があるテストの数を最小限に抑える方法を見つけることです。

于 2011-11-09T12:50:10.350 に答える
2
  1. 行の式を見つけるy = ((y2 - y1)/(x2 - x1)) * (x - x1) + y1
  2. スプライトのバウンディング ボックスを見つける
  3. 各スプライトの境界ボックスについて:
  4. 現在の境界ボックスの各コーナーについて:
  5. コーナーの座標の x 値を (1 から) 直線の式に入力し、結果から座標の y 値を減算します。
  6. 5の計算から符号を記録する
  7. 4 つの符号がすべて等しい場合、衝突は発生しません。いずれかの符号が異なる場合は、衝突の可能性があるため、さらにチェックしてください。
于 2011-11-10T22:21:15.183 に答える
0

分離軸定理を確認する必要があります。これは一般的にポリゴンに使用されますが、線とポリゴンで機能させることができると思います。

簡潔に説明しているリンクをここで見つけました。

于 2011-11-09T05:14:21.390 に答える
0

私は数学の才能はありませんが、次のようなことができると思います。

  1. ブロックの中心とレーザービームからの距離を測定します。
  2. ブロックの中心とブロックの端の間の距離を特定の角度で測定します (これには式がありますが、それが何であるかはわかりません)。

ポイント 2 の結果からポイント 1 の結果を引きます。

これの良いところは、点 1 が点 2 より大きい場合、まだ衝突が発生していないことがわかるということです。

または、 box2dを使用し、単に使用しますb2ContactPoint

于 2011-11-09T04:07:57.737 に答える