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

似乎您可以跳过几个步骤 - 可能有更聪明的方法,但我认为您不需要计算角度 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)。

值得注意的是,如果您与线的无限延伸对齐但不在其顶部,则这看起来像是碰撞,因为我们仅使用两个点来确定整条线。如果您不需要与该段发生碰撞并绕过它,我将在计算最近的接近段之前在圆周围的框的角和线周围的框之间进行简单的边界框碰撞测试。

于 2012-12-28T20:54:56.377 回答