0

だから私は、落書きゲームで円形のプレーヤーと線の間の衝突検出を取得しようとしています(as3を使用)。このために、線の端点と円を含む画像の左上の 3 点を知っています。

//Detects collision between a given player and a given line
public function detectCollision(p:Player, l:Line): Boolean{
    //First create a line running parallel to l that runs through the center of p
    //p hereby referred to by "the player"
    //l hereby referred to by "the offending line"
    //start by finding the center of p
    var pCenter:Point = new Point(p.x + 38, p.y + 38); //38 = radius
    //now find the angle of the offending line (in Q1 or Q2)
    var theta:Number = Math.atan2(l.y2 - l.y1, l.x2 - l.x1);
    //now make a line within the player that conforms to this angle
    var paraLine:Line = new Line(pCenter.x - Math.cos(theta) * 38, pCenter.y - Math.sin(theta) * 38, pCenter.x + Math.cos(theta) * 38, pCenter.y + Math.sin(theta) * 38);

    //Next we're going to create a perpendicular line in the circle pointing at the offending line
    var perpenLine:Line = new Line(pCenter.x - Math.cos(theta) * 38, pCenter.y + Math.sin(theta) * 38, pCenter.x + Math.cos(theta) * 38, pCenter.y + Math.sin(theta) * 38);
    var closestOnCircle:Point = new Point(pCenter.x - Math.cos(theta) * 38, pCenter.y + Math.sin(theta) * 38); //this is the point on the circle closest to the offending line

    //Now to find where the line running perpendicular to the offending line through the center of the player intersects with the offending line
    //this is done by using algebra
    //y = mx + b (perpenLine)
    //y = nx + c (offending line)
    //mx + b = nx + c
    //b - c = (n - m)x
    //x = (b - c) / (n - m)
    var xIntercept:Number = (perpenLine.getOffset() - l.getOffset()) / (l.getSlope() - perpenLine.getSlope());
    var pointOnLine:Point = new Point(xIntercept, xIntercept * l.getSlope() + l.getOffset()); //point on the line where the intersection happens

    //Finally whether a collision has occurred is calculated
    //this is done by seeing if both pCenter and closestOnCircle are on the same side of pointOnLine
    if((pCenter.y > pointOnLine.y && closestOnCircle.y > pointOnLine.y) || (pCenter.y < pointOnLine.y && closestOnCircle.y < pointOnLine.y))
        return false;
    else
        return true;
}

コードはやや複雑で、私は三角法が苦手で、なぜ機能しないのかを突き止めることができませんでした。プレーヤーは画面の上部から開始し、線が表示された瞬間に衝突が記録されます。ご不明な点がございましたら、お気軽にお問い合わせください。解決したいと思います。前もって感謝します。

4

1 に答える 1

2

いくつかの手順をスキップできるようです。もっと賢いアプローチがあるかもしれませんが、角度シータを計算する必要はないと思います。

から(x1, y1)までの直線(x2, y2)の傾きはm = (y2-y1)/(x2-x1)です。円の中心を(xc, yc)最も接近した線に接続する線は、その勾配に垂直であるため(あなたが言うように)、勾配は-1/mです。それらの線が交わる点を呼び出します(xi, yi)。(元の行から) と書くyi = (xi - x1)*m + y1ことができ、 と書くこともできますyi = (xi -xc)(-1/m) + yc。2 つの方程式、2 つの未知数、xi と yi を解くのは比較的簡単です。次に、円の中心から交点までの線の長さを決定し、それが半径 (38) より小さい場合は接触しています。

ライン全体を決定するために 2 つのポイントのみを使用しているため、ラインの無限延長に沿っているが、その上にない場合、これは衝突のように見えることに注意してください。このセグメントと衝突してその周りを通過する必要がない場合は、最接近セグメントを計算する前に、円の周りのボックスの角と線の周りのボックスの間の単純なバウンディング ボックス衝突テストから始めます。

于 2012-12-28T20:54:56.377 に答える