Pygame を使用して、Python でいくつかの画像から簡単なスプライト アニメーションを作成するための優れたチュートリアルを探していました。探しているものがまだ見つかりません。
私の質問は簡単です: いくつかの画像からアニメーション化されたスプライトを作成する方法 (例: 寸法 20x20px の爆発のいくつかの画像を 1 つにアニメーション化する)
良いアイデアはありますか?
Pygame を使用して、Python でいくつかの画像から簡単なスプライト アニメーションを作成するための優れたチュートリアルを探していました。探しているものがまだ見つかりません。
私の質問は簡単です: いくつかの画像からアニメーション化されたスプライトを作成する方法 (例: 寸法 20x20px の爆発のいくつかの画像を 1 つにアニメーション化する)
良いアイデアはありますか?
スプライトを変更して、そのイメージを 内の別のイメージに交換することができます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
、コードが入っている同じフォルダー内にあると想定しています。
すべてのスプライト アニメーションを 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])
アニメーション化されたスプライトの場合、画像 (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()