Pygame Zero③ スプライトとイベント処理
スプライトとイベント処理
スプライト(Sprite)とは,ゲームにおいてキャラクターをスクリーンに合成表示させるための仕組みのことです. 背景に対して,キャラクター・物体・文字などのスプライトを重ねて表示させることができます. CPU処理能力が低かったファミコンなどのゲーム機においてはハードウェアとして実装されていましたが, 現在のゲームにおいては,同様の機能がソフトウェアで実現され,疑似スプライトなどと呼ばれています. ここでは,位置の変更を伴うキャラクター画像のことを「スプライト」と考えれば良いです. スプライト用の画像は,様々なサイトで提供されていますが,KENNYで公開されているフリー画像を利用することにします. KENNYが提供しているアセット(素材)は,一部を除きCC0のライセンスであり,パブリックドメインとして自由に利用が可能です. また,キャラクターを動かすには,マウスやキーボードなどのイベント処理が必要となります. スプライトの使い方と合わせて,イベント処理についても学びましょう.
準備
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.png
,player_walk1.png
など)を,新規作成した imagesフォルダ を作成し,コピーして配置します.
Actorクラス
Pygame Zeroには,スプライトを扱うためのActorクラスが用意されています.
Actorクラスには,位置を表すx
,y
,画像ファイルを表す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() # スプライトを描画
スプライトの位置を設定には アンカーポイント を用いることができます.
アンカーポイントとして9種類が用意されており,center
は画像の中央,topleft
は画像の左上が,指定された座標と一致するよう配置されます.
# スプライトを生成
player = Actor("player_idle", topleft=(WIDTH/2, HEIGHT/2))
def draw():
screen.fill("white")
player.draw() # スプライトを描画
スプライトを回転させるには,angle
を用います.
90
に設定すれば反時計回りに90度,180
に設定すれば半時計周りに180度回転します(時計回りに回転させるには負の値を設定すれば良い).
このとき,回転の中心はアンカーポイントとなることに注意してください.
player = Actor("player_stand", center=(WIDTH/2, HEIGHT/2))
player.angle = 90
def draw():
screen.fill("white")
player.draw()
例題1
次の図を参考に,スプライトをスクリーンの下部に揃えて表示してください,
このとき,画像はplayer_stand.png
,アンカーポイントはmidbottom
を利用すること.
イベント処理
キーボードのイベント処理
キーボードを利用したイベント処理を利用して,プレイヤー(スプライト)を左右に移動させてみましょう.
キーボードのイベントを検出するには,keyboard
オブジェクトを利用するだけです.
例えば,右向きのカーソルキーが押されているかどうかを検出するには,
keyboard.right
がTrue
であるかを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
キーが押されているときに,プレイヤーの画像も変更してみます.
ここでは,右向きのカーソルキーが押されていると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"
例題2
次の図を参考に,上向きのカーソルキーを押すと,画像をplayer_hold1.png
に変更してください,
マウスのイベント処理
KENNYのHoliday Pack 2016に収録されている
プレゼントの画像item.png
をダウンロードして,imagesフォルダにコピーしてください.
上記のプレゼントの画像をアイテムとして,マウスがクリックされた位置の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) # リストに追加
アイテムを上部から落下させます.
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)
プレイヤーとアイテムの衝突を検知するには,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)
課題
次の課題に取組んでください.
- スクリーンの左上にスコアを表示する
- 落下しているアイテムを拾えばスコアに10を加算する
- KENNYのPixel Shmupに収録されている画像broken.pngをダウンロードして,imagesフォルダにコピーする
- アイテムがスクリーンの下部に到達したとき,画像をbroken.pngに変更する
- 画像がbroken.pngになったアイテムは拾えないようにする
課題を完成させたらスクリプトを保存し,chapter10フォルダをZIPで圧縮してから,chapter10.zipという名前でファイルを提出してください.