如何解决如何制作二维截取函数?
我正在创建一个 Python 程序,其中追逐者在目标之后运行。我有一个移动目标的函数,我正在尝试制作一个函数,根据自身和目标的位置、目标的方向和速度,输出追逐者需要移动的角度以拦截它自身和目标(它们总是以最高速度运行,它们的速度可能不同,也可能不同)。我发现的下图很好地描述了它的样子,但有一个重要的警告:
需要注意的是,如图所示,我使用的是绝对角度系统。 0 弧度是 3 点钟位置,逆时针方向继续到 2pi 弧度。因此,向上和向右是 pi/4,向前是 pi/2,向下和向右是 7pi/4,等等。
但是,在我的游戏中,有时追逐者在目标后面,有时目标向左移动。这些配置打破了公式。要么追逐者朝错误的方向移动,要么存在反正弦或反余弦的域错误。如果你好奇,我的 WIP 函数试图通过使用许多公式来解决这个问题,但仍然不起作用(它以同样的方式失败)在这篇文章的底部。
我的问题是:我如何让它适用于追逐者和目标的所有配置?我见过使用各种技术的解决方案,但它们都以与我相同的方式中断(当配置不是追逐者向右下方移动和目标向右上方移动时,追逐者向错误的方向移动和/或使用反正弦或反余弦引起域错误),或者它们使用相对角度系统。
我认为我使用的绝对角度系统有问题的原因是给定了目标角度,但目标角度与三角形内角度之间的关系根据目标角度是否在0之间而有所不同和 pi/2、pi/2 和 pi、pi 和 3pi/2,或 3pi/2 和 2pi。在我的“PS”中我有一个例子说明我的意思,如果它没有意义。
我的问题很简单:我如何制作这个功能?我做的大部分是正确的,我只需要做一个小的改变吗?我在想这完全错误吗?其他帖子是否与我的代码不同,允许我使用他们的答案(我如何在 python 中使用相对角度)?
感谢任何见解、解决方案或建议!
附言
下面是一个示例,说明为什么我使用的绝对角度测量系统有问题,以及为什么我试图在我的代码中使用许多不同的公式(请参阅我上面链接的图表以获取图表):
我们将 y 轴与连接追踪器和目标的线之间形成的角度称为“角度 Beta”。角度β可以通过获取追逐者和目标在每个方向上的距离来计算——我将这些距离称为deltaY和deltaX——并使用正弦定律。
Beta = arcsin(deltaX/d)
因此,角度 Alpha = pi/2 - targetAngle - Beta
现在,假设我们沿 y 轴翻转图像。突然之间,pi - targetAngle - Beta 什么都不是。在这种配置中,
Alpha = -pi/2 + targetAngle - Beta
公式不同,因为当我们旋转图像时,targetAngle 会发生变化——它有一个绝对引用,而不是相对引用。
我希望对我的问题的解释是清楚的-如果不是,请回复告诉我您不理解的部分,以便我澄清-我也可能是错的!
def chaseRec(self,target):
self.targetxpos = target.xpos
self.targetypos = target.ypos
self.targetspeed = target.speed
self.targetangle = target.currang - m.pi/2
print("target ang:",self.targetangle)
#gets all of the target information
self.deltaY = abs(self.ypos-self.targetypos)
self.deltaX = abs(self.xpos-self.targetxpos)
self.w = m.sqrt((self.deltaY)**2 + (self.deltaX)**2)
self.d = m.asin(self.deltaY/self.w)
self.z = m.pi/2 - self.d + self.targetangle
#Below line gives error
self.x = m.asin((self.targetspeed * m.sin(self.z)) / self.speed)
#Computes the location of (mx,my),the meeting point. Uses this to choose which formula to use to compute self.currang
if self.targetangle >= 0 and self.targetangle <= m.pi/2:
self.mx = self.targetxpos + self.targetspeed*m.sin((m.pi/2)-self.targetangle)
self.my = self.targetypos + self.targetspeed * m.cos((m.pi / 2) - self.targetangle)
elif self.targetangle > m.pi/2 and self.targetangle <= m.pi:
self.mx = self.targetxpos - self.targetspeed * m.sin((3*m.pi / 2) - self.targetangle)
self.my = self.targetypos + self.targetspeed * m.cos((3*m.pi / 2) - self.targetangle)
elif self.targetangle > m.pi and self.targetangle <= 3*m.pi/2:
self.mx = self.targetxpos - self.targetspeed * m.sin((3 * m.pi / 2) - self.targetangle)
self.my = self.targetypos - self.targetspeed * m.cos((3 * m.pi / 2) - self.targetangle)
else:
self.mx = self.targetxpos + self.targetspeed * m.sin((3 * m.pi / 2) - self.targetangle)
self.my = self.targetypos - self.targetspeed * m.cos((3 * m.pi / 2) - self.targetangle)
#Computes chaser angle
if self.mx > self.xpos:
if self.my > self.ypos:
self.currang = -1* self.d + self.x
else:
self.currang = 2*m.pi - self.d + self.x
else:
self.currang = m.pi + self.d - self.x
#moves the defender according to currang
self.xpos += ((self.speed * framelength) / 2) * m.cos(self.currang)
print("Xpos:",self.xpos)
self.ypos += ((self.speed * framelength) / 2) * m.sin(self.currang)
print("Ypos:",self.ypos)
编辑:我几乎已经解决了这个问题,但是当追逐者比目标快时,我的功能就会中断,等等。因此,以下只是部分答案。
我想我只是让我的功能正常工作。我使用了 Jeffery Hantin 对这篇文章的回复中的公式:
2d game : fire at a moving target by predicting intersection of projectile and unit
下面是我的新函数,有兴趣的朋友,附上很多我用来调试的无用的打印语句。该函数考虑了python中角度是绝对的这一事实。我还没有对它进行过广泛的测试,但我还没有能够打破它。当它追不上时,它就向前跑。
def chaseRec(self,target):
self.targetxpos = target.xpos
self.targetypos = target.ypos
self.targetspeed = target.speed
self.targetangle = target.currang
print("target ang:",self.targetangle)
print("Xpos1:",self.xpos)
print("Ypos1:",self.ypos)
self.dX = False
self.dY = False
print('ds: ',self.dX,self.dY)
#gets all of the target information
#Calculates abs(deltaY)
if self.targetangle <= m.pi/2:
self.deltaY = self.targetspeed * m.sin(self.targetangle) # 23 * 1
elif self.targetangle <=m.pi:
self.deltaY = self.targetspeed * m.sin(m.pi-self.targetangle)
self.dX = True
elif self.targetangle <=3*m.pi/2:
self.deltaY = self.targetspeed * m.sin(self.targetangle-m.pi)
#If deltaY,deltaX is actually negative
self.dY = True
self.dX = True
else:
self.deltaY = self.targetspeed * m.sin(self.targetangle - 3*m.pi/2)
self.dY = True
#Calculates abs(deltaX)
self.deltaX = m.sqrt(self.targetspeed**2 - self.deltaY**2)
#Quadratic Parameters
self.a = self.deltaX**2 + self.deltaY**2 - self.speed**2
self.b = 2 * (self.deltaX * (self.targetxpos - self.xpos) + self.deltaY * (self.targetypos - self.ypos))
self.c = (self.targetxpos - self.xpos)**2 + (self.targetypos - self.ypos)**2
self.disc = self.b**2 - (4* self.a * self.c)
print('data:',self.disc,self.a,self.b,self.c)
print('data2:',self.deltaX,self.deltaY)
#Selects root,then finds where to aim
if self.disc < 0:
self.currang = m.pi/2
print('data:',self.c)
print('data2:',self.deltaY)
else:
self.r1 = (-1 *self.b + m.sqrt(self.disc)) / (2 * self.a)
self.r2 = (-1 * self.b - m.sqrt(self.disc)) / (2 * self.a)
print('rs: ',self.r1,self.r2)
if self.r1 < 0 and self.r2 <0:
self.currang = m.pi/2
elif self.r1 <= self.r2:
if self.dX and self.dY:
self.mx = -1 * self.r1 * self.deltaX + self.targetxpos
self.my = -1 * self.r1 * self.deltaY + self.targetypos
elif self.dX:
self.mx = -1 * self.r1 * self.deltaX + self.targetxpos
self.my = self.r1 * self.deltaY + self.targetypos
elif self.dY:
self.mx = self.r1 * self.deltaX + self.targetxpos
self.my = -1 * self.r1 * self.deltaY + self.targetypos
else:
self.mx = self.r1 * self.deltaX + self.targetxpos
self.my = self.r1 * self.deltaY + self.targetypos
else:
if self.dX and self.dY:
self.mx = -1 * self.r2 * self.deltaX + self.targetxpos
self.my = -1 * self.r2 * self.deltaY + self.targetypos
elif self.dX:
self.mx = -1 * self.r2 * self.deltaX + self.targetxpos
self.my = self.r2 * self.deltaY + self.targetypos
elif self.dY:
self.mx = self.r2 * self.deltaX + self.targetxpos
self.my = -1 * self.r2 * self.deltaY + self.targetypos
else:
self.mx = self.r2 * self.deltaX + self.targetxpos
self.my = self.r2 * self.deltaY + self.targetypos
#computes currang
print("meeting point: ",self.mx,self.my)
self.theta = m.atan(abs(self.my - self.ypos) / abs (self.mx - self.xpos))
print('theta: ',self.theta)
if self.mx > self.xpos:
if self.my > self.ypos:
self.currang = self.theta
else:
self.currang = 2 * m.pi - self.theta
else:
if self.my > self.ypos:
self.currang = m.pi - self.theta
else:
self.currang = m.pi + self.theta
print("Chaser ang:",self.currang)
#finds self.currang,while avoiding domain errors
self.xpos += ((self.speed * framelength) / 2) * m.cos(self.currang)
print("Xpos:",self.xpos)
self.ypos += ((self.speed * framelength) / 2) * m.sin(self.currang)
print("Ypos:",self.ypos)
#moves the defender according to currang
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。