【Pygame】スプライトのグループ管理(高速描画)

この記事では、Pygameを用いてスプライトをグループ管理する方法とソースコードを解説します。

スプライトグループ(高速)

スプライトグループを使うと複数のスプライトを効率よく管理できます。(スプライトの更新・描画が楽)
また、スプライトの描画を高速に行うために汚れたRectのアニメーション(dirty rect animation)という手法があります。 この手法は、画面を更新するときに、全体を描き換えずにスプライトが更新された一部分だを描き換えます。
今回はPygameで汚れたRectのアニメーションを行ってみました。

処理手順
「pygame」モジュールをインポートする。
画面のサイズを設定する。
円の中心座標を画面の中心に設定する。
Pygameを初期化する。[pygame.init]
キャラクター3人分のスプライトを作成する。(この時同時にグループに追加される)
3つのスプライトをグループに追加する。(group.add)
画面のフレームレートを設定する。
スプライトを背景画像で消去する。
スプライトグループを更新する。(group.update)
スプライトグループを描画する。(group.draw)
変化がある箇所のRectを取得する。
画面を更新する。(変化がある部分のみ)
3人のキャラクターを指定した座標(x, y)に描画する。
イベント処理をする。画面の閉じるボタンが押されたら終了する。
7-15の処理を繰り返す。
# -*- coding: utf-8 -*-
import pygame
from pygame.locals import *
import sys

SCREEN = Rect(0, 0, 400, 400)

# スプライトのクラス
class Sprite(pygame.sprite.Sprite):
    # スプライトを作成(画像ファイル名, 位置(x, y), 速さ(vx, vy), 回転angle)
    def __init__(self, filename, (x, y), (vx, vy), angle=0):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.image = pygame.image.load(filename).convert_alpha()
        if angle != 0: self.img = pygame.transform.rotate(self.image, angle)
        w = self.image.get_width()
        h = self.image.get_height()
        self.rect = Rect(x, y, w, h)
        self.vx = vx
        self.vy = vy
        self.angle = angle

    def update(self):
        self.rect.move_ip(self.vx, self.vy)
        # 壁と衝突時の処理(跳ね返り)
        if self.rect.left < 0 or self.rect.right > SCREEN.width:
            self.vx = -self.vx
        if self.rect.top < 0 or self.rect.bottom > SCREEN.height:
            self.vy = -self.vy
        # 壁と衝突時の処理(壁を超えないように)
        self.rect = self.rect.clamp(SCREEN)

    def draw(self, screen):
        screen.blit(self.img, self.rect)

# メイン
def main():
    pygame.init()
    screen = pygame.display.set_mode(SCREEN.size)

    # スプライトグループを作成
    group = pygame.sprite.RenderUpdates()
    Sprite.containers = group

    # スプライトを作成(画像ファイル名, 位置(x, y), 速さ(vx, vy), 回転angle)
    player = Sprite("C:\prog\python\pygame\player.png", (200, 200), (2, 0), 0)
    enemy1 = Sprite("C:\prog\python\pygame\enemy1.png", (200, 200), (0, 2), 0)
    enemy2 = Sprite("C:\prog\python\pygame\enemy2.png", (200, 200), (2, 2), 10)
    clock = pygame.time.Clock()

    # 背景の作成と描画(背景は最初に1回だけ描画)
    bg = pygame.Surface(SCREEN.size)
    bg.fill((0, 20, 0)) # 画面の背景色
    screen.blit(bg, (0,0))
    pygame.display.update()

    while (1):
        clock.tick(30)  # フレームレート(30fps)
        group.clear(screen, bg)

        # スプライトグループを更新(キャラクタ3体を一括して更新)
        group.update()

        # スプライトを更新
        dirty_rects = group.draw(screen)

        # updateにdirty rectを渡すとその部分だけ更新するので効率よい
        # 画面更新
        pygame.display.update(dirty_rects)

        # イベント処理
        for event in pygame.event.get():
            # 終了用のイベント処理
            if event.type == QUIT:          # 閉じるボタンが押されたとき
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:       # キーを押したとき
                if event.key == K_ESCAPE:   # Escキーが押されたとき
                    pygame.quit()
                    sys.exit()

if __name__ == "__main__":
    main()


3人のキャラクターがあっちこっち動きます。

関連記事
1 【Pygame入門】ゲームプログラミング
2 【Python入門】サンプル集・使い方
Python
技術雑記

コメント

タイトルとURLをコピーしました