在 pygame 中如何将枪管指向鼠标?

How do you point the barrel towards mouse in pygame?

我已经解决了 post 中指出的问题,但现在我对如何将灰色矩形(桶)指向我的鼠标感到困惑。有人可以帮忙吗?谢谢!

这是我的代码:

import pygame
import math

pygame.init()

screen = pygame.display.set_mode((400, 400))

pygame.display.set_caption("diep.io")

screen.fill((255,255,255))

auto_shoot = False

class Bullet:
  def __init__(self, x_move, y_move, x_loc, y_loc):
    self.image = pygame.image.load("C:\Users\ender\OneDrive\Documents\repos\Bullet.png")
    self.x_move = x_move
    self.y_move = y_move
    self.x_loc = x_loc
    self.y_loc = y_loc
    self.bullet_rect = self.image.get_rect()
  
  def update(self):
    self.x_loc += self.x_move
    self.y_loc += self.y_move   
    self.bullet_rect.center = round(self.x_loc), round(self.y_loc)

    rect = screen.blit(self.image, self.bullet_rect)
    if not screen.get_rect().contains(rect):
      bullets.remove(self)

    if self.x_loc > 400 or self.y_loc > 400:
      bullets.remove(self)

bullet = None
bullets = []

while True:
  screen.fill((255, 255, 255))
  pygame.draw.rect(screen, (100, 100, 100), (205, 193, 25, 15)) # This is the rectangle I want to point at my mouse
  pygame.draw.circle(screen, (82, 219, 255), (200, 200), 15)
  for event in pygame.event.get():
    if event.type == pygame.MOUSEBUTTONUP:
      x = pygame.mouse.get_pos()[0] - 200
      y = pygame.mouse.get_pos()[1] - 200
      pythag = float(math.sqrt(x**2 + y**2))
      bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
  for bullet in bullets:
    bullet.update()
  pygame.display.update()
  pygame.time.delay(10)

注意:这与其他问题不同,因为我试图将一个矩形指向鼠标,而其他 posts 将图像指向鼠标。那不是我想做的。其次,pygame 个矩形是由它们的左下角定义的,所以这使事情更加复杂。

子弹的旋转见 and
计算方向向量的角度 grees(math.atan2(-y_move, x_move)) 并旋转子弹图像:

class Bullet:
    def __init__(self, x_move, y_move, x_loc, y_loc):
        self.image = pygame.image.load("C:\Users\ender\OneDrive\Documents\repos\Bullet.png")
        self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))

旋转矩形有点棘手。在 pygame.Surface:

上画大炮
cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)

参见 How do I rotate an image around its center using PyGame?。 写一个函数来旋转 blit 一个 Surface:

def blitRotateCenter(surf, image, center, angle):
    rotated_image = pygame.transform.rotate(image, angle)
    new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
    surf.blit(rotated_image, new_rect)

使用应用程序循环中的函数绘制大炮:

while True:
    # [...]
    
    x = pygame.mouse.get_pos()[0] - 200
    y = pygame.mouse.get_pos()[1] - 200
    angle = math.degrees(math.atan2(-y, x)) 
    blitRotateCenter(screen, cannon, (200, 200), angle)
    
    # [...]

另见 and


完整示例:

import pygame
import math

pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("diep.io")
screen.fill((255,255,255))
clock = pygame.time.Clock()

class Bullet:
    def __init__(self, x_move, y_move, x_loc, y_loc):
        #self.image = pygame.image.load("C:\Users\ender\OneDrive\Documents\repos\Bullet.png")
        self.image = pygame.Surface((20, 5), pygame.SRCALPHA)
        self.image.fill((255, 0, 0))
        self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))
        self.x_move = x_move
        self.y_move = y_move
        self.x_loc = x_loc
        self.y_loc = y_loc
        self.bullet_rect = self.image.get_rect()
    
    def update(self):
        self.x_loc += self.x_move
        self.y_loc += self.y_move   
        self.bullet_rect.center = round(self.x_loc), round(self.y_loc)
        rect = screen.blit(self.image, self.bullet_rect)
        if not screen.get_rect().contains(rect):
            bullets.remove(self)
        if self.x_loc > 400 or self.y_loc > 400:
            bullets.remove(self)

cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)

def blitRotateCenter(surf, image, center, angle):
    rotated_image = pygame.transform.rotate(image, angle)
    new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
    surf.blit(rotated_image, new_rect)

bullet = None
bullets = []
auto_shoot = False
run = True
while run:
    x = pygame.mouse.get_pos()[0] - 200
    y = pygame.mouse.get_pos()[1] - 200
    angle = math.degrees(math.atan2(-y, x))  
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONUP:
            pythag = float(math.sqrt(x**2 + y**2))
            bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
    
    screen.fill((255, 255, 255))
    for bullet in bullets:
        bullet.update()
    blitRotateCenter(screen, cannon, (200, 200), angle)
    pygame.display.update()
    clock.tick(100)

pygame.quit()
exit()