如何制作二维截距函数?

2024-07-04 07:27:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个python程序,其中一个追踪器跟踪一个目标。我有一个移动目标的函数,我正在尝试做一个函数,输出追逐器需要移动的角度来拦截它,给定自身和目标的位置,目标的方向,自身和目标的速度(它们总是以最高速度运行,它们的速度可能不同,也可能不同)。我发现的下图很好地描述了它的外观,但有一个重要的警告:

enter image description here

需要注意的是,如图所示,我使用的是绝对角度系统。0弧度为3点钟位置,逆时针方向继续为2pi弧度。因此,向上和向右是pi/4,正前方是pi/2,向下和向右是7pi/4,以此类推

然而,在我的游戏中,有时追逐者在目标后面,有时目标向左移动。这些配置打破了公式。追逐器的移动方向错误,或者存在反正弦或反余弦域错误。如果你好奇的话,我的WIP函数试图通过使用许多公式来处理这个问题,但仍然不起作用(它以同样的方式失败),它位于本文的底部

我的问题是:如何使其适用于追逐器和目标的所有配置?我见过使用各种技术的解决方案,但它们要么以与我相同的方式中断(当配置不是追逐器向右下移而目标向右上移时,追逐器向错误方向移动和/或使用反正弦或反正弦引起域错误),要么使用相对角度系统

我认为我使用的绝对角度系统有问题的原因是,给定了目标角度,但是目标角度和三角形内部角度之间的关系不同,这取决于目标角度是在0和pi/2之间,pi/2和pi,pi和3pi/2之间,还是3pi/2和2pi之间。在我的“附言”中,我举了一个例子来说明我的意思,如果它没有意义的话

我的问题很简单:我如何实现这个功能?我做的基本上是对的,我只需要做一点小小的改变吗?我是不是完全错了?其他帖子是否与我的代码有所不同,允许我使用它们的答案(在python中如何使用相对角度)

任何见解、解决方案或建议都将不胜感激


附言

下面是一个示例,说明了我使用的绝对角度测量系统存在问题的原因,以及我在代码中尝试使用许多不同公式的原因(请参阅上面链接的图片以获取图表):

让我们将y轴和连接追逐器和目标的线之间形成的角度称为“角度β”。角度β可以通过测量追逐器和目标在每个方向上的距离来计算,我将这些距离称为deltaY和deltaX,并使用正弦定律

贝塔=Arcin(deltaX/d)<;-d是追逐者和目标之间的距离

因此,角度α=π/2-目标角-β

现在,假设我们将图像沿y轴翻转。突然间,pi-targetAngle-Beta什么都不是。在这种配置中

Alpha=-pi/2+目标角-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)

编辑:我几乎已经解决了这个问题,但当chaser比target快时,我的函数就失效了。因此,以下只是部分答案

我想我刚刚完成了我的功能。我使用了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.disc, self.a, self.b, self.c)
        print('data2:', self.deltaX, 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

Tags: selftarget目标mypi角度printmx

热门问题