How do I make it so that my walking animation plays at a set speed? (Python, Pygame)

前端 未结 1 1873
有刺的猬
有刺的猬 2020-12-12 01:37
keystate = pg.key.get_pressed()
        if keystate[pg.K_LEFT]:
            self.counter = (self.counter + 1) % len(player_images)
            self.acc.x = -PLAYER_A         


        
相关标签:
1条回答
  • 2020-12-12 02:10

    You need to keep track of the time, so you can either use pygame.time.get_ticks or the time that clock.tick() returns (it's usually called dt for delta time) and then update the image after some time has passed.

    The pygame.time.get_ticks variant:

    class Player(pg.sprite.Sprite):
    
        def __init__(self, pos, *groups):
            super().__init__(*groups)
            self.frame = 0  # Index of the current animation frame.
            self.image = IMAGES[self.frame]  # Set image to the first image.
            self.rect = self.image.get_rect(center=pos)
            # Start time of the last animation frame.
            self.start_time = pg.time.get_ticks()
            # If the time limit is reached, increment the index
            # and change self.image.
            self.time_limit = 300  # Milliseconds.
    
        def update(self):
            now = pg.time.get_ticks()
            if now - self.start_time > self.time_limit:
                self.frame += 1  # Increment the frame index.
                self.frame %= len(IMAGES)  # Keep the index in the range.
                self.image = IMAGES[self.frame]  # Switch the image.
                self.start_time = now
    

    And a complete example with the delta time variant. (You'll need the dt in your class anyway for the movement speed, if you eventually want to make the game frame rate independent).

    import pygame as pg
    
    
    # Some images with dots for the animation.
    IMAGE1 = pg.Surface((90, 90))
    IMAGE1.fill((30, 90, 200))
    pg.draw.circle(IMAGE1, (50, 170, 220), (45, 45), 15)
    IMAGE2 = pg.Surface((90, 90))
    IMAGE2.fill((30, 90, 200))
    pg.draw.circle(IMAGE2, (50, 170, 220), (30, 30), 15)
    pg.draw.circle(IMAGE2, (50, 170, 220), (60, 60), 15)
    IMAGE3 = pg.Surface((90, 90))
    IMAGE3.fill((30, 90, 200))
    pg.draw.circle(IMAGE3, (50, 170, 220), (20, 20), 15)
    pg.draw.circle(IMAGE3, (50, 170, 220), (45, 45), 15)
    pg.draw.circle(IMAGE3, (50, 170, 220), (70, 70), 15)
    IMAGES = [IMAGE1, IMAGE2, IMAGE3]
    
    
    class Entity(pg.sprite.Sprite):
    
        def __init__(self, pos, *groups):
            super().__init__(*groups)
            self.frame = 0  # Index of the current animation frame.
            self.image = IMAGES[self.frame]  # Set image to the first image.
            self.rect = self.image.get_rect(center=pos)
            self.timer = 0  # Time in seconds.
    
        def update(self, dt):
            self.timer += dt  # Increment the timer.
            # If the timer is above the desired time limit ...
            if self.timer >= .5:
                self.timer = 0  # Reset the timer.
                self.frame += 1  # Increment the frame index.
                self.frame %= len(IMAGES)  # Keep the index in the range.
                self.image = IMAGES[self.frame]  # Switch the image.
    
    
    def main():
        screen = pg.display.set_mode((640, 480))
        clock = pg.time.Clock()
        all_sprites = pg.sprite.Group(Entity((200, 200)))
        dt = 0
        done = False
    
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            # Pass dt to the update methods of all sprites.
            all_sprites.update(dt)
            screen.fill((30, 30, 30))
            all_sprites.draw(screen)
    
            pg.display.flip()
            # dt is the time that has passed since the last clock.tick call.
            # Divide by 1000 to convert milliseconds to seconds.
            dt = clock.tick(30) / 1000
    
    
    if __name__ == '__main__':
        pg.init()
        main()
        pg.quit()
    
    0 讨论(0)
提交回复
热议问题