我试图沿着半径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修复的
答案 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))
我的问题中的代码已更新