首页 文章

Pygame Sprite旋转不会保持居中

提问于
浏览
1

我已经在这几天敲打了我的脑袋 . 我正在尝试在其中心轴上旋转一个精灵,并且已经引用了之前关于同一问题的帖子:

How do I rotate an image around its center using Pygame?

我正在使用与前一篇文章中描述的完全相同的代码,并且还使用image_clean属性,以便在连续旋转时不扭曲图像 . 当我尝试旋转我的精灵时,图像的中心在两点之间来回振荡 .

def rotate_center(image, angle):
    """rotate a Surface, maintaining position."""
    loc = image.get_rect().center  #rot_image is not defined 
    rot_img = pg.transform.rotate(image, angle)
    print('')
    print('>>> before: ' + str(rot_img.get_rect().center))
    rot_img.get_rect().center = loc
    print('>>> after: ' + str(rot_img.get_rect().center))
    return rot_img

print语句验证该行:

rot_sprite.get_rect().center = loc

似乎没有将 loc 值分配给图像中心 . 输出总是这样:

>>> before: (32, 32)
>>> after: (32, 32)

>>> before: (37, 37)
>>> after: (37, 37)

>>> before: (41, 41)
>>> after: (41, 41)

>>> before: (43, 43)
>>> after: (43, 43)

>>> before: (45, 45)
>>> after: (45, 45)

>>> before: (45, 45)
>>> after: (45, 45)

>>> before: (43, 43)
>>> after: (43, 43)

>>> before: (41, 41)
>>> after: (41, 41)

>>> before: (37, 37)
>>> after: (37, 37)

我总是希望中心位于(32,32)(我相信) . 任何帮助将不胜感激 .

码:

def main():
    pg.init()

# Screen Setup
size = (SCREEN_WIDTH, SCREEN_HEIGHT)
screen = pg.display.set_mode(size)
screen_flags = screen.get_flags()
pg.display.set_caption(GAME_NAME)
done = False
clock = pg.time.Clock()

# SPRITE GROUPS
all_sprites = pg.sprite.Group()
turrets = pg.sprite.Group()

turret = Tower2((SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
turrets.add(turret)
all_sprites.add(turret)

# -------- Main Program Loop -----------
while not done:
    # Process Incoming Events
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_q:
                done = True
            if event.key == pg.K_f:
                if screen_flags & pg.FULLSCREEN == False:
                    screen_flags |= pg.FULLSCREEN
                    pg.display.set_mode(size, screen_flags)
                else:
                    screen_flags ^= pg.FULLSCREEN
                    pg.display.set_mode(size, screen_flags)


    turret.angle += 10
    turret.image = rotate_center(turret.image_clean, turret.angle)


    screen.fill(WHITE)
    all_sprites.draw(screen)
    pg.display.flip()
    clock.tick(15)

pg.quit()


class Tower2(pg.sprite.Sprite):
    def __init__(self, pos, image, tRange, attackSpeed=1):
        super().__init__()
        self.image = image
        self.image_clean = image
        self.rect = self.image.get_rect()
        self.rect.center = pos
        self.range = tRange
        self.attackSpeed = attackSpeed
        self.lastAttack = time.time()
        self.angle = 0

    def __iter__(self):
        return self

    def canAttack(self):
        if time.time() - self.lastAttack > self.attackSpeed:
            return True
        else:
            return False

    def rotate(self):
        pass

    def update(self):
        self.angle += 10
        self.image = pg.transform.rotate(self.image_clean, self.angle)
        self.image.get_rect().center = self.image_clean.get_rect().center



class Turret1(Tower2):
    def __init__(self, pos):    
        TOWER_WIDTH = 64
        TOWER_HEIGHT = 64
        INIT_RANGE = 200
        INIT_RATE = 1
        SPEED = 1
        tower_img = pg.image.load('imgs/test_rotate.png')
        tower_img = pg.transform.scale(tower_img, (TOWER_WIDTH, TOWER_HEIGHT))
        super().__init__(pos, tower_img, INIT_RANGE, SPEED)

2 回答

  • 2

    你也必须传递精灵的矩形,因为它保持精灵的实际位置,然后将中心坐标传递给 .get_rect 或将它们分配给新的矩形 center . 如果您只是调用 .get_rect() ,则会得到一个带有topleft coords(0,0)的矩形 .

    def rotate_center(image, rect, angle):
        """Rotate a Surface, maintaining position."""
        rot_img = pg.transform.rotate(image, angle)
        # Get a new rect and pass the center position of the old
        # rect, so that it rotates around the center.
        rect = rot_img.get_rect(center=rect.center)
        return rot_img, rect  # Return the new rect as well.
    
    
    # In the main while loop.
    turret.angle += 10
    # Also pass the turret's rect which holds the position of the sprite.
    image, rect = rotate_center(turret.image_clean, turret.rect, turret.angle)
    turret.image = image  # Assign the new image.
    turret.rect = rect  # Assign the new rect.
    

    您也可以在精灵的 update 方法中执行此操作:

    import pygame as pg
    
    
    WHITE = pg.Color('white')
    
    class Tower2(pg.sprite.Sprite):
        def __init__(self, pos, tRange=1, attackSpeed=1):
            super().__init__()
            self.image = your_image
            self.image_clean = self.image
            self.rect = self.image.get_rect()
            self.rect.center = pos
            self.angle = 0
    
        def update(self):
            self.angle += 10
            self.image = pg.transform.rotate(self.image_clean, self.angle)
            self.rect = self.image.get_rect(center=self.rect.center)
    
    
    def main():
        pg.init()
    
        SCREEN_WIDTH = 640
        SCREEN_HEIGHT = 480
        size = (SCREEN_WIDTH, SCREEN_HEIGHT)
        screen = pg.display.set_mode(size)
        done = False
        clock = pg.time.Clock()
    
        all_sprites = pg.sprite.Group()
    
        turret = Tower2((SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
        all_sprites.add(turret)
    
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            all_sprites.update()
    
            screen.fill(WHITE)
            all_sprites.draw(screen)
            pg.display.flip()
            clock.tick(15)
    
    main()
    pg.quit()
    
  • 1

    不要一直使用 get_rect() - 它总是创建新的矩形,并且您在这个新矩形中更改位置,而不是原始矩形 . 然后你再次获得新的矩形来显示位置 .

    除了图像不保持位置,你必须得到矩形一次,并用它来保持位置 .

    loc = image.get_rect().center
    
    rot_img = pg.transform.rotate(image, angle)
    
    # get rectangle and keep it
    rot_img_rect = rot_img.get_rect()
    
    # change position in rectangle
    rot_img_rect.center = loc
    
    # display position 
    print('>>> after: ', rot_img_rect.center)
    
    # return image and position in `rot_img_rect`
    return rot_img, rot_img_rect
    

相关问题