【问题标题】:Why does flipping my sprites cause it to move weird为什么翻转我的精灵会导致它移动奇怪
【发布时间】:2022-01-14 10:09:05
【问题描述】:

我正在制作一个 pyGame 游戏,我决定将它水平翻转,而不是让 sprite 出现在两边改变每一帧,无论如何我可以控制图像中心。 作为记录,函数 draw 是从 Main.py 调用的

这是我的播放器类:

class Player(pygame.sprite.Sprite):
    def __init__(self, char_type, x, y, scale, speed):
        pygame.sprite.Sprite.__init__(self)
        self.alive = True
        self.char_type = char_type
        self.speed = speed
        self.direction = 1
        self.vel_y = 0
        self.jump = False
        self.in_air = True
        self.flip = False
        self.attack = False
        self.moving_left = False
        self.moving_right = False
        self.animation_list = []
        self.frame_index = 0
        self.action = 0
        self.update_time = pygame.time.get_ticks()
        
        #load all images for the players
        animation_types = ['stand', 'walk', 'jump', 'attack1', 'attack2', 'attack3']
        for animation in animation_types:
            #reset temporary list of images
            temp_list = []
            #count number of files in the folder
            num_of_frames = len(os.listdir(f'sprites/{self.char_type}/{animation}'))
            for i in range(num_of_frames):
                img = pygame.image.load(f'sprites/{self.char_type}/{animation}/{i}.png')
                img = pygame.transform.scale(img, (int(img.get_width() * scale), int(img.get_height() * scale)))
                temp_list.append(img)
            self.animation_list.append(temp_list)

        self.image = self.animation_list[self.action][self.frame_index]
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)


    def move(self, GRAVITY):
        #reset movement variables
        dx = 0
        dy = 0

        #assign movement variables if moving left or right
        if self.moving_left:
            dx = -self.speed
            self.flip = True
            self.direction = -1
        if self.moving_right:
            dx = self.speed
            self.flip = False
            self.direction = 1

        # if self.attack:
            # self.play_sound("attack")

        #jump
        if self.jump == True and self.in_air == False:
            self.vel_y = -11
            self.jump = False
            self.in_air = True

        # if self.attack == True:
        #     self.attack = False

        #apply gravity
        self.vel_y += GRAVITY
        if self.vel_y > 10:
            self.vel_y
        dy += self.vel_y

        #check collision with floor
        if self.rect.bottom + dy > 450:
            dy = 450 - self.rect.bottom
            self.in_air = False

        #update rectangle position
        self.rect.x += dx
        self.rect.y += dy


    def update_animation(self):
        #update animation
        if self.action == 0:
            animation_cooldown = 800
        elif self.action == 1:
            animation_cooldown = 170
        elif self.action == 2:
            animation_cooldown = 50
        elif self.action == 3:
            self.moving_left = False
            self.moving_right = False
            animation_cooldown = 250
            # self.action = random.randint(3, 5)
        #update image depending on current frame
        self.image = self.animation_list[self.action][self.frame_index]
        #check if enough time has passed since the last update
        if pygame.time.get_ticks() - self.update_time > animation_cooldown:
            self.update_time = pygame.time.get_ticks()
            self.frame_index += 1
        #if the animation has run out the reset back to the start
        if self.frame_index >= len(self.animation_list[self.action]):
            if self.action == 3:
                self.attack = False
            self.frame_index = 0



    def update_action(self, new_action):
        #check if the new action is different to the previous one
        if new_action != self.action:
            self.action = new_action
            #update the animation settings
            self.frame_index = 0
            self.update_time = pygame.time.get_ticks()

    
    def play_sound(self, sound):
        soundObj = pygame.mixer.Sound('sprites/sounds/player/' + sound + '.mp3')
        soundObj.play()
        




    def draw(self, screen):
        screen.blit(pygame.transform.flip(self.image, self.flip, False), self.rect)

【问题讨论】:

  • 这个绘制函数是从哪里调用的?请提供minimal reproducible example
  • 我更新了,函数draw正在从main调用,现在我也发布了播放器类的完整代码

标签: python object pygame sprite flip


【解决方案1】:

您需要反转翻转面的列表。 reverse名单到位:

temp_list.reverse()            
self.animation_list.append(temp_list)

或附加一个reversed 列表:

self.animation_list.append(reversed(temp_list))

如果您的图片尺寸不同,您需要创建相同尺寸的图片。找到最大图像的大小。为每个图像创建一个pygame.Surface 并在Surface 上创建一个blit 图像:

for animation in animation_types:

    max_image_size = [0, 0]       
    temp_list = []
    num_of_frames = len(os.listdir(f'sprites/{self.char_type}/{animation}'))
    for i in range(num_of_frames):
        img = pygame.image.load(f'sprites/{self.char_type}/{animation}/{i}.png')
        temp_list.append(img)
        max_image_size[0] = max(max_image_size[0], img.get_width())
        max_image_size[0] = max(max_image_size[1], img.get_height())
        
    for i in range(num_of_frames):
        img = pygame.Surface(max_image_size, pygame.SRCALPHA)        
        img.blit(temp_list[i], (0, 0))
        temp_list[i] = pygame.transform.scale(img, (int(img.get_width() * scale), int(img.get_height() * scale)))
        
    self.animation_list.append(temp_list)

【讨论】:

  • 抱歉,误会了,但我的帧顺序没问题,问题是 img 的中心每帧都会改变,所以看起来它会将播放器向后推。
  • @Hawanity 所以你的方法只适用于相同大小的图像。抱歉,但是对于不同大小的图像,有一种很好且干净的方法可以解决这个问题。您必须确保图像大小相同。但是,问题取决于图像的内容,没有人可以在没有看到图像的情况下回答这个问题。
  • @Hawanity 如果您的图像大小相同,则问题没有数学上的原因。它要么适用于左侧和右侧,要么根本不起作用。
猜你喜欢
  • 1970-01-01
  • 2015-05-07
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
相关资源
最近更新 更多