在pygame中向鼠标方向射击子弹
Posted
技术标签:
【中文标题】在pygame中向鼠标方向射击子弹【英文标题】:Shooting a bullet in pygame in the direction of mouse 【发布时间】:2020-05-15 12:56:13 【问题描述】:我只是想不通为什么我的子弹不起作用。我做了一个子弹类,它是:
class Bullet:
def __init__(self):
self.x = player.x
self.y = player.y
self.height = 7
self.width = 2
self.bullet = pygame.Surface((self.width, self.height))
self.bullet.fill((255, 255, 255))
现在我在我的游戏类中添加了几个函数,这是新代码:
class Game:
def __init__(self):
self.bullets = []
def shoot_bullet(self):
if self.bullets:
for bullet in self.bullets:
rise = mouse.y - player.y
run = mouse.x - player.x
angle = math.atan2(rise, run)
bullet.x += math.cos(angle)
bullet.y += math.sin(angle)
pygame.transform.rotate(bullet.bullet, -math.degrees(angle))
D.blit(bullet.bullet, (bullet.x, bullet.y))
def generate_bullet(self):
if mouse.is_pressed():
self.bullets.append(Bullet())
我期望代码执行的操作是,每次我按下鼠标按钮时,Bullet()
都会添加到 game.bullets
,然后 game.shoot_bullet
会计算玩家和鼠标之间的角度并相应地射击子弹在鼠标的方向。然而,结果是一团糟,子弹实际上不旋转也不移动。它们被生成并奇怪地移动到屏幕的左侧。不知道是不是我搞砸了,还是我使用的方法完全错误。
【问题讨论】:
这可能是三角函数在不同象限中产生负面结果吗? - teachoo.com/7240/1406/… 鼠标在右上方是否有效? 我打印了 sin 和 cos 值,似乎是这样(看起来 sin 在第二象限是负数)。我该如何解决这个问题?谢谢 右上 sin 为正,cos 为负 使用极坐标怎么样?参考:***.com/questions/6775897/… 【参考方案1】:首先pygame.transform.rotate
不会变换对象本身,而是创建一个新的旋转表面并将其返回。
如果你想向某个方向发射子弹,方向是在子弹发射的那一刻定义的,但它不会连续改变。 子弹发射时,设置子弹的起始位置,计算到鼠标位置的方向向量:
self.pos = (x, y)
mx, my = pygame.mouse.get_pos()
self.dir = (mx - x, my - y)
方向向量不应该取决于到鼠标的距离,但它必须是Unit vector。 通过除以Euclidean distance 来归一化向量
length = math.hypot(*self.dir)
if length == 0.0:
self.dir = (0, -1)
else:
self.dir = (self.dir[0]/length, self.dir[1]/length)
计算矢量的角度并旋转子弹。一般来说,一个向量的角度可以通过atan2(y, x)
来计算。 y 轴需要反转 (atan2(-y, x)
),因为 y 轴通常指向上方,但在 PyGame 坐标系中,y 轴指向下方(参见 How to know the angle between two points?):
angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))
self.bullet = pygame.Surface((7, 2)).convert_alpha()
self.bullet.fill((255, 255, 255))
self.bullet = pygame.transform.rotate(self.bullet, angle)
要更新子弹的位置,只需缩放方向(按速度)并将其添加到子弹的位置:
self.pos = (self.pos[0]+self.dir[0]*self.speed,
self.pos[1]+self.dir[1]*self.speed)
要在正确的位置绘制旋转的子弹,请取旋转子弹的边界矩形并将中心点设置为self.pos
(参见How do I rotate an image around its center using PyGame?):
bullet_rect = self.bullet.get_rect(center = self.pos)
surf.blit(self.bullet, bullet_rect)
另见Shoot bullets towards target or mouse
最小示例: repl.it/@Rabbid76/PyGame-FireBulletInDirectionOfMouse
import pygame
import math
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
class Bullet:
def __init__(self, x, y):
self.pos = (x, y)
mx, my = pygame.mouse.get_pos()
self.dir = (mx - x, my - y)
length = math.hypot(*self.dir)
if length == 0.0:
self.dir = (0, -1)
else:
self.dir = (self.dir[0]/length, self.dir[1]/length)
angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))
self.bullet = pygame.Surface((7, 2)).convert_alpha()
self.bullet.fill((255, 255, 255))
self.bullet = pygame.transform.rotate(self.bullet, angle)
self.speed = 2
def update(self):
self.pos = (self.pos[0]+self.dir[0]*self.speed,
self.pos[1]+self.dir[1]*self.speed)
def draw(self, surf):
bullet_rect = self.bullet.get_rect(center = self.pos)
surf.blit(self.bullet, bullet_rect)
bullets = []
pos = (250, 250)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
bullets.append(Bullet(*pos))
for bullet in bullets[:]:
bullet.update()
if not window.get_rect().collidepoint(bullet.pos):
bullets.remove(bullet)
window.fill(0)
pygame.draw.circle(window, (0, 255, 0), pos, 10)
for bullet in bullets:
bullet.draw(window)
pygame.display.flip()
【讨论】:
以上是关于在pygame中向鼠标方向射击子弹的主要内容,如果未能解决你的问题,请参考以下文章