2009-10-03 43 views
0

如何检测线路上的碰撞,最好是鼠标点击?检测线路上的碰撞

我不使用XNA。我只使用简单的WinForms。而我并没有创造一款游戏。

编辑:我从brone链接实施解决方案,并得到真正奇怪的结果。这是小片段。我做错了什么? Pastebin link

+5

而不是告诉我们你不*使用,你可以告诉我们你*做*使用什么可能是有帮助的。 – Noldorin 2009-10-03 22:46:43

+0

Pastebin对我来说是404--没有理由不能在你的问题中发布你的代码。请记住正确地格式化它。 – 2009-10-05 19:03:53

回答

5

最小距离的点与线之间:

http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/

更多referenece材料在他的一般几何部分:

http://local.wasp.uwa.edu.au/~pbourke/geometry/

+1

+1表示如果你想写游戏就去学习几何学,而不必实际说出它; – 2009-10-03 23:53:29

+0

嗯,我在学校教过射线的参数定义,我明白了,但没有解释我可以在这个问题上应用这些知识。 – mnn 2009-10-04 10:54:42

+0

我在该页面上实现了解决方案,但我在线条和鼠标之间确实存在奇怪的距离,例如-64321左右。代码如下:http://pastebin.com/m3bf3aeac – mnn 2009-10-04 11:23:06

1

如果您能够使用线性代数,那么您需要检测从测试点到线段上最近点的距离。

  • 让AB成为您的线段。
  • 让C成为你的鼠标点。
  • 设D是AB上的点,使得线段CD是最小的。

您想查找CD的长度。由于AB和CD是垂直的,你知道AB的斜率是CD斜率的倒数倒数。你知道C和一个斜率,所以你可以找到CD的一般方程。然后,找到AB和CD的交点,给你点D.

一旦你有了点D,找到CD的长度是微不足道的。如果这个距离小于一定阈值,那么你知道你点击线段你感兴趣的近

0

好了,我也就懒得解释它,因为我不记得这是如何工作的。但是我用C++写成这个......呃...... 1995年。我确信有更多更好的方法可以做到这一点,因为我当时只写了大约两年的代码。无论如何,它被转换为C#:

static bool PointHitSegment(Point[] line, Point hitPoint, int errorMargin) 
{ 
    if (hitPoint.X >= (Math.Max(line[0].X, line[1].X) + errorMargin) || 
     hitPoint.X <= (Math.Min(line[0].X, line[1].X) - errorMargin) || 
     hitPoint.Y >= (Math.Max(line[0].Y, line[1].Y) + errorMargin) || 
     hitPoint.Y <= (Math.Min(line[0].Y, line[1].Y) - errorMargin)) 
     return false; 

    if (line[0].X == line[1].X || line[0].Y == line[1].Y) 
     return true; 

    double y1, y2, x1, x2; 
    double m, b; 
    int ny; 

    if (Math.Abs(line[0].Y - line[1].Y) <= Math.Abs(line[0].X - line[1].X)) 
    { 
     y1 = line[0].Y; 
     y2 = line[1].Y; 
     x1 = line[0].X; 
     x2 = line[1].X; 
    } 
    else 
    { 
     y1 = line[0].X; 
     y2 = line[1].X; 
     x1 = line[0].Y; 
     x2 = line[1].Y; 

     int tmp = hitPoint.Y; 
     hitPoint.Y = hitPoint.X; 
     hitPoint.X = tmp; 
    } 

    m = (y2 - y1)/(x2 - x1); 
    b = y1 - m * x1; 

    ny = (int)((m * ((double)hitPoint.X) + b) + 0.5); 

    if (Math.Abs(hitPoint.Y - ny) > errorMargin) 
     return false; 

    return true; 
}