嘿,我刚开始制作游戏和编程,我试图在Pygame做一个小游戏,包括一个家伙射击子弹和东西。但是,我无法让射击机制正确。我有这样的代码
class Projectile():
def __init__(self, surface, color, start_pos, end_pos, move_speed):
super().__init__()
# Shooter and target positions
self.start_pos = start_pos
self.end_pos = end_pos
# Trigonometry stuffs and like
self.dx = self.end_pos[0] - self.start_pos[0]
self.dy = self.end_pos[1] - self.start_pos[1]
self.rads = atan2(-self.dy,self.dx)
self.rads %= 2*pi
self.degs = degrees(self.rads)
# More stuff I dont understand but it works nearly well.
self.quarter = self.get_quarter(self.degs)
# Change the way rel_x and rel_y are calculated so stuff works fair enough
if self.quarter == 1:
self.rel_x = -self.end_pos[0] + self.start_pos[0]
self.rel_y = -self.end_pos[1] + self.start_pos[1]
elif self.quarter == 2:
self.rel_x = self.end_pos[0] - self.start_pos[0]
self.rel_y = -self.end_pos[1] + self.start_pos[1]
elif self.quarter == 3:
self.rel_x = -self.end_pos[0] + self.start_pos[0]
self.rel_y = self.end_pos[1] - self.start_pos[1]
elif self.quarter == 4:
self.rel_x = self.end_pos[0] - self.start_pos[0]
self.rel_y = self.end_pos[1] - self.start_pos[1]
self.d = (self.rel_x**2 + self.rel_y**2)**0.5
self.angle_x = ((self.rel_x * cos(self.rads)) / self.d) * move_speed
self.angle_y = ((self.rel_y * -sin(self.rads)) / self.d) * move_speed
def move(self):
self.leftover_x += self.angle_x
self.leftover_y += self.angle_y
self.rect.x += int(self.leftover_x)
self.rect.y += int(self.leftover_y)
self.leftover_x = (self.leftover_x % 1)
self.leftover_y = (self.leftover_y % 1)
Move是这样编写的,因为Pygame不允许你移动像素的1.337,所以我将东西移动1,然后保存.337,当保存的数字结尾超过1时,它们也会被添加
的子弹使用数字我标记了在init中的if语句中使用的屏幕四分之一。
你可以看到,有点不起作用。我希望子弹制作一个圆圈。我该怎么办。
我会承认,我不知道三角学。我还没在学校学习,一年就会有。因此,我希望有人尽可能简单地向我解释。并告诉我一个更好的方法来实现这一目标,而不是使用这个季度的东西。
答案 0 :(得分:2)
恭喜!你已经为自己发现了sin()和cos()。
拉出一张纸并标记两个点:一个用于光标位置(=目标),另一个用于子弹的当前(起始?)位置。
现在在它们之间画一条线。该行的长度是你的代码的.d(对于距离,我认为)。
然后从其中一个点绘制一条水平线,足够远,使其正好在另一个点的上方或下方。这个长度是你的rel_x(在微积分中你称之为“dx”)。
然后绘制垂直线以完成一个三角形 - 该长度是你的rel_y(或“dy”)。
我不确定为什么你需要你称之为angle_x和angle_y的变量。一旦射击,角度总是相同的,就像一颗子弹(除非目标正在移动,你正在飞行追击过程,就像一个寻的导弹;做一个“纯粹的追求”你只需重新计算每回合的路线,所以它总是指向目标在那个时间的位置)。
接下来需要的是移动距离。那将是d的一部分。如果您的速度大于d,则覆盖所有d并到达;否则你只能覆盖d的一小部分。所以你需要这样的东西:
if(speed> d):fraction_of_d = 1 else:fraction_of_d = speed / d
现在您需要注意的是,如果您要前往目标的1 / n,您还将覆盖x和y距离的1 / n(更长时间地凝视纸张)如果你没有看到这一点)。
但是你已经有了x和y的总距离(rel_x和rel_y)。所以你只需将每个乘以fraction_of_d,然后告诉你沿着那个方向移动多远。然后按这些金额更新项目符号的位置。
你将在trig中学习sin()只是“对立”(三角形的垂直边)的长度除以斜边(d)的长度。 cos()只是“相邻”(水平面)的长度除以斜边的长度。所以你已经有效地计算了正弦和余弦。
希望更清楚。
-Steve
答案 1 :(得分:1)
好。我自己找到了解决方案。子弹仍然有点不完全与第2和第3季的光标不同,但它会形成一个圆圈。
事实证明,我有sin()和cos()函数的事实存在问题。我刚删除它们以使代码成为
self.angle_x = (self.rel_x / self.d) * move_speed
self.angle_y = (self.rel_y / self.d) * move_speed
现在可以使用了。我也可以删除这个季度检测的东西,它现在没有它。最终代码如下所示:
class Projectile():
def __init__(self, surface, color, start_pos, end_pos, move_speed):
super().__init__()
# Shooter and target positions
self.start_pos = start_pos
self.end_pos = end_pos
# Trigonometry stuffs and like
# NOW REDUNDANT
# self.dx = self.end_pos[0] - self.start_pos[0]
# self.dy = self.end_pos[1] - self.start_pos[1]
# self.rads = atan2(-self.dy,self.dx)
# self.rads %= 2*pi
# self.degs = degrees(self.rads)
# More stuff I dont understand but it works nearly well.
# self.quarter = self.get_quarter(self.degs)
self.rel_x = self.end_pos[0] - self.start_pos[0]
self.rel_y = self.end_pos[1] - self.start_pos[1]
self.d = (self.rel_x**2 + self.rel_y**2)**0.5
self.angle_x = (self.rel_x / self.d) * move_speed
self.angle_y = (self.rel_y) / self.d) * move_speed
尽管如此,有人应该发布一个更好的答案,这个答案也解决了子弹不能完全转到鼠标点击位置的问题。