WPF:沿路径查找元素

WPF:沿路径查找元素,wpf,math,2d,Wpf,Math,2d,我还没有标记这个问题的答案。 由于赏金时间限制,当前接受的答案自动被接受 关于我目前正在建设的 从上面的链接可以看出,我目前正在制作一款游戏,用户可编程机器人在竞技场中自主作战 现在,我需要一种方法来检测一个机器人是否以特定角度检测到另一个机器人(取决于炮塔可能面对的位置): 从上图中可以看到,我画了一个坦克的视角,我现在需要在游戏中模拟它,以检查其中的每个点,看看是否有另一个机器人在视野中 机器人只是不断在战场上转换的画布(另一个画布) 我知道炮塔的方向(它当前面对的方向),因此,我需要

我还没有标记这个问题的答案。
由于赏金时间限制,当前接受的答案自动被接受


关于我目前正在建设的

从上面的链接可以看出,我目前正在制作一款游戏,用户可编程机器人在竞技场中自主作战


现在,我需要一种方法来检测一个机器人是否以特定角度检测到另一个机器人(取决于炮塔可能面对的位置):

从上图中可以看到,我画了一个坦克的视角,我现在需要在游戏中模拟它,以检查其中的每个点,看看是否有另一个机器人在视野中

机器人只是不断在战场上转换的画布(另一个画布)

我知道炮塔的方向(它当前面对的方向),因此,我需要找到它的路径中是否有机器人(路径应该以“视点”的方式定义,如上图中红色“三角形”的形式所示。我希望这张图像能让我想表达的内容更加清晰

我希望有人能指导我解决这个问题涉及到什么数学


[更新]

我尝试了您告诉我的计算,但它无法正常工作,因为从图像中可以看到,bot1应该无法看到Bot2。以下是一个示例:

在上述场景中,Bot 1正在检查是否可以看到Bot 2。以下是详细信息(根据):

视角=0.69813170079773179//弧度(40度)
方向=3.3//Bot1当前航向(191度)
x1=518//两个1的中心X
y1=277//两个1的中心Y
x2=276//2号底部的中心X
y2=308//2的中心Y
cx=x2-x1=276-518=-242
cy=y2-y1=308-277=31
方位角=数学Atan2(cy,cx)=3.0141873380511295
canHit=(方位角<方位角+视角/2)和&(方位角>方位角-视角/2)
= (3.0141873380511295 < 3.3 + 0.349065850398865895) && (3.0141873380511295 > 3.3 - 0.349065850398865895)
=正确
根据上述计算,Bot1可以看到Bot2,但正如您从图像中看到的,这是不可能的,因为它们面对不同的方向


我在上面的计算中做错了什么?

机器人之间的角度是arctan(x距离,y距离)(大多数平台都提供这个2参数arctan,可以为您进行角度调整。然后您只需检查这个角度是否小于当前航向的某个数字


编辑2020:以下是基于问题中更新的示例代码和现已删除的imageshack图像的更完整分析

  • Atan2:查找两点之间的角度所需的关键函数是
    Atan2
    。该函数获取向量的Y坐标和X坐标,并返回该向量与正X轴之间的角度。该值将始终被包装为介于-Pi和Pi之间

  • 航向与方向:
    atan2
    ,通常所有的数学函数都在“数学标准坐标系”中工作,这意味着“0”的角度对应于正东方向,角度逆时针增加。因此,
    atan2(1,0)给出的“数学角度”为Pi/2
    表示与点(x=0,y=1)相匹配的“从正东逆时针90度”方向。“航向”是一种导航概念,表示方向与正北成顺时针角

    • 分析:在现已删除的imageshack图像中,191度的“航向”对应于西南方向。这实际上是一个-101度或-1.76的三角“方向”。因此,更新代码中的第一个问题是将“航向”和“方向”合并。您可以通过
      方向度=90-航向度
      方向弧度=Math.PI/2-航向弧度
      从前者获得后者,或者您可以在数学坐标系而不是航海航向坐标系中指定输入方向
  • 检查角度是否位于其他两个向量之间:检查向量是否位于其他两个向量之间并不像检查数字角度值是否介于两者之间那么简单,因为角度在Pi/-Pi处缠绕

    • 分析:在您的示例中,方向为3.3,视图的右边缘为方向2.95,视图的左边缘为3.65。计算出的方位角为3.0141873380511295,这恰好是正确的(它介于两者之间)。但是,对于像-3这样的方位角值,这将失败,该值应计算为“命中”。有关解决方案,请参阅

  • 计算每个机器人相对于当前机器人的相对角度和距离。如果角度在当前航向的某个阈值内且在最大视图范围内,则可以看到它


    唯一棘手的事情是处理角度从2pi弧度变为0的边界情况。

    看看你的两个问题,我认为你可以使用提供的数学解决这个问题,然后你必须解决碰撞检测、发射子弹等许多其他问题。这些问题很难解决,特别是如果你的机器人不是方形的。我建议看看物理引擎——在codeplex上是一个很好的WPF例子,但这使它成为一个比高中开发任务更大的项目


    我得到的关于高分的最好建议是,做一些简单的事情,做得非常好,不要做一些精彩的事情。

    你们的炮塔真的有那个么宽的射击模式吗?子弹的路径是一条直线,并且不会随着它的移动而变大。你们应该有一个简单的向量,指向炮塔的旋转方向
    angleOfSight = 0.69813170079773179 //in radians (40 degrees)
    orientation = 3.3 //Bot1's current heading (191 degrees)
    
    x1 = 518 //Bot1's Center X
    y1 = 277 //Bot1's Center Y
    
    x2 = 276 //Bot2's Center X
    y2 = 308 //Bot2's Center Y
    
    cx = x2 - x1 = 276 - 518 = -242
    cy = y2 - y1 = 308 - 277 =  31
    
    azimuth = Math.Atan2(cy, cx) = 3.0141873380511295
    
    canHit = (azimuth < orientation + angleOfSight/2) && (azimuth > orientation - angleOfSight/2)
           = (3.0141873380511295 < 3.3 + 0.349065850398865895) && (3.0141873380511295 > 3.3 - 0.349065850398865895)
           = true
    
    /// <summary>
    /// Check to see if another bot is visible from this bot's point of view.
    /// </summary>
    /// <param name="other">The other bot to look for.</param>
    /// <returns>True iff <paramref name="other"/> is visible for this bot with the current turret angle.</returns>
    private bool Sees(Bot other)
    {
        // Get the actual angle of the tangent between the bots.
        var actualAngle = Math.Atan2(this.X - other.X, this.Y - other.Y) * 180/Math.PI + 360;
    
        // Compare that angle to a the turret angle +/- the field of vision.
        var minVisibleAngle = (actualAngle - (FOV_ANGLE / 2) + 360);
        var maxVisibleAngle = (actualAngle + (FOV_ANGLE / 2) + 360); 
        if (this.TurretAngle >= minVisibleAngle && this.TurretAngle <= maxVisibleAngle)
        {
            return true;
        }
        return false;
    }
    
    int range = Math.sqrt( Math.abs(my.Location.X - bots.Location.X)^2 + 
                Math.abs(my.Location.Y - bots.Location.Y)^2 );
    
    if (range < maxRange)
    {
        // check for FOV
    }
    
    /// assumming canvas1 is firing on canvas2
    
    // positions of canvas1 and canvas2, respectively
    // (you're probably tracking these in your Tank objects)
    int x1, y1, x2, y2;
    
    // orientation of canvas1 (angle)
    // (you're probably tracking this in your Tank objects, too)
    double orientation;
    // angle available for firing
    // (ditto, Tank object)
    double angleOfSight;
    
    // vector from canvas1 to canvas2
    int cx, cy;
    // angle of vector between canvas1 and canvas2
    double azimuth;
    // can canvas1 hit the center of canvas2?
    bool canHit;
    
    // find the vector from canvas1 to canvas2
    cx = x2 - x1;
    cy = y2 - y1;
    
    // calculate the angle of the vector
    azimuth = Math.Atan2(cy, cx);
    // correct for Atan range (-pi, pi)
    if(azimuth < 0) azimuth += 2*Math.PI;
    
    // determine if canvas1 can hit canvas2
    // can eliminate the and (&&) with Math.Abs but this seems more instructive
    canHit = (azimuth < orientation + angleOfSight) &&
        (azimuth > orientation - angleOfSight);