首页 > 解决方案 > Pygame以与玩家相同的方式移动绘制的矩形(不是图像),包括旋转

问题描述

我正在尝试为我的星舰创建激光束,该激光束是绘制的矩形而不是图像,我用“wasd”移动星舰并用鼠标瞄准,我创建了一个“激光”类,我已经设法使其瞄准与玩家相同的方向。除了旋转之外,横梁也应该移动以保持附着在船上,但我不明白该怎么做。

class Player:
#inizialize the player
def __init__(self, x, y, player):
    self.x = x
    self.y = y
    self.image = player
    self.is_shooting = False
    self.original_player_image = player
    self.angle = 0

#move the player
def movePlayer(self):
    if key[0]:
        self.x -= 10
    elif key[1]:
        self.x += 10
    if key[2]:
        self.y -= 10
    elif key[3]:
        self.y += 10

    #check borders
    if self.x <= 0:
        self.x = 0
    if self.x + rock_image.get_width() >= display_width:
        self.x = display_width - player_image.get_width()
    if self.y <= 0:
        self.y = 0
    if self.y + player_image.get_height() >= display_height:
        self.y = display_height - player_image.get_height()

#rotate the player where the mouse is aiming
def rotate(self):
    mouse_x, mouse_y = pygame.mouse.get_pos()
    rel_x, rel_y = mouse_x - self.x, mouse_y - self.y
    self.angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 90
    self.image = pygame.transform.rotate(self.original_player_image, int(self.angle))
    self.rect = self.image.get_rect()

#draw the player
def drawPlayer(self):
    screen.blit(self.image, (self.x, self.y))


class Laser:
def __init__(self, player_x, player_y):
    self.x = player_x
    self.y = player_y
    self.original_image = pygame.Surface((5, 150))
    self.original_image.set_colorkey( (0,0,0) )
    self.original_image.fill( (255,0,0) )
    self.copy_image = self.original_image.copy()
    self.copy_image.set_colorkey( (0,0,0) )
    self.rect = self.copy_image.get_rect()
    self.rect.center = self.x + player_image.get_width()//2, self.y - 75
    self.new_image = pygame.Surface((5, 150))

def continueDrawLaser(self):
    if laser_bool:
        screen.blit(self.new_image, self.rect)

def rotate(self):
    mouse_x, mouse_y = pygame.mouse.get_pos()
    rel_x, rel_y = mouse_x - player1.x, mouse_y - player1.y
    angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 85
    vel_x = math.cos(angle)
    vel_y = math.sin(angle)
    self.new_image = pygame.transform.rotate(self.original_image, angle)
    self.rect = self.new_image.get_rect()
    self.rect.center = player1.x + vel_x, player1.y + vel_y

第一个是玩家类(星舰)第二个是激光类(激光束)

这就是我得到的:

在此处输入图像描述

如果您需要我在这里发布的整个代码:

https://pastebin.com/jnYifErX

为了让你测试代码我把所有没用的东西都去掉了,只给玩家留下了激光束,所以你只需要下载宇宙飞船来测试代码,这里是缩短的代码:

https://pastebin.com/VTbuCZY4

飞船下载链接:

https://www.flaticon.com/free-icon/spaceship_1114780?term=space%20ship&page=1&position=57

标签: pythonpygame

解决方案


如何使用 Pygame 围绕其中心旋转图像的答案中?提出了一种围绕枢轴旋转图像的算法。

使用算法实现rotate类中的功能Laser,取决于方向和位置player1

class Laser:
    # [...]

    def rotate(self):

        # get rectangle of player and laser, as if the angle would be 0 
        player_rect = player1.original_player_image.get_rect(topleft = (player1.x, player1.y))
        laser_rect  = self.original_image.get_rect(midbottom = player_rect.midtop)
        self.angle  = player1.angle
        pos         = player_rect.center
        pivotPos    = [pos[0] - laser_rect.x, pos[1] - laser_rect.y]   

        # calcaulate the axis aligned bounding box of the rotated image
        w, h       = self.original_image.get_size()
        box        = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
        box_rotate = [p.rotate(self.angle) for p in box]
        min_box    = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])
        max_box    = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])

        # calculate the translation of the pivot 
        pivot        = pygame.math.Vector2(pivotPos[0], -pivotPos[1])
        pivot_rotate = pivot.rotate(self.angle)
        pivot_move   = pivot_rotate - pivot

        # calculate the upper left origin of the rotated image
        origin = (pos[0] - pivot[0] + min_box[0] - pivot_move[0], pos[1] + pivot[1] - max_box[1] + pivot_move[1])

        # get a rotated image
        self.new_image = pygame.transform.rotate(self.original_image, self.angle)

        # get new rectangle
        self.rect = self.new_image.get_rect(topleft = (round(origin[0]), round(origin[1])))

更进一步,您必须确保正确放置旋转的宇宙飞船。计算未旋转的宇宙飞船的中心并将该中心应用于旋转的宇宙飞船。使用.rect飞船的属性来blit

class Player:
    # [...]

    # rotate the player where the mouse is aiming
    def rotate(self):
        mouse_x, mouse_y = pygame.mouse.get_pos()
        rel_x, rel_y = mouse_x - self.x, mouse_y - self.y
        self.angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 90
        self.image = pygame.transform.rotate(self.original_player_image, int(self.angle))
        orig_center = self.original_player_image.get_rect(topleft = (self.x, self.y)).center
        self.rect = self.image.get_rect(center = orig_center)

    # draw the player
    def drawPlayer(self):
        screen.blit(self.image, self.rect.topleft)     

当然,每次玩家旋转时,激光也必须旋转:

player1.movePlayer()
player1.rotate()
laser1.rotate()


推荐阅读