Замок Виндзор IoC в приложении MVC

Существует два типа анимации: зависящие от кадра и зависящие от времени. Оба работают аналогичным образом.


До основного цикла

  1. Загрузите все изображения в список.
  2. Создайте три переменные: index, которая отслеживает текущий индекс списка изображений. current_time или current_frame, который отслеживает текущее время или текущий кадр с момента последнего переключения индекса. animation_time или animation_frames, которые определяют, сколько секунд или кадров должно пройти до переключения изображения.

Во время основного цикла

  1. Increment current_time на количество секунд, прошедшее с момента последнего его увеличения, или приращение current_frame на 1.
  2. Проверьте, есть ли current_time >= animation_time или current_frame >= animation_frame. Если true, продолжайте с 3-5.
  3. Сбросьте current_time = 0 или current_frame = 0.
  4. Увеличьте индекс, если только он будет равен или больше, чем количество изображений , В этом случае сбросьте index = 0.
  5. Измените изображение спрайта соответствующим образом.

Полный рабочий пример

import os
import pygame
pygame.init()

SIZE = WIDTH, HEIGHT = 720, 480
BACKGROUND_COLOR = pygame.Color('black')
FPS = 60

screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()


def load_images(path):
    """
    Loads all images in directory. The directory must only contain images.

    Args:
        path: The relative or absolute path to the directory to load images from.

    Returns:
        List of images.
    """
    images = []
    for file_name in os.listdir(path):
        image = pygame.image.load(path + os.sep + file_name).convert()
        images.append(image)
    return images


class AnimatedSprite(pygame.sprite.Sprite):

    def __init__(self, position, images):
        """
        Animated sprite object.

        Args:
            position: x, y coordinate on the screen to place the AnimatedSprite.
            images: Images to use in the animation.
        """
        super(AnimatedSprite, self).__init__()

        size = (32, 32)  # This should match the size of the images.

        self.rect = pygame.Rect(position, size)
        self.images = images
        self.images_right = images
        self.images_left = [pygame.transform.flip(image, True, False) for image in images]  # Flipping every image.
        self.index = 0
        self.image = images[self.index]  # 'image' is the current image of the animation.

        self.velocity = pygame.math.Vector2(0, 0)

        self.animation_time = 0.1
        self.current_time = 0

        self.animation_frames = 6
        self.current_frame = 0

    def update_time_dependent(self, dt):
        """
        Updates the image of Sprite approximately every 0.1 second.

        Args:
            dt: Time elapsed between each frame.
        """
        if self.velocity.x > 0:  # Use the right images if sprite is moving right.
            self.images = self.images_right
        elif self.velocity.x < 0:
            self.images = self.images_left

        self.current_time += dt
        if self.current_time >= self.animation_time:
            self.current_time = 0
            self.index = (self.index + 1) % len(self.images)
            self.image = self.images[self.index]

        self.rect.move_ip(*self.velocity)

    def update_frame_dependent(self):
        """
        Updates the image of Sprite every 6 frame (approximately every 0.1 second if frame rate is 60).
        """
        if self.velocity.x > 0:  # Use the right images if sprite is moving right.
            self.images = self.images_right
        elif self.velocity.x < 0:
            self.images = self.images_left

        self.current_frame += 1
        if self.current_frame >= self.animation_frames:
            self.current_frame = 0
            self.index = (self.index + 1) % len(self.images)
            self.image = self.images[self.index]

        self.rect.move_ip(*self.velocity)

    def update(self, dt):
        """This is the method that's being called when 'all_sprites.update(dt)' is called."""
        # Switch between the two update methods by commenting/uncommenting.
        self.update_time_dependent(dt)
        # self.update_frame_dependent()


def main():
    images = load_images(path='temp')  # Make sure to provide the relative or full path to the images directory.
    player = AnimatedSprite(position=(100, 100), images=images)
    all_sprites = pygame.sprite.Group(player)  # Creates a sprite group and adds 'player' to it.

    running = True
    while running:

        dt = clock.tick(FPS) / 1000  # Amount of seconds between each loop.

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    player.velocity.x = 4
                elif event.key == pygame.K_LEFT:
                    player.velocity.x = -4
                elif event.key == pygame.K_DOWN:
                    player.velocity.y = 4
                elif event.key == pygame.K_UP:
                    player.velocity.y = -4
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
                    player.velocity.x = 0
                elif event.key == pygame.K_DOWN or event.key == pygame.K_UP:
                    player.velocity.y = 0

        all_sprites.update(dt)  # Calls the 'update' method on all sprites in the list (currently just the player).

        screen.fill(BACKGROUND_COLOR)
        all_sprites.draw(screen)
        pygame.display.update()


if __name__ == '__main__':
    main()

Когда выбрать, какая

Временная анимация позволяет вам воспроизводить анимацию с одинаковой скоростью, независимо от того, насколько медленна / быстрая частота кадров или медленный / быстрый ваш компьютер. Это позволяет вашей программе свободно изменять частоту кадров, не влияя на анимацию, и она также будет последовательной, даже если компьютер не сможет справиться с частотой кадров. Если программа отстает, анимация догонит до состояния, она должна была быть, как если бы не было задержки.

Хотя может случиться так, что цикл анимации не синхронизируется с частотой кадров, что делает цикл анимации кажется нерегулярным. Например, скажем, что мы обновляем кадры каждые 0,05 секунды и изображение переключателя анимации каждые 0,075 секунды, тогда цикл будет:

  1. Рамка 1; 0,00 секунды; изображение 1
  2. Рамка 2; 0,05 секунды; изображение 1
  3. Кадр 3; 0,10 секунды; изображение 2
  4. Кадр 4; 0,15 с; изображение 1
  5. Рамка 5; 0,20 с; изображение 1
  6. Рама 6; 0,25 с; image 2

И так далее ...

Фреймозависимая может выглядеть более гладко, если ваш компьютер может последовательно работать с частотой кадров. Если произойдет лаг, он остановится в своем текущем состоянии и перезапустится, когда отставание остановится, что делает отставание более заметным. Эта альтернатива немного проще реализовать, так как вам просто нужно увеличивать current_frame с 1 на каждый вызов вместо того, чтобы иметь дело с дельта-временем (dt) и передавать его каждому объекту.

Sprites

Результат

13
задан Community 23 May 2017 в 10:29
поделиться