【问题标题】:Changing Sprite animation Speed (pygame)改变精灵动画速度(pygame)
【发布时间】:2018-08-20 14:22:39
【问题描述】:

我设法使用我创建的“动画”功能为我的播放器设置动画 - 在角色移动时循环遍历每帧的角色图像列表。但是,我也发现这与游戏运行的速度相同;并希望有一种简单的方法来改变它,使精灵的动画速度比游戏 FPS 慢。

这是我的精灵类代码:

class Civilian(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.player1group, game.bothplayers
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self._layer = PLAYER1_LAYER
        self.image = pg.Surface((61, 67))
        self.rect = self.image.get_rect()
        self.hit_rect = PLAYER_HIT_RECT
        self.hit_rect.center = self.rect.center
        self.playerspeed = 90
        self.vel = vec(0, 0)
        self.pos = vec(x , y)
        self.move = 0
        self.speedboost = False
        self.last_dir = 'down'#
        self.anim_speed = 0

    def animate(self, direction):
        if direction == 'right':
            self.spritesheet = pg.image.load('walk right civ.png') # Loading the right directional movement spritesheet into the variable
        if direction == 'left':
            self.spritesheet = pg.image.load('walk left civ.png')
        if direction == 'up':
            self.spritesheet = pg.image.load('walk up civ.png')
        if direction == 'down':
            self.spritesheet = pg.image.load('walk down civ.png')
        self.frames = [] # List which will contain each cell of the spritesheet
        # Adding the cells to the list #
        self.frames.append(self.spritesheet.subsurface(pg.Rect(0, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(61, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(122, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(183, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(244, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(305, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(366, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(427, 0, 61, 67)).convert_alpha())
        self.frames.append(self.spritesheet.subsurface(pg.Rect(488, 0, 61, 67)).convert_alpha())
        # Number of frames/cells
        self.frames_number = len(self.frames)
        # Current animation frame
        self.current_frame = 0
        # Frame rectangle
        self.frame_rect = self.frames[0].get_rect()
        self.last_dir = direction

    def get_keys(self):
        self.vel= vec(0, 0)
        keys = pg.key.get_pressed()

        if keys[pg.K_a]:    # Const. subtracts player speed from velocity (E.g. Moves sprite to the left)
            self.vel.x= -self.playerspeed
            self.move += 1
            self.moving = 'left' # Uses different spritesheet depending on direction
        elif keys[pg.K_d]:    # Const. adds player speed value to velocity (E.g. Moves sprite to the right)
            self.vel.x= self.playerspeed
            self.move += 1
            self.moving = 'right'
        elif keys[pg.K_w]:    # Const. subtracts player speed value from y velocity (Moves player upwards; opposite)
            self.vel.y= -self.playerspeed
            self.move += 1
            self.moving = 'up'
        elif keys[pg.K_s]: # Const. adds player speed value to y velocity (Moves player downwards; opposite)
            self.vel.y= self.playerspeed
            self.move += 1
            self.moving = 'down'

    def add_speed(self):
        pass

    def collide_with_player2(self, dir, ifColliding):
        if dir == 'x':
            collides = pg.sprite.spritecollide(self, self.game.player2group, False, collide_player_hit_rect)
            if collides:
                if self.vel.x > 0:
                    self.pos.x = collides[0].hit_rect.left - self.hit_rect.width / 2
                if self.vel.x < 0:
                    self.pos.x = collides[0].hit_rect.right + self.hit_rect.width / 2
                self.vel.x = 0
                self.hit_rect.centerx = self.pos.x
                print("collide x")
                if random.randint(0, 100) <= 4:
                    random.choice(self.game.thief_hit_sounds).play()
                self.ifColliding = True

        if dir == 'y':
            collides = pg.sprite.spritecollide(self, self.game.player2group, False, collide_player_hit_rect)
            if collides:
                if self.vel.y > 0:
                    self.pos.y = collides[0].hit_rect.top - self.hit_rect.height / 2
                if self.vel.y < 0:
                    self.pos.y = collides[0].hit_rect.bottom + self.hit_rect.height / 2
                self.vel.y = 0
                self.hit_rect.centery = self.pos.y
                print("collide y")
                if random.randint(0, 100) <= 4:
                    random.choice(self.game.thief_hit_sounds).play()
                self.ifColliding = True

    def collide_with_walls(self, dir):
        if dir == 'x':
            collides = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
            if collides:
                if self.vel.x > 0:
                    self.pos.x = collides[0].rect.left - self.hit_rect.width / 2
                if self.vel.x < 0:
                    self.pos.x = collides[0].rect.right + self.hit_rect.width / 2
                self.vel.x = 0
                self.hit_rect.centerx = self.pos.x
        if dir == 'y':
            collides = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
            if collides:
                if self.vel.y > 0:
                    self.pos.y = collides[0].rect.top - self.hit_rect.height / 2
                if self.vel.y < 0:
                    self.pos.y = collides[0].rect.bottom + self.hit_rect.height / 2
                self.vel.y = 0
                self.hit_rect.centery = self.pos.y

    def update(self):
        # frame updates
        self.anim_speed += 1
        self.moving = 'idle'
        self.animate(self.last_dir) # Sets the down spritesheet as default
        self.get_keys()
        if self.moving == 'up':
            self.animate(self.moving) # Uses the up-movement spritesheet if char moving upwards
        if self.moving == 'down':
            self.animate(self.moving) # Same as above, different direction
        if self.moving == 'left':
            self.animate(self.moving)
        if self.moving == 'right':
            self.animate(self.moving)
        self.ifColliding = False




        self.rect.center = self.pos
        self.pos += self.vel * self.game.dt
        self.hit_rect.centerx = self.pos.x
        self.collide_with_walls('x'), self.collide_with_player2('x', self.ifColliding)
        self.hit_rect.centery = self.pos.y
        self.collide_with_walls('y'), self.collide_with_player2('y', self.ifColliding)
        self.rect.center = self.hit_rect.midtop




        if self.ifColliding == True:
            Thief.health -= COL_DAMAGE
            print(Thief.health)
        self.current_frame = (self.current_frame + self.move) % self.frames_number
        if self.moving == 'idle':
            self.current_frame = 0
        self.image = self.frames[self.current_frame] # Image of sprite changes as program cycles through the sheet

【问题讨论】:

    标签: python animation pygame sprite-sheet


    【解决方案1】:

    您可以通过某种方式将动画速率与帧速率联系起来,从而将动画速率与帧速率解耦。

    一种方法是使用pygame.time.get_ticks() 返回自调用pygame.init() 以来的毫秒数。如果您存储此值,您可以测量已经过去了多少时间并适当地制作动画。

    def update(self):
        self.elapsed = pygame.time.get_ticks() - self.elapsed
        if self.elapsed > 500: # animate every half second
            self.animate()
    

    注意:您还需要在构造函数中初始化self.elapsed

    【讨论】:

    • 你提到在搞乱动画等之前初始化'self.elapsed';其中的值可以是任何数字/自定义值吗? - 只是为了澄清:)
    • 上面的逻辑非常简单,如果你想确保在第一次update 调用时产生动画,你可以将值初始化为零。如果您有多个精灵并且不希望它们同步,则应在创建时将这些值初始化为 0 到 500 之间的随机值。
    【解决方案2】:

    这是我为帧速率为 60 的精灵制作动画并且精灵动画比帧速率慢的代码

    import pygame
    import glob
    
    
    def fps():
        fr = "V.3 Fps: " + str(int(clock.get_fps()))
        frt = font.render(fr, 1, pygame.Color("coral"))
        return frt
    
    
    class MySprite(pygame.sprite.Sprite):
        def __init__(self, action):
            super(MySprite, self).__init__()
            self.action = action
            # This is to slow down animation # takes the frame now and...
            self.elapsed = 0
            self.images = []
            self.temp_imgs = []
            self.load_images()
            self.count = 0
    
        def load_images(self):
            l_imgs = glob.glob(f"png\\{self.action}*.png")
            for img in l_imgs:
                if len(img) == len(l_imgs[0]):
                    self.images.append(pygame.image.load(img))
                else:
                    self.temp_imgs.append(pygame.image.load(img))
            self.images.extend(self.temp_imgs)
            self.index = 0
            self.rect = pygame.Rect(5, 5, 150, 198)
    
        def update(self):
            self.count += 1
            if self.index == len(self.images):
                    self.index = 0
            self.image = self.images[self.index]
            if self.count > 2:
                    #self.image = self.images[self.index]
                    self.index += 1
                    self.count = 0
    
        def group_sprites(self):
            return pygame.sprite.Group(self)
    
    
    def group():
        "Dictionary of group of sprites"
        dici = {}
        actions = "idle walk run jump dead"
        actions = actions.split()
        for action in actions:
            dici[action] = MySprite(action).group_sprites()
        return dici
    
    
    def main():
        global clock
        global font
    
        SIZE = 600, 600
        FPS = 60
        pygame.init()
        action = group()
        my_group = action["idle"]
        screen = pygame.display.set_mode(SIZE)
        pygame.display.set_caption("Game v.3")
        font = pygame.font.SysFont("Arial", 60)
        clock = pygame.time.Clock()
    
        loop = 1
        while loop:
    
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    loop = 0
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        my_group = action["walk"]
                    if event.key == pygame.K_UP:
                        my_group = action["jump"]
                    if event.key == pygame.K_SPACE:
                        my_group = action["idle"]
                    if event.key == pygame.K_RIGHT:
                        my_group = action["run"]
                    if event.key == pygame.K_DOWN:
                        my_group = action["dead"]
    
            my_group.update()
            screen.fill((0, 0, 0))
            my_group.draw(screen)
            screen.blit(fps(), (10, 0))
            pygame.display.update()
            clock.tick(FPS)
        pygame.quit()
    
    
    if __name__ == '__main__':
        main()
    

    阅读这篇文章...slow down animation without affecting the frame rate

    Dowload images and put the in a directory called png

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-21
      • 2017-06-21
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多