Pygame精灵在旋转后移动后会跳动

3

我正在创建一个基础的坦克游戏,目前正在开发坦克的炮管部分。我已经成功让炮管围绕一个轴旋转,并且通过按下“a”和“d”键使其移动,但有时候当炮管旋转后再移动时,它会出现向右移动的情况。这是代码:

class tankGun(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = tankGunImage
        self.rect = self.image.get_rect()
        self.x = 400
        self.xx = 410
        self.y = 400
        self.rect.x = self.x
        self.rect.y = self.y
        self.angle = 0
        self.original = self.image
        tankGunList.add(self)
        tankGunList.draw(gameDisplay)

def rotate(self, chk):
    test = False
    if chk == 1:
        self.angle += 1
    elif chk == 2:
        self.angle -= 1
    if self.angle > 0 and self.angle < 180:
        test = True
    else:
        if chk == 1:
            self.angle = 180
        elif chk == 2:
            self.angle = 0
    if test == True:
        self.image = pygame.transform.rotate(self.original, self.angle)
        tankGunList.clear(gameDisplay, background)
        tankGunList.draw(gameDisplay)
        self.rect = self.image.get_rect(center = self.rect.center)

def move(self, chk):
    self.x += chk
    self.xx = self.x + 10
    self.rect.x = self.x
    tankGunList.clear(gameDisplay, background)
    tankGunList.draw(gameDisplay)        

(注:chk作为移动的+1或-1,旋转的1或2发送。这只是检测按下哪个键的一种方法。)

顺便提一下:self.x 的值始终与 self.rect.x 相同,因此您只需使用 self.rect.x 并删除 self.x - self.y 也是如此。 - furas
看起来你在三个地方使用了 tankGunList.draw(gameDisplay)。你应该只在主循环中绘制一次。 - furas
2个回答

1
问题出现的原因是旋转后没有更新self.x位置。当你旋转一个图像时,它的边界框大小会改变,所以新矩形的x self.rect.x位置也会改变。然而,self.x属性仍然保持不变,当你下一次移动坦克时,你再次同步self.xself.rect.x,它就会跳动。
要解决这个问题,只需在旋转后更新self.x即可:
if turn == True:
    self.image = pg.transform.rotate(self.original, self.angle)
    self.rect = self.image.get_rect(center=self.rect.center)
    self.x = self.rect.x

我更喜欢使用xy属性作为中心坐标,然后设置self.rect.center = (self.x, self.y),这样在旋转后就不必更新self.x了。
import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
tankGunImage = pg.Surface((30, 50), pg.SRCALPHA)
tankGunImage.fill((70, 200, 30))


class tankGun(pg.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = tankGunImage
        self.rect = self.image.get_rect()
        self.x = 300  # Center x.
        self.xx = 310
        self.y = 200  # Center y.
        # Set the center attributes.
        self.rect.centerx = self.x
        self.rect.centery = self.y
        self.angle = 0
        self.original = self.image

    def rotate(self, chk):
        turn = False
        if chk == 1:
            self.angle += 4
        elif chk == 2:
            self.angle -= 4
        if self.angle > 0 and self.angle < 180:
            turn = True
        else:
            if chk == 1:
                self.angle = 180
            elif chk == 2:
                self.angle = 0

        if turn == True:
            self.image = pg.transform.rotate(self.original, self.angle)
            self.rect = self.image.get_rect(center=self.rect.center)
            # No need to update the `self.x` now, since the center stays the same.

    def move(self, chk):
        self.x += chk
        self.xx = self.x + 10
        self.rect.center = (self.x, self.y)


def main():
    clock = pg.time.Clock()
    color = pg.Color(30, 30, 30)
    all_sprites = pg.sprite.Group()
    tank = tankGun()
    all_sprites.add(tank)

    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        keys = pg.key.get_pressed()
        if keys[pg.K_a]:
            tank.rotate(1)
        if keys[pg.K_d]:
            tank.rotate(2)
        if keys[pg.K_j]:
            tank.move(-4)
        if keys[pg.K_l]:
            tank.move(4)
        all_sprites.update()

        screen.fill(color)
        all_sprites.draw(screen)
        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    main()
    pg.quit()

0

我不知道你为什么有问题 - 我无法运行它以查看问题。

但是我会展示我会做出的更改。也许这会有所帮助。

首先,我会使用更易读的名称而不是 chk - 例如 directionstep

class tankGun(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()

        self.original = tankGunImage
        self.image = self.original

        self.rect = self.image.get_rect()
        self.rect.x = 400
        self.rect.y = 400

        self.xx = self.rect.x + 10

        self.angle = 0

        tankGunList.add(self)

    def rotate(self, direction):
        rotate_image = False

        if direction == 1:
            if self.angle < 180
                self.angle += 1
                rotate_image = True
        elif direction == 2:
            if self.angle > 0
                self.angle -= 1
                rotate_image = True

        if rotate_image == True:
            self.image = pygame.transform.rotate(self.original, self.angle)
            self.rect = self.image.get_rect(center=self.rect.center)

    def move(self, step):
        self.rect.x += step
        self.xx = self.rect.x + 10

# --- in mainloop ---

tankGunList.clear(gameDisplay, background)
tankGunList.draw(gameDisplay)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接