Pygame Zero③ スプライトとイベント処理

Image from Gyazo

スプライトとイベント処理

スプライト(Sprite)とは,ゲームにおいてキャラクターをスクリーンに合成表示させるための仕組みのことです. 背景に対して,キャラクター・物体・文字などのスプライトを重ねて表示させることができます. CPU処理能力が低かったファミコンなどのゲーム機においてはハードウェアとして実装されていましたが, 現在のゲームにおいては,同様の機能がソフトウェアで実現され,疑似スプライトなどと呼ばれています. ここでは,位置の変更を伴うキャラクター画像のことを「スプライト」と考えれば良いです. スプライト用の画像は,様々なサイトで提供されていますが,KENNYで公開されているフリー画像を利用することにします. KENNYが提供しているアセット(素材)は,一部を除きCC0のライセンスであり,パブリックドメインとして自由に利用が可能です. また,キャラクターを動かすには,マウスやキーボードなどのイベント処理が必要となります. スプライトの使い方と合わせて,イベント処理についても学びましょう.

Image from Gyazo

Image from Gyazo

準備

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

WIDTH = 640
HEIGHT = 480

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

スプライトの表示

KENNYからPlatformer Charactersをダウンロードしましょう. このアセットには,プレイヤー(Player),女性(Female),冒険家(Adventurer),戦士(Soldier),ゾンビ(Zombie)の5種類のキャラクターが含まれています. この中から,プレイヤー(Player)に該当する24種類のPNG画像(player_idle.pngplayer_walk1.pngなど)を,新規作成した imagesフォルダ を作成し,コピーして配置します.

Image from Gyazo

Actorクラス

Pygame Zeroには,スプライトを扱うためのActorクラスが用意されています. Actorクラスには,位置を表すxy,画像ファイルを表すimageなどの変数と, スクリーンに表示するためのdraw(),他のスプライトと衝突を判定するcollidepoint()colliderect()などの関数が実装されています.

それでは,Actorクラスを利用して,画像ファイルplayer_idle.pngをスプライトとして表示させます. このとき,スプライトの位置は,スクリーンの中央とします. また,スプライトをスクリーンに表示させるにはdraw()を用います.

# スプライトを生成
player = Actor("player_idle", center=(WIDTH/2, HEIGHT/2))

def draw():
    screen.fill("white")
    player.draw()  # スプライトを描画

Image from Gyazo

スプライトの位置を設定には アンカーポイント を用いることができます. アンカーポイントとして9種類が用意されており,centerは画像の中央,topleftは画像の左上が,指定された座標と一致するよう配置されます.

Image from Gyazo

# スプライトを生成
player = Actor("player_idle", topleft=(WIDTH/2, HEIGHT/2))

def draw():
    screen.fill("white")
    player.draw()  # スプライトを描画

Image from Gyazo

スプライトを回転させるには,angleを用います. 90に設定すれば反時計回りに90度,180に設定すれば半時計周りに180度回転します(時計回りに回転させるには負の値を設定すれば良い). このとき,回転の中心はアンカーポイントとなることに注意してください.

player = Actor("player_stand", center=(WIDTH/2, HEIGHT/2))
player.angle = 90

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

Image from Gyazo

例題1

次の図を参考に,スプライトをスクリーンの下部に揃えて表示してください, このとき,画像はplayer_stand.png,アンカーポイントはmidbottomを利用すること.

Image from Gyazo

イベント処理

キーボードのイベント処理

キーボードを利用したイベント処理を利用して,プレイヤー(スプライト)を左右に移動させてみましょう. キーボードのイベントを検出するには,keyboardオブジェクトを利用するだけです. 例えば,右向きのカーソルキーが押されているかどうかを検出するには, keyboard.rightTrueであるかをif文で判定すれば良いです(判定可能なキーの一覧). ここでは,右向きのカーソルキーが押されていると右方向に5だけ移動し, 左向きのカーソルキーが押されていると左方向に5だけ移動します.

player = Actor("player_stand", midbottom=(WIDTH/2, HEIGHT))

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

def update():

    if keyboard.right: # 右向きのカーソルキー
        player.x = player.x + 5
    elif keyboard.left: # 左向きのカーソルキー		
        player.x = player.x - 5

Image from Gyazo

キーが押されているときに,プレイヤーの画像も変更してみます. ここでは,右向きのカーソルキーが押されているとplayer_walk1.pngを表示し, 左向きのカーソルキーが押されているとplayer_walk2.pngを表示します. また,何もキーが押されていないときはplayer_stand.pngを表示します.

player = Actor("player_stand", midbottom=(WIDTH/2, HEIGHT))

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

def update():
    if keyboard.right:
        player.x = player.x + 5
        player.image = "player_walk1"
    elif keyboard.left:
        player.x = player.x - 5
        player.image = "player_walk2"
    else:
        player.image = "player_stand"

Image from Gyazo

例題2

次の図を参考に,上向きのカーソルキーを押すと,画像をplayer_hold1.pngに変更してください,

Image from Gyazo

マウスのイベント処理

KENNYHoliday Pack 2016に収録されている プレゼントの画像item.pngをダウンロードして,imagesフォルダにコピーしてください.

Image from Gyazo

上記のプレゼントの画像をアイテムとして,マウスがクリックされた位置のX座標に表示させます. 複数のアイテムを表示させるため,リストitem_listを宣言します. マウスのイベントを検出するには,on_mouse_down(pos)を用います. 引数のposはマウスがクリックされた座標を表しており,X座標はpos[0],Y座標はpos[1]で参照します. ここでは,アイテムのX座標をpos[0],Y座標を0に設定します. アイテムを表示させるには,for文を利用して,リストから一つずつアイテムを取り出し,draw()を実行します.

player = Actor("player_stand", midbottom=(WIDTH/2, HEIGHT))

# アイテムのリスト
item_list = []

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

	# アイテムを表示
    for item in item_list:
        item.draw()

def update():
    if keyboard.right:
        player.x = player.x + 5
        player.image = "player_walk1"
    elif keyboard.left:
        player.x = player.x - 5
        player.image = "player_walk2"
    elif keyboard.up:
        player.image = "player_hold1"
    else:
        player.image = "player_stand"

# マウスのイベント処理
def on_mouse_down(pos):
    item = Actor("item", center=(pos[0], 0))
    item_list.append(item)  # リストに追加

Image from Gyazo

アイテムを上部から落下させます. update()の中で,for文を利用して,リストから一つずつアイテムを取り出し,Y座標に1だけ加算します.

player = Actor("player_stand", midbottom=(WIDTH/2, HEIGHT))

item_list = []

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

    for item in item_list:
        item.draw()

def update():
    if keyboard.right:
        player.x = player.x + 5
        player.image = "player_walk1"
    elif keyboard.left:
        player.x = player.x - 5
        player.image = "player_walk2"
    elif keyboard.up:
        player.image = "player_hold1"
    else:
        player.image = "player_stand"

	# アイテムの落下
    for item in item_list:
        item.y = item.y + 1

def on_mouse_down(pos):
    item = Actor("item", center=(pos[0], 0))
    item_list.append(item)

Image from Gyazo

プレイヤーとアイテムの衝突を検知するには,colliderect()を利用します. 衝突が検出されたときはTrue,検出されないときはFalseとなります. ここでは,上方向のキーボードが押されているときに,プレイヤーとアイテムの衝突が検知されれば,アイテムを非表示にします. アイテムを非表示にするには,アイテムの座標はスクリーンの外部に設定します(pygame zeroのバージョン1.3なら透明度opacityでも代替可能).

player = Actor("player_stand", midbottom=(WIDTH/2, HEIGHT))

item_list = []

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

    for item in item_list:
        item.draw()

def update():
    if keyboard.right:
        player.x = player.x + 5
        player.image = "player_walk1"
    elif keyboard.left:
        player.x = player.x - 5
        player.image = "player_walk2"
    elif keyboard.up:
        player.image = "player_hold1"

		# アイテムとの衝突処理
        for item in item_list:
            if(player.colliderect(item)):
                item.x = -9999  # スクリーン外に移動
                item.y = -9999
    else:
        player.image = "player_stand"

    for item in item_list:
        item.y = item.y + 1

def on_mouse_down(pos):
    item = Actor("item", center=(pos[0], 0))
    item_list.append(item)

Image from Gyazo

課題

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

Image from Gyazo

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

参考書籍

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