【Pygame Zero】簡単なゲーム04:ジャンプして風船を割ろう!
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Happiness_is_everywhere 」 by Tinymemory
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Heal [04] (Short. Low)」:回復
・ 「Jump [01] (High)」:アクションゲーム
・ 「Synthesizer [07] Vibrato Bass」:シンセサイザーで作った音(分類できないもの)

基礎プログラムと 画像を入れた
「簡単なゲーム04 ジャンプして タッチ!」zipフォルダを ダウンロードしてください


今回は、スクリーンの色を “honeydew“に したよ
「原色大事典」サイトには、URL:https://www.colordic.org/
pygame zeroで使える色が載っています

学習の流れ
スペースキーを押すと ジャンプする
4つの風船をタッチすると クリア
コウモリに 触れたら ゲームオーバー
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Happiness_is_everywhere 」 by Tinymemory
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Heal [04] (Short. Low)」:回復
・ 「Jump [01] (High)」:アクションゲーム
・ 「Synthesizer [07] Vibrato Bass」:シンセサイザーで作った音(分類できないもの)
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する


モジュールとは、
関数やプログラムが書かれているファイルのことだよ

Actor()クラスが入っている変数boonには、
boonを 動かす属性(データ)やメソッド(命令)が あります。


属性(データ)やメソッド(命令)は、
『 . (ドット)』を付ければ、使えるよ
今回のプログラミングのポイント

今回は、
boonが ジャンプするプログラムを作っていきます。

ジャンプの上方向:-(マイナス)
下方向:+(プラス)


リストballoonsを作成して、その中に4個の風船を入れるよ

balloons[:]は、リストballoonsのコピー と覚えてね

この3つのステップで
コスチュームを 切り替えることができるよ


3つに 分けたよ
スペースキーを押すと ジャンプする

ジャンプのプログラムを作っていきます。
boonオブジェクトに 2つのプロパティ
・ jump_speed : ジャンプの時にboonが上下に動く長さを保存
・ on :地面に着地したか判定(True/ False)
を 追加します。

boon = Actor("boon", (400, 200))
boon.jump_speed = 0 #1 追加プロパティjump_speed: 0 に設定する
boon.on = False #2 追加プロパティon: False に設定するdef boon_jump(): #3 boonのジャンプを 定義する
if not boon.on: #4 もし プロパティonが False なら
boon.jump_speed += 0.5 #5 プロパティjump_speedを 0.5ずつ 増やす
boon.y += boon.jump_speed #6 boonのy座標を プロパティjump_speedずつ 増やす
if boon.collide_pixel(ground): #7 もし 地上に触れたら
boon.on = True #8 プロパティon:Tureに設定する
boon.jump_speed = 0 #9 プロパティjump_speedに 0を設定する
boon.bottom = ground.top #10 boonのプロパティbottom(下)を 地面のプロパティtop(上)のデータを設定するdef update():
boon_jump() #11 boonが ジャンプする
おおっ!着地したぞ

次に スペースキーを押したら
プロパティjump_speedを -20 に設定するよ
これで、boonは ジャンプしちゃうんだ
game = "play" #1 変数game を宣言 初期値:playdef on_key_down(key): #2 キーを押す関数を 定義する
if key == keys.SPACE and boon.on and game == "play": #3 もし スペースキーで プロパティonが True かつ 変数gameが playだったら
boon.jump_speed = -20 #4 プロパティjump_speedを -20に設定する
boon.on = False #5 プロパティonを Falseに設定する
ジャンプだ!

次に、左右キーを押したら boonが左右に動くよう
boon_move( ) 関数を 定義するよ
プロパティright と left を使って
左右の端で止まるようにしました。

def boon_move(): #1 boonの動きを 定義する
if game == "play": #2 もし 変数gameが playなら
if keyboard.right: #3 もし 右キーが 押されたら
if boon.right < WIDTH: #4 もし boonの右端が WIDTHより小さければ
boon.x += 5 #5 boonのx座標を 5ずつ増やす
boon.flip_x = False #6 boonを反転させない
elif keyboard.left: #6 もし 左キーが 押されたら
if boon.left > 0: #7 もし boonの左端が 0より大きかったら
boon.x -= 5 #8 boonのx座標を 5ずつ減らす
boon.flip_x = True #9 boonを反転させるdef update():
boon_jump()
boon_move() #10 boon_move()関数を 実行する

左右の端で 止まったね。
プロパティ:flip_x で、boonの向きを 進む方向にしたよ
4つの風船にタッチすると クリア

つぎは、空のリストballoons を作成して、
4個の風船を スクリーンに 表示します。

balloons = [] #1 リストballoonsに 空リストを代入する
for i in range(4): #2 4回繰り返す カウント変数 i: 0, 1, 2, 3
x = 100 + 200 * i #3 x座標に 100+200 × i を代入する
y = 80 #4 y座標に 80 を代入する
balloon = Actor("balloon", (x, y)) #5 風船を 生成する
balloons.append(balloon) #6 リストballoonsに 風船を追加するdef draw():
screen.fill("honeydew")
for balloon in balloons: #7 リストballoonsから 風船を取り出す
balloon.draw() #8 風船を 表示する
boon.draw()
ground.draw()

風船が きれいに並んだね

boonが風船にタッチしたか判定する関数
def check_balloon_touch( ) を 定義します。
collide_pixel( )メソッドを使って
boonに触れたか 判定します。



remove( )メソッドを使って
リストballoonsから 風船を 削除するよ

def check_balloon_touch(): #1 check_balloon_touch()関数を 定義する
global game #2 グローバル変数 game
if game == "play": #3 もし 変数gameが playなら
for balloon in balloons[:]: #4 コピーリストballoonsから 風船を取り出す
if balloon.collide_pixel(boon): #5 もし 風船がboonに 触れたら
balloons.remove(balloon) #6 リストballoonsから 風船を 削除するdef update():
boon_jump()
boon_move()
check_balloon_touch() #7 check_balloon_touch()関数を 実行するここで、リストballoons の中の風船を削除する場合
for balloon in balloons[:] で、リストballoons のコピーを使うか
解説します。
もし、リストbatsで コウモリを取り出すと
82. for balloon in balloons:
84. balloons.remove(balloon)
リストballoons から 風船を取り出している最中に 削除すると
風船の取り出し方が変になり、 エラーが起きる場合があります。

ああっ!
風船「2」が 飛ばされてるね
ポイント1
リストballoons を コピーして リストballoons[:]にする
82. for balloon in balloons[;]
84. balloons.remove(balloon)
元のリストballoons から風船を削除しても、
コピーしたリストballoons[:]には影響しません。

なるほどね!
リストballoons[ : ] は、
最後の風船を取り出してからコピーするんだね

それでは、
風船が全部タッチされたら クリアになるプログラムを作ります。
len( ) 関数を使って 風船が 『0』になったら
変数bg_image に 画像『bg_clear』を代入しましょう

bg_image = None #1 変数bg_image を宣言 初期値:None(無し)
def draw():
if game == "play": #2 もし 変数gameが playなら
screen.fill("honeydew")
else: #3 その他は
screen.blit(bg_image, (0, 0)) #4 変数bg_imageを 表示するdef check_balloon_touch():
global game, bg_image #5 グローバル変数bg_image
if game == "play":
for balloon in balloons[:]:
if balloon.collide_pixel(boon):
balloons.remove(balloon)
if len(balloons) == 0: #6 もし リストballoonsの要素が 0 なら
game = "clear" #7 変数gameに clearを代入する
bg_image = "bg_clear" #8 変数bg_imageに 画像bg_clearを 代入する
boon.image = "boon_clear" #9 boonのプロパティimageに 画像boon_clearを設定するコウモリに 触れたら ゲームオーバー

つぎに、コウモリをランダムに動くようにします。
まず、コスチュームモジュールを使って
コウモリの羽を ばたつかせるよ
bat = Actor("bat1", (700, 100))
bat.images = ["bat1", "bat2"] #1 プロパティimagesに リスト[画像bat1, bat2]を セットする
bat.fps = 20 #2 プロパティfpsを 20に設定するdef update():
boon_jump()
boon_move()
bat.animate() #3 コスチュームの切り替えをする
animate( )関数を 使って ランダムに 動かしましょう

def bat_move(): #1 コウモリの動きを 定義する
x = random.randint(50, WIDTH-50) #2 xに 50~750から ランダムに決めた値を 代入する
y = random.randint(50, 200) #3 yに 50~200から ランダムに決めた値を 代入する
time = random.uniform(0.5, 2.0) #4 timeに 0.5~2.0から ランダムに決めた値を代入する
animate(bat, pos=(x, y), duration = time, on_finished=bat_move) #5 コウモリの動きを アニメーションする
bat_move() #6 bat_move( )関数を 実行する
おおっ! いいねぇ
on_finished = bat_move で、bat_move()関数が 繰り返されるんだね

collide_pixel( )メソッドを使って
boonが コウモリに 触れたら ゲームオーバーにします。
背景画像”bg_over“を 表示させましょう
def boon_jump():
global game, bg_image #1 グローバル変数bg_image
if not boon.on:
boon.jump_speed += 0.5
boon.y += boon.jump_speed
if boon.collide_pixel(bat) and game == "play": #2 もし boonが コウモリに触れ かつ 変数gameが playだったら
game = "over" #3 変数gameに overを代入する
bg_image = "bg_over" #4 変数bg_imageに 画像bg_overを 代入する
boon.image = "boon_over" #5 プロパティimageに 画像boon_overを設定する
変数gameが “over“になったから
キーを 押しても boonが 動かないね
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Happiness_is_everywhere 」 by Tinymemory
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Heal [04] (Short. Low)」:回復
・ 「Jump [01] (High)」:アクションゲーム
・ 「Synthesizer [07] Vibrato Bass」:シンセサイザーで作った音(分類できないもの)

それでは、BGMを 入れてみましょう
Python zeroには、musicオブジェクトが標準装備であります。
やり方、以下の手順です
BGM の 流し方
1. MP3ファイルのBGMを 用意する

☆ Pygame zeroでは英語の大文字が 使えません。 エラーが出ます
小文字 に直します
2. フォルダ『music』フォルダに 入れる

3. musicモジュールのメソッドを使う


今回は、set_volume()メソッドを使って
BGMの音量を 調整したよ
def boon_jump():
global game, bg_image
if not boon.on:
boon.jump_speed += 0.5
boon.y += boon.jump_speed
if boon.collide_pixel(bat) and game == "play":
game = "over"
bg_image = "bg_over"
boon.image = "boon_over"
music.stop() #3 BGMを 止める (ゲームオーバー)def check_balloon_touch():
global game, bg_image
if game == "play":
for balloon in balloons[:]:
if balloon.collide_pixel(boon):
balloons.remove(balloon)
if len(balloons) == 0:
game = "clear"
bg_image = "bg_clear"
boon.image = "boon_clear"
music.stop() #4 BGMを 止める (クリア)music.play("happiness_is_everywhere") #1 BGMを 入れる
music.set_volume(0.5) #2 BGMの音量を 50%に する
今回のプログラムに「DOVA-SYNDROME」サイトから
・ 「Happiness_is_everywhere 」 by Tinymemory
BGMの曲として お借りしました。 ありがとうございます。

つぎに
効果音をつけましょう!
・ ジャンプした時
・ 風船に タッチした時
・ クリア
・ ゲームオーバー
Python zeroには、soundsオブジェクトが標準装備であります。
次の手順で 行います
効果音のつけ方
1. WAVファイルの効果音を 用意する




2. フォルダ『sounds』フォルダに 入れる

3. soundsモジュールのplay( )メソッドを使う


今回のプログラムに
「Chisato’s Website」サイトから
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Heal [04] (Short. Low)」:回復
・ 「Jump [01] (High)」:アクションゲーム
・ 「Synthesizer [07] Vibrato Bass」:シンセサイザーで作った音(分類できないもの)
効果音を お借りしました。 ありがとうございます。
def boon_jump():
global game, bg_image
if not boon.on:
boon.jump_speed += 0.5
boon.y += boon.jump_speed
if boon.collide_pixel(bat) and game == "play":
game = "over"
bg_image = "bg_over"
boon.image = "boon_over"
music.stop()
sounds.synthesizer_07_vibrato_bass.play() #4 ゲームオーバーの効果音を入れるdef on_key_down(key):
if key == keys.SPACE and boon.on and game == "play":
boon.jump_speed = -20
boon.on = False
sounds.jump_01_high.play() #2 ジャンプの効果音を 入れるdef check_balloon_touch():
global game, bg_image
if game == "play":
for balloon in balloons[:]:
if balloon.collide_pixel(boon):
sounds.heal_04_short_low.play() #2 風船にタッチした効果音を入れる
balloons.remove(balloon)
if len(balloons) == 0:
game = "clear"
bg_image = "bg_clear"
boon.image = "boon_clear"
music.stop()
sounds.accent_brilliant_02_low.play() #3 クリアの効果音を入れる
今回の学習は、これで 終了! おつかれさま
まとめ

今回は、
boonが ジャンプするプログラムを 作りました。
import pgzrun
from pgzhelper import *
import random
WIDTH = 800
HEIGHT = 600
boon = Actor("boon", (400, 200))
boon.jump_speed = 0
boon.on = False
balloons = []
for i in range(4):
x = 100 + 200 * i
y = 80
balloon = Actor("balloon", (x, y))
balloons.append(balloon)
bat = Actor("bat1", (700, 100))
bat.images = ["bat1", "bat2"]
bat.fps = 20
ground = Actor("ground", midbottom = (400, 600))
game = "play"
bg_image = None
def draw():
if game == "play":
screen.fill("honeydew")
else:
screen.blit(bg_image, (0, 0))
for balloon in balloons:
balloon.draw()
bat.draw()
boon.draw()
ground.draw()
def boon_jump():
global game, bg_image
if not boon.on:
boon.jump_speed += 0.5
boon.y += boon.jump_speed
if boon.collide_pixel(bat) and game == "play":
game = "over"
bg_image = "bg_over"
boon.image = "boon_over"
music.stop()
sounds.synthesizer_07_vibrato_bass.play()
if boon.collide_pixel(ground):
boon.on = True
boon.jump_speed = 0
boon.bottom = ground.top
def on_key_down(key):
if key == keys.SPACE and boon.on and game == "play":
boon.jump_speed = -20
boon.on = False
sounds.jump_01_high.play()
def boon_move():
if game == "play":
if keyboard.right:
if boon.right < WIDTH:
boon.x += 5
boon.flip_x = False
elif keyboard.left:
if boon.left > 0:
boon.x -= 5
boon.flip_x = True
def check_balloon_touch():
global game, bg_image
if game == "play":
for balloon in balloons[:]:
if balloon.collide_pixel(boon):
sounds.heal_04_short_low.play()
balloons.remove(balloon)
if len(balloons) == 0:
game = "clear"
bg_image = "bg_clear"
boon.image = "boon_clear"
music.stop()
sounds.accent_brilliant_02_low.play()
def bat_move():
x = random.randint(50, WIDTH-50)
y = random.randint(50, 200)
time = random.uniform(0.5, 2.0)
animate(bat, pos=(x, y), duration = time, on_finished=bat_move)
bat_move()
def update():
boon_jump()
boon_move()
check_balloon_touch()
bat.animate()
music.play("happiness_is_everywhere")
music.set_volume(0.5)
pgzrun.go()
ジャンプのプログラムを作る時は、
プロパティjump_speedを 追加して boonを上下に 動かそう

プロパティon を 使って
boonが 着地したかどうか判定することを 忘れないでね


ジャンプの仕組みで、マリオみたいなゲームも作れるね
それじゃ、またね!
