pygame,在半径R

时间:2017-10-27 03:17:49

标签: python pygame

我试图沿着半径R从A点到B点绘制一个圆弧。

Player.__draw_fov()中,您可以看到我当前是如何绘制弧线的。然而,当我旋转圆弧时,它会被绘制成超过90度。现在当我进行矢量数学运算以获得fov向量与默认向量(x,0)的角度时,它总是返回值0 <= angle <= 180。所以它适用于前180度到0度。但是对于底部180到360度不起作用。

现在我尝试了各种各样的事情,包括跟踪玩家的角度。从90开始(朝上)(0面向右)。当玩家面对低于0或高于180时,它会改变度数。但似乎没有任何效果。

class Player:

    def __init__(self, distance, fov, color, start, pygame, screen):
        self.distance = distance
        self.fov = fov
        self.color = color
        self.pygame = pygame
        self.screen = screen
        self.left = False
        self.right = False

        self.angularSpeed = 5
        self.speed = 5

        self.angle = 90
        self.origin = start

        unit = 1 / numpy.linalg.norm(numpy.array([0, -10]))

        self.points = numpy.array([
            numpy.array([-3, 3]) + start,
            numpy.array([3, 3]) + start,
            numpy.array([0, -10]) + start,
            self.rotate([0, distance * unit * -10], self.fov / 2) + start,
            self.rotate([0, distance * unit * -10], -self.fov / 2) + start
        ])

    def update(self):
        if self.left: self._left()
        elif self.right: self._right()
        self._draw_body()
        self._draw_fov()

    def _draw_fov(self):
        P1 = self.points[3]
        P2 = self.points[4]
        self.pygame.draw.line(self.screen, self.color, self.origin, P1.tolist())
        self.pygame.draw.line(self.screen, self.color, self.origin, P2.tolist())

        O = numpy.array([10, 0])
        A1 = self.vector_angle(P1-self.origin, O)
        A2 = self.vector_angle(P2-self.origin, O)

        if self.angle >= 135: A2 = -A2
        if self.angle >= 225: A1 = -A1
        if self.angle <=  45: A1 = -A1
        if self.angle >= 315: A2 = -A2

        O_corner = self.origin - numpy.array([self.distance, self.distance])

        if (135 <= self.angle < 225) or
           (0 <= self.angle <= 45) or
           (315 <= self.angle < 360):
            self.pygame.draw.arc(self.screen, self.color, (O_corner, (self.distance * 2, self.distance * 2)), math.radians(A1), math.radians(A2))
        else:
            self.pygame.draw.arc(self.screen, self.color, (O_corner, (self.distance * 2, self.distance * 2)), math.radians(A2 - 90), math.radians(A1 + 90))

    def vector_angle(self, A, B):
        dot = A[0] * B[0] + A[1] * B[1]
        norm = numpy.linalg.norm(A) * numpy.linalg.norm(B)

        return math.degrees(math.acos(dot/norm))

    def _left(self):
        self.angle = (self.angle + self.angularSpeed) % 360
        for point in range(self.points.shape[0]):
            self.points[point] = self.rotate(self.points[point], -self.angularSpeed, self.origin)
        self.directionVector = self.rotate(self.directionVector, -self.angularSpeed)

    def _right(self):
        self.angle = (self.angle - self.angularSpeed) % 360
        for point in range(self.points.shape[0]):
            self.points[point] = self.rotate(self.points[point], self.angularSpeed, self.origin)
        self.directionVector = self.rotate(self.directionVector, self.angularSpeed)

修改 更改并格式化为更惯用(三元比较和%模数,与负数一起使用)。比较&lt;不再需要0和&gt; = 360。

修改

我改进算法以便在转弯时更好地绘制弧线,当你转弯时它似乎是正确的。 然而,随着时间的推移,当玩家不断转动时,弧线会开始不正确地绘制。这似乎是一个我无法看到的累积问题。累积问题在_right()内部,它发生在360 - self.angle,这是用360 + self.angle修复的

enter image description here

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:0)

通过保持角度变量来表示玩家所面对的方向,并使用它来调整两个FOV向量和原始向量([10,0])之间计算的矢量角度,我能够调整角度,使其适应总是正确画出弧线。

这些角度中的每一个都基于自身角度是否超过某些45度点来修改FOV矢量的角度。基本上,当FOV位于圆的下半部分时,这会通知。由于使用矢量来获得角度仅在0到180度之间工作,因此它不考虑180以上的角度,因为这些只是介于0和-180之间的负值,而矢量并不关心。

这些角度仅适用于90度的fov。为了补偿任何fov,我修改了它们如下:

if self.angle >= 180-self.fov/2: A2 = -A2
if self.angle >= 180+self.fov/2: A1 = -A1
if self.angle <=  self.fov/2: A1 = -A1
if self.angle >= 360-self.fov/2: A2 = -A2

# if self.angle >= 135: A2 = -A2 # 90 + 45
# if self.angle >= 225: A1 = -A1 # 180 + 45
# if self.angle <=  45: A1 = -A1 # 45
# if self.angle >= 315: A2 = -A2 # 270 + 45

O_corner = self.origin - numpy.array([self.distance, self.distance])

if (self.angle >= 135 and self.angle < 225) or (self.angle <= 45 and self.angle >= 0) or (self.angle >= 315 and self.angle < 360):
self.pygame.draw.arc(self.screen, self.color, (O_corner, (self.distance*2, self.distance*2)), math.radians(A1), math.radians(A2))
else:
    self.pygame.draw.arc(self.screen, self.color, (O_corner, (self.distance*2, self.distance*2)), math.radians(A2-90), math.radians(A1+90))

我的问题中的代码已更新