15

Pygame を使用して、Python でいくつかの画像から簡単なスプライト アニメーションを作成するための優れたチュートリアルを探していました。探しているものがまだ見つかりません。

私の質問は簡単です: いくつかの画像からアニメーション化されたスプライトを作成する方法 (例: 寸法 20x20px の爆発のいくつかの画像を 1 つにアニメーション化する)

良いアイデアはありますか?

4

4 に答える 4

21

スプライトを変更して、そのイメージを 内の別のイメージに交換することができますupdate。そうすれば、スプライトがレンダリングされると、アニメーションのように見えます。

編集

これが私が作成した簡単な例です:

import pygame
import sys

def load_image(name):
    image = pygame.image.load(name)
    return image

class TestSprite(pygame.sprite.Sprite):
    def __init__(self):
        super(TestSprite, self).__init__()
        self.images = []
        self.images.append(load_image('image1.png'))
        self.images.append(load_image('image2.png'))
        # assuming both images are 64x64 pixels

        self.index = 0
        self.image = self.images[self.index]
        self.rect = pygame.Rect(5, 5, 64, 64)

    def update(self):
        '''This method iterates through the elements inside self.images and 
        displays the next one each tick. For a slower animation, you may want to 
        consider using a timer of some sort so it updates slower.'''
        self.index += 1
        if self.index >= len(self.images):
            self.index = 0
        self.image = self.images[self.index]

def main():
    pygame.init()
    screen = pygame.display.set_mode((250, 250))

    my_sprite = TestSprite()
    my_group = pygame.sprite.Group(my_sprite)

    while True:
        event = pygame.event.poll()
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit(0)

        # Calling the 'my_group.update' function calls the 'update' function of all 
        # its member sprites. Calling the 'my_group.draw' function uses the 'image'
        # and 'rect' attributes of its member sprites to draw the sprite.
        my_group.update()
        my_group.draw(screen)
        pygame.display.flip()

if __name__ == '__main__':
    main()

image1.png呼び出された 2 つのイメージがありimage2.png、コードが入っている同じフォルダー内にあると想定しています。

于 2012-12-26T17:53:00.247 に答える
4

すべてのスプライト アニメーションを 1 つの大きな「キャンバス」に配置する必要があるため、20x20 の爆発スプライト フレームを 3 つ使用すると、60x20 の画像になります。画像の領域をロードすることで、適切なフレームを取得できるようになりました。

スプライト クラス内では、ほとんどの場合 update メソッドで次のようなものを用意する必要があります (簡単にするためにハードコーディングされているため、適切なアニメーション フレームの選択を担当する別のクラスを用意することをお勧めします)。self.f = 0オン__init__

def update(self):
    images = [[0, 0], [20, 0], [40, 0]]
    self.f += 1 if self.f < len(images) else 0
    self.image = your_function_to_get_image_by_coordinates(images[i])
于 2012-12-26T18:02:08.223 に答える
1

アニメーション化されたスプライトの場合、画像 (pygame.Surfaceオブジェクト) のリストを生成する必要があります。映画の写真のように、フレームごとに異なるリストの写真が表示されます。これにより、アニメーション オブジェクトの外観が得られます。
イメージのリストを取得する 1 つの方法は、アニメーションGIF (Graphics Interchange Format)をロードすることです。残念ながら、PyGame はアニメーション GIF のフレームをロードする機能を提供していません。ただし、この問題に対処するスタック オーバーフローの回答がいくつかあります。

1 つの方法は、人気のあるPillowライブラリ ( pip install Pillow ) を使用することです。次の関数は、アニメーションGIFpygame.Surfaceのフレームを読み込み、オブジェクトのリストを生成します。

from PIL import Image, ImageSequence
def loadGIF(filename):
    pilImage = Image.open(filename)
    frames = []
    for frame in ImageSequence.Iterator(pilImage):
        frame = frame.convert('RGBA')
        pygameImage = pygame.image.fromstring(
            frame.tobytes(), frame.size, frame.mode).convert_alpha()
        frames.append(pygameImage)
    return frames

pygame.sprite.Sprite画像のリストを保持するクラスを作成します。フレームごとに異なる画像を選択する update メソッドを実装します。
画像のリストをクラス コンストラクターに渡します。indexリスト内の現在の画像のインデックスを示す属性を追加します。Updateメソッドのインデックスを増やします。インデックスがイメージ リストの長さ以上である場合は、インデックスをリセットします (またはモジュロ ( %) 演算子を使用します)。サブスクリプションによってリストから現在のイメージを取得します。

class AnimatedSpriteObject(pygame.sprite.Sprite):
    def __init__(self, x, bottom, images):
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.image = self.images[0]
        self.rect = self.image.get_rect(midbottom = (x, bottom))
        self.image_index = 0
    def update(self):
        self.image_index += 1
        if self.image_index >= len(self.images):
            self.image_index = 0
        self.image = self.images[self.image_index]

アニメーション GIFスプライトの読み込みも参照してください。

GIF の例 (アニメーション GIF、アニメーション画像から):

最小限の例: repl.it/@Rabbid76/PyGame-SpriteAnimation

import pygame
from PIL import Image, ImageSequence

def loadGIF(filename):
    pilImage = Image.open(filename)
    frames = []
    for frame in ImageSequence.Iterator(pilImage):
        frame = frame.convert('RGBA')
        pygameImage = pygame.image.fromstring(
            frame.tobytes(), frame.size, frame.mode).convert_alpha()
        frames.append(pygameImage)
    return frames
 
class AnimatedSpriteObject(pygame.sprite.Sprite):
    def __init__(self, x, bottom, images):
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.image = self.images[0]
        self.rect = self.image.get_rect(midbottom = (x, bottom))
        self.image_index = 0
    def update(self):
        self.image_index += 1
        self.image = self.images[self.image_index % len(self.images)]
        self.rect.x -= 5
        if self.rect.right < 0:
            self.rect.left = pygame.display.get_surface().get_width()

pygame.init()
window = pygame.display.set_mode((300, 200))
clock = pygame.time.Clock()
ground = window.get_height() * 3 // 4

gifFrameList = loadGIF('stone_age.gif')
animated_sprite = AnimatedSpriteObject(window.get_width() // 2, ground, gifFrameList)    
all_sprites = pygame.sprite.Group(animated_sprite)

run = True
while run:
    clock.tick(20)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    all_sprites.update()

    window.fill((127, 192, 255), (0, 0, window.get_width(), ground))
    window.fill((255, 127, 64), (0, ground, window.get_width(), window.get_height() - ground))
    all_sprites.draw(window)
    pygame.display.flip()

pygame.quit()
exit()
于 2020-11-03T19:01:49.603 に答える