我正在开发以Flixel为基础的游戏,我需要的一部分是检查沿线的碰撞(特别是从A点到B点的线)。解释这个问题的最佳方法是我有一个激光束从一艘船射到另一个物体(如果没有任何东西与该线重叠,则会射到太空中的一个点)。我希望线只能到达物体。如何以数学/编程方式确定线条在一条直线上运行的位置?
我可以尝试测量线的长度并检查碰撞点,直到碰到它,但是当我确定有一种数学方法可以确定它时,这似乎是每个帧的过多开销。
编辑:在检查对象与线本身发生碰撞之前,我会首先消除不在线的边界框内的任何对象 - 由最左边的点的x,最顶点的y,最右边的点的x和最底点的y。这会将行冲突检查限制为几个对象。
再次编辑:我的问题似乎仍然不完全清楚,抱歉。一些解决方案可能会起作用,但我正在寻找一种简单的,最好是数学解决方案。当我说“矩形”时,我指的是一个侧面锁定在x和y轴上,而不是一个可旋转的矩形。因此,一条线不是宽度为0的矩形,除非它处于90或-90度(假设屏幕右侧为0度)。
这是我想要找到的内容的直观表示:
答案 0 :(得分:6)
所以,你有一个线段(A-B),我收集线段正在移动,你想知道线段将在什么点碰撞另一个线段(你的船,无论如何)。
在数学上你想要的是检查两条线相交的时间(两条线总是相交,除非平行),然后检查它们相交的点是否在屏幕上。 首先,您需要将线段转换为线方程,如下所示:
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会给你一个交叉点,当然你必须针对所有船的线段测试你的线段,这可能有点耗时,那就是碰撞盒等等。输入图片。
数学全部都在维基百科中,如果您需要更多信息,请查看。
修改强>
附加组件以跟进评论:
与测试你的片段与矩形的所有四个片段碰撞之前相同,你会得到以下三种情况之一:
两次碰撞,使用类似下面的代码检查每个结果段(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));
}
处理碰撞时棘手的问题是找出最小化你必须进行的测试次数的方法。
答案 1 :(得分:1)
y = ((y2 - y1)/(x2 - x1)) * (x - x1) + y1
答案 2 :(得分:0)
我不是数学天赋,但我认为你可以这样做:
从第2点的结果中减去第1点的结果。
关于这一点的好处是,如果第1点大于第2点,你知道还没有碰撞。
或者使用box2d,然后使用b2ContactPoint
答案 3 :(得分:0)
你应该看看分离轴定理。这通常用于多边形,但我认为你可以使它适用于直线和多边形。
我找到了一个简洁的链接,here.