1

我正在开发一个以 Flixel 为基础的游戏,我需要的部分内容是检查沿线的碰撞(特别是从 A 点到 B 点的线)。解释这一点的最好方法是我有一个激光束从一艘船射到另一个物体(或者如果没有任何东西与线重叠,则射到空间中的一个点)。我希望这条线只到达它碰到一个物体。如何以数学/编程方式确定该线沿线在何处进入对象?

我可以尝试测量线的长度并检查碰撞点,直到有人这样做,但是当我确定有一种数学方法来确定它时,这似乎对每一帧都进行了太多的开销。

编辑:在检查对象是否与线本身发生碰撞之前,我将首先消除不在线边界框内的任何对象 - 由最左边点的 x、最顶部点的 y、最右边的点和最底端的 y。这会将行碰撞检查限制为几个对象。

再次编辑:对不起,我的问题似乎仍然不完全清楚。一些解决方案可能会起作用,但我正在寻找一个简单的,最好是数学解决方案。当我说“矩形”时,我的意思是边锁定在 x 和 y 轴上的矩形,而不是可旋转的矩形。因此,一条线不是宽度为 0 的矩形,除非它位于 90 度或 -90 度(假设 0 度指向屏幕右侧)。

这是我要查找的内容的可视化表示: 线路碰撞检测

4

4 回答 4

6

所以,你有一条线段(AB),我收集到这条线段正在移动,你想知道这条线段会在什么点与另一条线段(你的船,无论如何)发生碰撞。

因此,从数学上讲,您想要检查两条线何时相交(两条线将始终相交,除非平行),然后检查它们相交的点是否在您的屏幕上。首先,您需要将线段转换为线方程,如下所示:

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};
     }  
}

Point2D 将为您提供相交点,当然您必须针对所有船的线段测试您的线段,这可能会有点耗时,例如碰撞框等进入图片。

数学都在维基百科中,如果您需要更多信息,请查看那里。

编辑:

附加组件以跟进评论:

与之前测试您的线段与矩形的所有四个线段的碰撞相同,您将得到以下三种情况之一:

  1. 屏幕上没有碰撞/碰撞点(请记住,碰撞测试是针对线,而不是线段,除非平行,否则线将始终相交),嘲讽玩家失踪:-)
  2. 一次碰撞,绘制/执行任何您想要的部分将是 AC(C 碰撞点)
  3. 两次碰撞,使用类似下面的代码检查每个结果段 (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

我没有数学天赋,但我认为你可以这样做:

  1. 测量距块中心和激光束的距离。
  2. 以给定的角度测量块中心和块边缘之间的距离(会有一个公式,我只是不知道它是什么)。

从点 2 的结果中减去点 1 的结果。

这样做的好处是,如果第 1 点大于第 2 点,您就知道还没有发生碰撞。

或者使用box2d,然后使用b2ContactPoint

于 2011-11-09T04:07:57.737 回答
0

你应该看看分离轴定理。这通常用于多边形,但我认为您可以使其适用于直线和多边形。

我在这里找到了一个以简洁方式解释它的链接

于 2011-11-09T05:14:21.390 回答