我没有标记这个问题已回答。
由于Bounty Time-Limit
参考我目前正在制作的this programming game。
从上面的链接可以看出,我目前正在制作一款用户可编程机器人在竞技场中自主战斗的游戏。
现在,我需要一种方法来检测机器人是否在特定角度检测到另一个机器人(取决于炮塔可能面对的位置):
alt text http://img21.imageshack.us/img21/7839/robotdetectionrg5.jpg
从上图中可以看出,我已经绘制了一种坦克的视角,我现在需要在游戏中模拟,以检查其中的每个点,看看是否有另一个机器人在视野中。
机器人只是在战斗竞技场(另一个画布)上不断翻译的画布。
我知道炮塔的标题(它将面向当前的方式),并且我需要找到它的路径中是否有任何机器人(并且路径应该以'视点'的方式定义,在上面的图像中以红色“三角形”的形式描绘。我希望图像能够使我想要表达的内容更加清晰。
我希望有人可以指导我实现这个问题所涉及的数学。
[UPDATE]
我已经尝试过你告诉我的计算,但它没有正常工作,因为从图像中可以看出,bot1应该无法看到Bot2。这是一个例子:
alt text http://img12.imageshack.us/img12/7416/examplebattle2.png
在上面的场景中,Bot 1正在检查他是否能看到Bot 2.以下是详细信息(根据Waylon Flinn's answer):
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
根据上面的计算,Bot1可以看到Bot2,但从图像中可以看出,这是不可能的,因为它们面向不同的方向。
在上述计算中我做错了什么?
答案 0 :(得分:3)
机器人之间的角度是arctan(x距离,y距离)(大多数平台提供这个2参数arctan为你做角度调整。然后你只需要检查这个角度是否小于某个数字远离当前的标题。
编辑:对于模糊的回答感到抱歉,但这里有一些关于更新的说明:坐标将在笛卡尔系统中,而不是窗口系统。这会导致一些不同的数字
方向:3.3&lt; - 这是不正确的,bot1看起来像是面向4或其他东西。 191度大约是时钟的8:30位置,几乎直接指向坦克2.难怪系统返回“可见”!
方位角:cy为-31(31个单位以下),而不是31个。
通过这些更改,您应该得到正确的结果。
答案 1 :(得分:1)
计算每个机器人相对于当前机器人的相对角度和距离。如果角度在当前航向的某个阈值内且在最大视图范围内,则可以看到它。
唯一棘手的事情是处理角度从2pi弧度变为0的边界情况。
答案 2 :(得分:1)
在你的机器人类中有类似的东西(C#代码):
/// <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;
}
注意:
这假定:
免责声明:未对此进行测试甚至检查以进行编译,并根据需要进行调整。
答案 3 :(得分:1)
在实施类似的事情之后提出了一些建议(很久以前!):
以下假设您正在循环战场上的所有机器人(这不是一个特别好的练习,但可以快速轻松地完成某些工作!)
1)如果机器人在范围内,那么它是否更容易检查,如果它现在可以在FOV内看到,例如
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
}
这确保了它可以对很多FOV检查进行短路,并加快运行模拟的过程。作为一个警告,你可以在这里有一些随机性使它更有趣,这样在一定距离后,看到的机会与机器人的范围成线性比例。
2)This article似乎有FOV计算的东西。
3)作为AI毕业生......你试过神经网络,你可以训练他们识别机器人是否在射程和有效目标。这将否定任何可怕的复杂和复杂的数学!您可以在机器人坐标中有一个多层感知器[1],[2],并且目标会在最后进行协调并接受一个很好的火灾/禁火决定。警告:我觉得有必要告诉你,这种方法不是最容易实现的,并且在出错时会非常令人沮丧。由于这种形式的算法的(simle)非确定性,调试可能是一种痛苦。另外,您需要某种形式的学习,包括Back Propogation(带训练案例)或遗传算法(另一个完美的复杂过程)!鉴于我的选择,我会使用3号,但不是每个人都这样!
答案 4 :(得分:1)
这将告诉您canvas2的中心是否可以被canvas1击中。如果你想考虑canvas2的宽度,它会变得有点复杂。简而言之,您必须进行两次检查,一次针对canvas2的每个相关角落,而不是对中心进行一次检查。
/// 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);
答案 5 :(得分:1)
使用称为点积的矢量数学中的概念可以很容易地实现。
http://en.wikipedia.org/wiki/Dot_product
它可能看起来令人生畏,但并不是那么糟糕。这是处理你的FOV问题最正确的方法,而且无论你是处理2D还是3D(当你知道解决方案是正确的时候),同样的数学运算也是如此。
(注意:如果有任何不清楚的地方,请在评论部分询问,我将填写缺失的链接。)
步骤:
1)你需要两个向量,一个是主坦克的标题向量。你需要的另一个矢量来自所讨论的坦克和主坦克的位置。
对于我们的讨论,我们假设主油箱的航向矢量是(ax,ay),主油箱位置和目标油箱之间的矢量是(bx,by)。例如,如果主油箱位于(20,30)并且目标油箱位于(45,62),则矢量b =(45 - 20,62 - 30)=(25,32)。
再次,为了讨论的目的,让我们假设主坦克的标题向量是(3,4)。
这里的主要目标是找到这两个向量之间的角度,点积可以帮助你实现这一点。
2)点积定义为
a * b = | a || b | COS(角度)
读作(点积)b,因为a和b不是数字,它们是向量。
3)或表达另一种方式(在一些代数操作之后):
angle = acos((a * b)/ | a || b |)
angle是两个向量a和b之间的角度,所以这个信息可以告诉你一个坦克是否可以看到另一个。
| A |是矢量a的大小,根据毕达哥拉斯定理,只是sqrt(ax * ax + ay * ay),同样适用于| b |。
现在问题来了,你怎么找到一个* b(点积b)来找到角度。
4)救援来了。原来,点积也可以表示如下:
a * b = ax * bx + ay * by
所以angle = acos((ax * bx + ay * by)/ | a || b |)
如果角度小于FOV的一半,则可以看到有问题的水箱。否则就不是。
所以使用上面的示例数字:
根据我们的示例数字:
a =(3,4) b =(25,32)
| A | = sqrt(3 * 3 + 4 * 4)
| B | = sqrt(25 * 25 + 32 * 32)
angle = acos((20 * 25 + 30 * 32)/ | a || b |
(在将其与您的FOV进行比较之前,请务必将得到的角度转换为度数或弧度)
答案 6 :(得分:0)
看看你的两个问题,我认为你可以使用提供的数学解决这个问题,然后你必须解决许多其他关于碰撞检测,发射子弹等的问题。这些都是非常重要的解决,特别是如果你的机器人不正方形。我建议查看物理引擎 - 在Codeplex上farseer是一个很好的WPF示例,但这使得它成为比高中开发任务更大的项目。
我获得高分的最佳建议,做一些非常简单的事情,不要提供出色的东西。
答案 7 :(得分:0)
你的炮塔真的有这么宽的射击模式吗?子弹所采取的路径将是一条直线,并且在行进时不会变大。你应该在炮塔的方向上有一个简单的矢量来代表炮塔杀戮区。每个坦克都有一个代表其脆弱区域的边界圆。然后,您可以按照光线跟踪的方式进行操作。一个简单的光线/圆形交叉点。请查看文档Intersection of Linear and Circular Components in 2D的第3部分。
答案 8 :(得分:0)
您的更新问题似乎来自orientation
和azimuth
的不同“零”方向:0 orientation
似乎意味着“直线上升”,但是{{1} 0“直接右”。