コンテンツにスキップ

1 PyGameZero

1.1 準備

PyGame Zeroは2次元ゲーム用のライブラリです。PyGameをより簡単に利用できます。 インストールをpipコマンドで行います。

pip install pgzero

1.2 ウィンドウの描画

pgzrunをインポートし、go関数で実行します。 WIDTHに画面の幅、HEIGHTに高さを指定します。これで実行するとウィンドウが表示されます。

import pgzrun

WIDTH = 800
HEIGHT = 600

# ここに処理を書く

pgzrun.go()

pgzrun.go()は必ず最後に行います。

座標について

PyGame Zeroの画面は、左上隅が原点 (0, 0) となります。X座標は右へ進むほど増加します。Y座標は下へ進むほど増加します

背景色を変えてみます。描画を行うには draw関数を定義します。 この中で背景色を設定するscreen.fillを行い、色をRGBで指定します。 pgzrun.go()の前で以下を行います。

def draw():
    screen.fill((128, 0, 0))

ウィンドウ初期位置

ウィンドウ初期位置はpgzrunをインポートする前に以下のようにして変更します。

import os os.environ['SDL_VIDEO_WINDOW_POS'] = "100,100"

1.3 PyGame Zeroの関数

PyGame Zeroは、以下の定義された関数を自動的に繰り返し呼び出すことでゲームを動作させます。

関数名 役割 呼び出し頻度
update() 更新処理 毎フレーム(通常 60 FPS)
draw() 画面の描画 毎フレーム(通常 60 FPS)
on_key_down() キーが押されたとき イベント発生時
on_mouse_down() マウスがクリックされたとき イベント発生時

Fps

frame per second 1秒間に何回画面が更新されるか。

1.4 画像の描画

画像を描画するには、まず、imagesフォルダに対象画像を保存します。

画像の例として、KENNYの2Dアセットの中からPlatformer Art Deluxeをダウンロードし、Extra animations and enemiesフォルダ内のAlien sprites内にある alienPink.png を使用します。

ファイル名は小文字のみですので名前をalien.pngに変更し、imagesフォルダに保存します。

最初にActorオブジェクトを生成します。 コンストラクタの最初の引数には画像ファイル名(拡張子省略)を指定します。pos引数に位置を指定します(画像の中心座標)。

alien = Actor('alien', pos=(100,50))

drawメソッドでalienオブジェクトのdrawメソッドを呼び出し描画します。

def draw():
    alien.draw()

Actorの警告

VSCodeではActorなど組み込みのクラスに警告が出ます。以下で回避できます(screenは回避できません)

from pgzero.builtins import *

1.5 画像の移動

画像を動かしてみます。一定時間ごとに自動的に呼び出されるupdate関数内で、alienオブジェクトの位置プロパティ(left(左上)やtop(上)など)を変更します。 移動させるには、画像の座標を変えます。

def update():
    alien.left += 2

ただし、このままでは前の画像が残ってしまいます。 そこで、drawの描画を行うときに、いったんスクリーンをクリアします。

def draw():
    screen.clear()
    alien.draw()

画像の速度は2で固定なのでこれを変数にしてみます。 alineオブジェクトを生成した後に、vx 属性に 2 を入れます。

alien = Actor('alien', pos=(100,50))
alien.vx = 2

そして、それをupdateで足すようにします。

def update():
    alien.left += alien.vx

1.6 キーボードの処理

キーを押したときに何かが起こるようにしてみます。 キーを押したらon_key_downメソッドが自動的に呼ばれます。 そのとき、引数 key にはどのキーを押したかが入っています。

左右の矢印キーで移動方向を変えるようにしてみます。

def on_key_down(key):
    if key == keys.RIGHT:
        alien.vx = 2
    elif key == keys.LEFT:
        alien.vx = -2

上下の移動も出来るようにします。まず、vx以外にvyも作ります。vxもvyも0で初期化します。

alien = Actor('alien', pos=(100,50))
alien.vx = 0
alien.vy = 0

update関数でvyをtopに足すようにします。topは上の座標を表します。

def update():
    alien.left += alien.vx
    alien.top += alien.vy

上キー、下キーでvyを変化させます。

def on_key_down(key):
    if key == keys.RIGHT:
        alien.vx = 2
    elif key == keys.LEFT:
        alien.vx = -2
    elif key == keys.UP:
        alien.vy = -2
    elif key == keys.DOWN:
        alien.vy = 2

1.7 外に出ないように

現状では画面の外にキャラクターが移動してしまいます。 これを移動しないようにするには update関数でleftとtopの値を更新した後に、外に出ていないかをチェックします。

まず左右をチェックします。

    if alien.right > WIDTH:
        alien.right = WIDTH
    elif alien.left < 0:
        alien.left = 0

次に上下をチェックします。

    if alien.bottom > HEIGHT:
        alien.bottom = HEIGHT
    elif alien.top < 0:
        alien.top = 0

1.8 衝突判定

ゲームの目的として、他のアイテムの場所まで移動させることとします。 アイテムとして cherry (Candy Expansion配下) を右下に置きます。

cherry = Actor('cherry', pos=(750,550))

draw関数でcherryを表示します。

def draw():
    screen.clear()
    alien.draw()
    cherry.draw()

alienとcherryが衝突したかどうかは、colliderect関数で判定します。 衝突したら gameclear関数を呼ぶようにします。

def update():
    alien.left += alien.vx
    alien.top += alien.vy

    # cherryとの衝突判定
    if alien.colliderect(cherry):
        gameclear()

gameclear関数ではalienが動かなくなるように vx と vy を 0 にします。

def gameclear():
    alien.vx = 0
    alien.vy = 0

1.9 文字の表示

ゲームのクリアを判定して、クリアしたら CLEARの文字を表示することにします。 まず、ゲーム開始時にはクリアしていないことを示すために、alien.clear に False を入れておきます。

alien = Actor('alien', pos=(100,50))
alien.vx = 0
alien.vy = 0
alien.clear = False

ゲームクリア時に、alien.clear に True を入れます。

def gameclear():
    alien.vx = 0
    alien.vy = 0
    alien.clear = True

alien.clear が Trueなら画面に「CLEAR!」を出します。 screen.draw.text(文字, 位置, color=色, fontsize=フォントサイズ) で指定します。 このとき、位置は center=(x,y) と指定することで文字の位置の中央を指定できます。

def draw():
    screen.clear()
    alien.draw()
    cherry.draw()
    if(alien.clear):
        screen.draw.text("CLEAR!", center=(400, 200), color=(255,255,255), fontsize=48)

日本語の表示

日本語の表示はフォントを指定しないと出来ません。fontフォルダを配下に作成しフォントファイルを置きます。screen.draw.textの引数にfontname=でファイル名を指定します。 例:IPAゴシックの場合

screen.draw.text("クリア!", center=(400, 200), color=(255,255,255), fontsize=4, fontname='ipaexg.ttf')

1.10 マウスクリック

エイリアンをクリックしたら何かが起こるようにします。 そのためには、on_mouse_down関数を定義します。

def on_mouse_down(pos):
    print(pos)

引数posにはクリックした位置が入っています。マウスをクリックするとその座標がコンソールに出力されます。

画像をクリックしたら、という判定には、Actorクラスのcollidepointメソッドを使います。 collideとは衝突という意味です。その場所がActorに衝突しているかが分かります。

def on_mouse_down(pos):
    if alien.collidepoint(pos):
        print("Hit!")

画像をクリックしたら、画像を変更してみます。 alienPink_hurt.png を alien_hurt.png に名前変更し、imagesに置きます。 Actorのimageプロパティを変更すると、画像が変わります。

def on_mouse_down(pos):
    if alien.collidepoint(pos):
        alien.image = 'alien_hurt'

1.11 クロック

一定時間後に何かをしたい場合にはclockを使います。 例えば、画像をクリックして画像が変わった後、一定時間後に元にもどしたい場合などです。

clockのschedule_uniqueを使うと一定時間後に特定の関数を一回のみ呼び出すことが出来ます。

def on_mouse_down(pos):
    if alien.collidepoint(pos):
        alien.image = 'alien_hurt'
        clock.schedule_unique(set_alien_normal, 0.5)

この例ではset_alien_normal関数を0.5秒後に呼び出しています。 set_alien_normal関数では、画像を通常のものに戻します。

def set_alien_normal():
    alien.image = 'alien'

1.12 描画

四角形の描画を行うには screen.draw.rect(範囲, 色) で行います。 範囲はRect((x,y), (幅,高さ)) で指定します。

xが300、yが250の地点で50×50の四角形を書いてみます。 まず、範囲をboxという変数に入れます。

box = Rect((300, 250), (50, 50))

draw関数内に以下を書き、赤色で表示します。

screen.draw.rect(box, "red")

塗りつぶすにはfilled_rectを使用します。

screen.draw.filled_rect(box, "red")

これに衝突したら、ゲームオーバーにしてみます。 まず、ゲームオーバーフラグを作成し、Falseにしておきます。

alien.game_over = False

update関数内の最後でboxに衝突したら、このフラグをTrueにします。

if alien.colliderect(box):
    alien.game_over = True

draw関数内でゲームオーバーになったら、表示を行います。

if(alien.game_over):
    screen.draw.text("GAME OVER!", center=(400, 200), color=(255,255,255), fontsize=48)

ゲームオーバーになったら画面を更新しないようにupdate関数でreturnします。

if alien.game_over:
    return