見出し画像

4-5 Pygameのスプライト

同人誌について

 この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。

 同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。


スプライトとは

 『Pygame』ではスプライトを利用できます。スプライトは、ゲーム開発でよく出てくる、複数の小さな画像を高速に描画するための仕組みです。

 『Pygame』のスプライトでは、複数のスプライトをグループ化して、一括して描画することができます。

Spriteを継承したクラス

 スプライトの例「example_pygame/sprite.py」を示します。

import pygame

# キャラクター
class Chara(pygame.sprite.Sprite):
    # 初期化
    def __init__(self, images: list[pygame.Surface]):
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.image = images[0]
        self.rect = self.image.get_rect()

    # 更新
    def update(self):
        time = pygame.time.get_ticks()  # 経過時間
        i = time // 500 % 2   # 0, 1
        self.image = self.images[i]

def main():
    pygame.init()       # Pygameを初期化
    screen = pygame.display.set_mode((800, 600))    # 画面作成
    running = True      # 実行継続フラグ

    # スプライト グループの準備と画像の読み込み
    sprite_all = pygame.sprite.RenderUpdates() # 描画更新用
    image0 = pygame.image.load("image/chara0.png")  # 画像読み込み
    image1 = pygame.image.load("image/chara1.png")  # 画像読み込み

    # スプライトの作成と準備
    for y in range(8):
        for x in range(10):
            chara = Chara([image0, image1])
            chara.add(sprite_all)
            chara.rect.x = x * (64 + 16)
            chara.rect.y = y * (64 + 10)

    while running:
        pygame.display.update()     # 画面を更新
        screen.fill(pygame.Color(0, 0, 0))  # 画面を塗りつぶす
        for event in pygame.event.get():    # イベント
            if event.type == pygame.QUIT: running = False   # 終了

        sprite_all.update()         # スプライト更新
        sprite_all.draw(screen)     # スプライト描画

        pygame.display.flip()   # 画面フリップ
    pygame.quit()

if __name__ == "__main__":
    main()

 実行した画面です。

スプライト

 まずは、`pygame.sprite.Sprite`を継承した`Chara`クラスを作ります。`Chara`クラスには、コンストラクター`__init__`と、スプライトの処理で必要な`update()`メソッドを書きます。

import pygame

# キャラクター
class Chara(pygame.sprite.Sprite):
    # 初期化
    def __init__(self, images: list[pygame.Surface]):
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.image = images[0]
        self.rect = self.image.get_rect()

    # 更新
    def update(self):
        elapse = pygame.time.get_ticks()    # 経過時間
        i = elapse // 500 % 2   # 0, 1
        self.image = self.images[i]

 スプライトには、次のメソッドがあります。

スプライトのメソッド

Spriteの利用

 次に、`Chara`クラスを利用して、複数のスプライト描画を一括でおこないます。

 まずは、スプライト グループの準備と画像の読み込みです。

def main():
    pygame.init()       # Pygameを初期化
    screen = pygame.display.set_mode((800, 600))    # 画面作成
    running = True      # 実行継続フラグ

    # スプライト グループの準備と画像の読み込み
    sprite_all = pygame.sprite.RenderUpdates() # 描画更新用
    image0 = pygame.image.load("image/chara0.png")  # 画像読み込み
    image1 = pygame.image.load("image/chara1.png")  # 画像読み込み

 `pygame.sprite.RenderUpdates()`で、描画一括更新用のスプライト グループを作成します。そして変数`sprite_all`に代入します。また、画像を読み込みます。

 次は、スプライトの作成と準備です。

    # スプライトの作成と準備
    for y in range(8):
        for x in range(10):
            chara = Chara([image0, image1])
            chara.add(sprite_all)
            chara.rect.x = x * (64 + 16)
            chara.rect.y = y * (64 + 10)

 y方向8個、x方向10個、合計80個のスプライトを作ります。スプライトは`Chara()`で作り、変数`chara`に代入します。この`Chara`クラスは、`Sprite`を継承しています。

 スプライト`chara`の`add()`メソッドを使い、スプライト グループ`sprite_all`を登録します。また`rect.x` `rect.y`に、描画位置を設定します。

 次は、スプライトの一括更新と描画です。

    while running:
        pygame.display.update()     # 画面を更新
        screen.fill(pygame.Color(0, 0, 0))  # 画面を塗りつぶす
        for event in pygame.event.get():    # イベント
            if event.type == pygame.QUIT: running = False   # 終了

        sprite_all.update()         # スプライト更新
        sprite_all.draw(screen)     # スプライト描画

        pygame.display.flip()   # 画面フリップ
    pygame.quit()

 `sprite_all.update()`を実行することで、`sprite_all`が登録されたスプライトが一括更新されます。また、`sprite_all.draw()`を実行することで、一括描画がおこなわれます。

 画像を1枚ずつ更新したり描画したりしないので、メインループがすっきりします。キャラクターの描画やマップの描画には、このスプライトの仕組みが便利です。

 スプライトには多くの派生クラスがあります。必要に応じて、それらを使うことになります。複雑なことをしないのならば、基本の`Sprite`と`RenderUpdates`を使えば十分です。

 また、`pygame.sprite`にはアクションゲーム用の衝突判定の関数もあります。四角形や円を基準とした衝突検出ができます。今回は、衝突判定は使わないので割愛します。


同人誌について

 この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。

 同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。

 このnoteの記事と、Webページに一部抜粋版を掲載しています。

 技術系同人誌など まとめページ


この記事が気に入ったらサポートをしてみませんか?