2012-12-28 37 views
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; 
} 

該代碼有點複雜,我不擅長三角學,我一直無法找出它爲什麼不工作。播放器從屏幕頂部開始,線出現的那一刻它會記錄一次碰撞。如果有任何問題,請問,我真的很想弄清楚。提前致謝。

回答

2

好像你可以跳過幾個步驟 - 可能有一個更聰明的方法,但我不認爲你需要計算角度theta。

(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),則與您聯繫。

值得注意的是,如果您符合線的無限延伸但不在頂端,這看起來像是碰撞,因爲我們僅使用兩點來確定整條線。如果您不需要與該段碰撞並繞過它,我將首先在圍繞圓圈的方框的角落與圍繞該線段的方框之間進行簡單的邊界框碰撞測試,然後再計算最近的接近段。

+0

我在解決xi和yi這兩個方程時遇到了問題,你能否提供一個解決這個問題的方案? – avorum

+0

劃痕,讓它工作。感謝您的幫助,就像魅力一樣。 – avorum