Pygame Zero② フレーム処理とクラス

Image from Gyazo

フレーム処理とクラス

ゲーム開発において基本となる フレーム処理 について学習します. フレーム とは,図形,文字列,画像などが表示されているスクリーンのある時刻の状態のことです. パラパラ漫画の要領でフレームが切り替わることで,映像としてゲームが成立しています. フレームの切り替わりの速度は, フレームレート(fps) として表され,一般的なゲームで必要とされる60fpsは,1秒間に60回フレームが切り替わることを意味しています. また,ゲーム開発において,利用すると便利な クラス についても説明します. クラスは,整数や文字列などを記憶するための変数と,複数の処理を実行する関数を,まとめて管理するための仕組みです. クラスを正しく理解するには, オブジェクト指向を学ぶ必要がありますが,本授業では割愛します.

準備

Muエディタを起動したら,Pygame Zero モードを選択しましょう. 保存用のフォルダを「chapter9」という名前で作成し,ソースファイルを「game.py」という名前でフォルダ内に保存します. また,ゲームを表示するためのウィンドウを作成します. ウィンドウの幅は640px,高さは480px,背景色は白色に設定します.

WIDTH = 640
HEIGHT = 480

def draw():
	screen.fill("white")

フレーム処理

Pygame Zeroでフレーム処理を実装するには,draw()update()を定義します. 1つのフレームにおいて,最初にdraw()が実行され,その後でupdate()が実行されます. draw()では図形や画像などの 表示update()では図形や画像の移動などの 更新 を記述します.

Image from Gyazo

最初にdraw()において,filled_circle()line()で赤いリンゴを表示します. リンゴの位置は変数xyを利用して相対的に決まることに注意してください.

x = 320  # X座標
y = 0  # Y座標
speed = 1  # 落下速度

def draw():
    screen.fill("white") # screen.fill((255, 255, 255))でもOK

	# 赤いリンゴ
    screen.draw.filled_circle((x, y), 10, "red")
    screen.draw.line((x, y-5), (x, y-15), "black")

Image from Gyazo

次にupdate()において,Y座標を速度分だけ増やすことで,赤いリンゴを下方向に移動させます. 変数xyspeedはグローバル変数として宣言します.

def update():
    global x, y, speed  # グローバル変数
    y = y + speed  # 落下速度だけ下方向に移動

Image from Gyazo

例題1

任意の位置に青いリンゴを表示させ,下方向に落下させてください.

Image from Gyazo

例題2

リンゴの落下速度を徐々に速くしてください.

Image from Gyazo

クラスとオブジェクト

上記で実装したリンゴには,位置や速度を表す変数と,表示や落下などの動作が必要です. これらをまとめて表現するには クラス を利用します. ここでは次のようにAppleクラスを定義します. Appleクラスには,4つの変数(xyspeedcolor)と,2つの関数(paint()fall())を定義しています. 関数の中で変数を参照するには,引数にselfを宣言し,self.xself.yと記述します.

Image from Gyazo

# Appleクラスを定義
class Apple:
    x = 320
    y = 0
    speed = 1
    color = "green"

    def paint(self):
        screen.draw.filled_circle((self.x, self.y), 10, self.color)
        screen.draw.line((self.x, self.y-5), (self.x, self.y-15), "black")

    def fall(self):
        self.y = self.y + self.speed
        self.speed = self.speed + 0.05

Appleクラスはデータの型でしかありません. このAppleクラスを利用できるようにした状態をオブジェクト(インスタンス)と呼びます. このオブジェクトからクラスで定義した変数・関数を呼び出すことが可能です. 例えば,Appleクラスのオブジェクトappleから,変数xを参照するにはapple.x,関数paint()を実行するにはapple.paint()と記述します.

# Appleクラスのオブジェクトを生成
apple = Apple()
print(apple.x) # -> 320
print(apple.y) # -> 0

def draw():
    screen.fill("white")
    apple.paint() # paint()を実行する

def update():
    apple.fall() # fall()を実行する

Image from Gyazo

クラスの変数(xyなど)を,オブジェクトを生成するタイミングで設定するには コンストラクタ を利用します. コンストラクタは特殊な関数であり,__init__()という名前で定義します. オブジェクトの生成の際に,引数に設定した変数を渡すことができます. 例えば,Apple(320, 0, 1, "green")と設定すると,それぞれx=320y=0speed=1color="green"が代入されます. クラスを利用すると,簡単に複数のオブジェクトを生成することが可能です. ここでは,緑のリンゴと,ピンクのリンゴを,Appleクラスを利用して生成しています.

class Apple:

	# コンストラクタ(引数で値を設定)
    def __init__(self, x, y, speed, color):
        self.x = x
        self.y = y
        self.speed = speed
        self.color = color

    def paint(self):
        screen.draw.filled_circle((self.x, self.y), 10, self.color)
        screen.draw.line((self.x, self.y-5), (self.x, self.y-15), "black")    

    def fall(self):
        self.y = self.y + self.speed
        self.speed = self.speed + 0.05

# 引数に値を渡す
apple1 = Apple(320, 0, 1, "green") #  緑色のリンゴ
apple2 = Apple(480, 0, 1, "pink")  # ピンク色のリンゴ

def draw():
    screen.fill("white")
    apple1.paint()
    apple2.paint()

def update():
    apple1.fall()
    apple2.fall()

Image from Gyazo

リストでオブジェクトを管理

リストを利用することで,多くのオブジェクトを管理することができます. ここでは,for文を利用して,Appleクラスのオブジェクトを100個生成し,リストapple_listに格納しています. このときオブジェクトのX座標はランダムに設定しています. リストapple_listの要素を,for文で取り出し,paint()fall()を呼び出しています. この結果,100個のリンゴが同時に落下します.

from random import *

# リストを初期化
apple_list = []
for i in range(100):
    x = randint(0, 640)  # ランダムにX座標を設定
    apple = Apple(x, 0, 1, "red")
    apple_list.append(apple)  # リストに追加

def draw():
    screen.fill("white")
    for apple in apple_list:
        apple.paint()

def update():
    for apple in apple_list:
        apple.fall()

Image from Gyazo

リンゴが落下するタイミングをずらすため,Appleクラスにvisibleという変数を新たに追加し,visibleTrueのときだけ,リンゴを表示・落下させることにします. draw()の中で,乱数を利用して1/1000の確率でvisibleTrueに設定することで,一部のリンゴだけが表示・落下することになります.

class Apple:

    def __init__(self, x, y, speed, color):
        self.x = x
        self.y = y
        self.speed = speed
        self.color = color
        self.visible = False  # 変数を追加

    def paint(self):
        if self.visible:
            screen.draw.filled_circle((self.x, self.y), 10, self.color)
            screen.draw.line((self.x, self.y-5), (self.x, self.y-15), "black")

    def fall(self):
        if self.visible:
            self.y = self.y + self.speed
            self.speed = self.speed + 0.05

apple_list = []
for i in range(100):
    x = randint(0, 640)
    apple = Apple(x, 0, 1, "red")
    apple_list.append(apple)

def draw():
    screen.fill("white")

    for apple in apple_list:

		# 1/1000の確率でvisible=Trueに設定
        if random() < 0.001:
            apple.visible = True

        apple.paint()

def update():
    for apple in apple_list:
		apple.fall()

Image from Gyazo

課題

次の課題に取組んでください.

Image from Gyazo

課題を完成させたらスクリプトを保存し,chapter9フォルダをZIPで圧縮してから,chapter9.zipという名前でファイルを提出してください.

参考書籍

愛知県名古屋市にある椙山女学園大学 文化情報学部 向研究室の公式サイトです. 専門は情報科学であり,人工知能やデータベースなどの技術要素を指導しています. この公式サイトでは,授業で使用している教材を公開すると共に, ベールに包まれた女子大教員のミステリアスな日常を4コマ漫画でお伝えしていきます. サイトに関するご意見やご質問はFacebookまたはTwitterでお問い合わせください.