【Pygame Zero】量産06:浮かび上がる風船をパンチしよう!
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Kirakira_ToyBox 」 by こうだつの
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Synth-Bell. E-Major [01A] (Monophonic)」:アクセント
・ 「Button [06-3] (Cancel)」:ボタン音

基礎プログラムと 画像を入れた
「量産06 風船に パンチ!」zipフォルダを ダウンロードしてください



今回は、blit( )メソッドを使って 背景画像を 入れてみたよ

学習の流れ
マウスで boonを 動かす
風船が 次々と 現れる
boonが 風船にパンチすると 消える
風船が 上の端に到着すると ゲームオーバー
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Kirakira_ToyBox 」 by こうだつの
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Synth-Bell. E-Major [01A] (Monophonic)」:アクセント
・ 「Button [06-3] (Cancel)」:ボタン音
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「風船に パンチ!」では、
・ boonが 風船にパンチする
・ 風船を 下の端から ランダムに 出現する
プログラムがあります。
そこで、2つのモジュールを 用意しました



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

今回は、
風船が 次々と現れて上がっていくプログラムを 作っていきます。
scratchで言う「クローン」。
pygama zeroでは、次の手順で プログラムします

リスト:balloonsを 作成して、その中にねずみを 追加していくんだ

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


それぞれの動きが わかりやすくなるよ


2つに 分けたよ
マウスで boonを 動かす

angle_to( ) メソッドで、
boonを マウスの方へ向くようにします

game = "play" #1 変数game 宣言 初期値:playdef on_mouse_move(pos): #2 マウスが動いた時 引数posに 座標が代入される
global game #3 グローバル変数 game
if game == "play": #4 もし 変数gameが playなら
boon.angle = boon.angle_to(pos) #5 boonの向きに マウスの方へ向く角度を 代入する
マウスが動くと、引数posの中に マウスの座標が 代入されるんだ

つぎは、
マウスオブジェクトにプロパティposを追加して、
move_towards( )メソッドを使って boonをマウスの方へ 動かします


mouse.pos = 400, 300 #1 プロパティ:posに (400, 300)を 代入するdef on_mouse_move(pos):
global game
if game == "play":
boon.angle = boon.angle_to(pos)
mouse.pos = pos #2 追加プロパティposに マウスの座標を代入する
def boon_move(): #3 boonの動きを 定義する
global game #4 グローバル変数 game
if game == "play": #5 もし 変数gameが playなら
boon.move_towards(mouse.pos, 5) #6 boonが マウスの方へ5pxずつ 動くdef update(): #7 更新する
boon_move() #8 boonを 動かす
これで、boon の動きは 完了です
風船が 次々を現れる

最初に
風船を作る関数:cleate_balloon( ) を定義します。
そして、
schedule_interval()メソッドを使って
0.5秒経ったら、風船を作っていきましょう

balloons = [] #1 リストballoonsに 空のリストを 代入する
def create_balloon(): #2 風船を作る関数を 定義する
x = random.randint(50, WIDTH-50) #3 x座標に 50~750からランダムに決めて代入する
y = HEIGHT #4 y座標に 590を代入する
balloon = Actor("balloon", (x, y)) #5 風船を 作る
balloon.speed = random.uniform(1,5) #6 追加プロパティspeedに 1~の間の小数をランダムに決める
balloons.append(balloon) #7 リストballoonsに 追加する
clock.schedule_interval(create_balloon, 0.5) #8 0.5秒ごとに 風船を作る
def draw():
screen.blit("bg", (0, 0))
boon.draw()
for balloon in balloons: #9 リストballoonsから 風船を取り出す
balloon.draw() #10 風船を 表示するdef cleate_balloon: 風船を作る定義
ポイント1
20. balloon.speed = random.uniform(1,5)

Actor( ) クラスは、自分でプロパティを作成し追加することができます
プロパティ:speed・・・風船の上へ動く速さ
これにより、風船が それぞれ違う速さで上へ動くようになります
ポイント2
21. balloons.append(balloon)

Actor( ) クラスで 作った風船を リストballoons に追加していきます。
ポイント3
23. clock.schedule_interval(cleate_balloon, 0.5)
schedule_interval( ) メソッドを使って
0.5秒ごとに 風船を作るcleate_balloon( ) 関数を実行します。

リストballoons は、0.5秒ごとに 風船が 追加されます。


ここまでが、風船が 作られるポイント!
まだ、スクリーンには 表示されないよ
def draw( ) : 風船を表示する
ポイント4
28. for balloon in balloons:
29. balloon.draw()
for 文を使って、リストballoons に入っている風船を
順番に 変数balloon に代入して draw( ) メソッドで 表示します。
これを一瞬で行います。
そして、リストに入っている風船が 表示されるよ


次に、プロパティ: speedを使って
風船を 動かしてみよう!
def balloon_move(): #1 風船の動きを 定義する
global game #2 グローバル変数 game
if game == "play": #3 もし 変数gameが play だったら
for balloon in balloons[:]: #4 コピーリストballoonsから 風船を取り出す
balloon.y -= balloon.speed #5 風船のy座標を プロパティspeedずつ減らすdef update():
boon_move()
balloon_move() #6 風船を 動かす
風船ごとにプロパティ:speedが 違うから 速さも違うね!
風船にパンチすると 消える

collide_pixel( ) メソッドを使って、boonが風船にパンチしたら
消えるようにするよ


def balloon_move():
global game
if game == "play":
for balloon in balloons[:]:
balloon.y -= balloon.speed
if balloon.collide_pixel(boon): #1 もし 風船に boonが衝突したら
balloons.remove(balloon) #2 リストballoonsから 風船を削除するポイント1
風船が 削除されるときは、リストballoonsをコピーして 風船を取り出す
50. for balloon in balloons[:]:
54. balloons.remove(balloon)
なぜ、
風船が削除される場合、リストコピーballoons[:]を使うか 解説します
もし、リストballoons のまま 風船を取り出すと
50. for balloon in balloons:
54. balloons.remove(balloon)
リストballoons から 風船を取り出している最中に 削除すると
風船の取り出し方が 変になり、 エラーが起きる場合があります。

ああっ!
風船「2」が 飛ばされるね
そこで、リストballoonsを コピーします。 balloons[:]
リストballoonsをコピーしたballoons[ : ]から 風船を取り出します。
50. for balloon in balloons[:]:
54. balloons.remove(balloon)
元のリストballoons から要素を削除しても、
コピーしたリストballoons[:]には影響しません。

なるほどね!
リストballoons[:] は、
最後の風船を取り出してから コピーするんだね
風船が 上の端に到着すると ゲームオーバー

風船が上の端に着いたら ゲームオーバーになります
clear( ) メソッドを使って、他の風船を 削除しましょう

message = Actor("message", (400, 300)) #6 メッセージを 生成するdef draw():
screen.blit("bg", (0, 0))
boon.draw()
for balloon in balloons:
balloon.draw()
if game == "over": #7 もし 変数gameが overなら
message.draw() #8 メッセージを 表示するdef balloon_move():
global game
if game == "play":
for balloon in balloons[:]:
balloon.y -= balloon.speed
if balloon.collide_pixel(boon):
balloons.remove(balloon)
if balloon.y <= 50: #1 もし 風船のy座標が 50以下なら
game = "over" #2 変数gameに overを代入する
clock.unschedule(create_balloon) #3 create_balloon()関数を 中止する
balloons.clear() #3 リストballoonsを 空にする
balloons.append(balloon) #4 リストballoonsに 風船を追加する
boon.image = "boon_ouch" #5 boonの画像を boon_ouchにするゲームオーバー
ポイント1
59. balloons.clear()
60. balloons.append(balloon)
リストballoonsを 空にしてから、
上端に来た風船だけを追加したよ

ポイント2
40. clock .unschedule(cleate_balloon)
unschedule( )メソッドを使って
cleate_balloon( )関数を中止します。


変数gameが “over“になったから
上の端にある風船は、動かないんだよ
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Kirakira_ToyBox 」 by こうだつの
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Synth-Bell. E-Major [01A] (Monophonic)」:アクセント
・ 「Button [06-3] (Cancel)」:ボタン音

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

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

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

def balloon_move():
global game
if game == "play":
for balloon in balloons[:]:
balloon.y -= balloon.speed
if balloon.collide_pixel(boon):
balloons.remove(balloon)
if balloon.y <= 50:
game = "over"
music.stop() #2 BGMを 止めるmusic.play("kirakira_toybox") #1 BGMを 流す
今回のプログラムに「DOVA-SYNDROME」サイトから
・ 「Kirakira_ToyBox 」 by こうだつの
BGMの曲として お借りしました。 ありがとうございます。

最後に
効果音をつけましょう!
・ 風船を パンチする音
・ 風船が 上端に到達した音
Python zeroには、soundsオブジェクトが標準装備であります。
次の手順で 行います
効果音のつけ方
1. WAVファイルの効果音を 用意する


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

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


今回のプログラムに
「Chisato’s Website」サイトから
・ 「Accent. Synth-Bell. E-Major [01A] (Monophonic)」:
アクセント
・ 「Button [06-3] (Cancel)」:ボタン音
効果音を お借りしました。 ありがとうございます。
def balloon_move():
global game
if game == "play":
for balloon in balloons[:]:
balloon.y -= balloon.speed
if balloon.collide_pixel(boon):
sounds.button_06_3_cancel.play() #1 効果音を入れる
balloons.remove(balloon)
if balloon.y <= 50:
sounds.accent_synth_bell_e_major_01a_mono.play() #2 効果音を入れるBGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「Kirakira_ToyBox 」 by こうだつの
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Synth-Bell. E-Major [01A] (Monophonic)」:アクセント
・ 「Button [06-3] (Cancel)」:ボタン音

これで、今回の学習は終了! おつかれさま
まとめ

今回は、
上へ動く風船を パンチするプログラムを 作りました。
import pgzrun
import random
from pgzhelper import *
WIDTH = 800
HEIGHT = 590
boon = Actor("boon", (400, 300))
message = Actor("message", (400, 300))
game = "play"
mouse.pos = 400, 300
balloons = []
def create_balloon():
x = random.randint(50, WIDTH-50)
y = HEIGHT
balloon = Actor("balloon", (x, y))
balloon.speed = random.uniform(1,5)
balloons.append(balloon)
clock.schedule_interval(create_balloon, 0.5)
def draw():
screen.blit("bg", (0, 0))
boon.draw()
for balloon in balloons:
balloon.draw()
if game == "over":
message.draw()
def on_mouse_move(pos):
global game
if game == "play":
boon.angle = boon.angle_to(pos)
mouse.pos = pos
def boon_move():
global game
if game == "play":
boon.move_towards(mouse.pos, 5)
def balloon_move():
global game
if game == "play":
for balloon in balloons[:]:
balloon.y -= balloon.speed
if balloon.collide_pixel(boon):
sounds.button_06_3_cancel.play()
balloons.remove(balloon)
if balloon.y <= 50:
sounds.accent_synth_bell_e_major_01a_mono.play()
game = "over"
music.stop()
clock.unschedule(create_balloon)
balloons.clear()
balloons.append(balloon)
boon.image = "boon_ouch"
def update():
boon_move()
balloon_move()
music.play("kirakira_toybox")
pgzrun.go()
風船の動きの速さを 変えたい時は
プロパティ:speedを 追加して ランダムに数字を代入しました

Actorクラスで作った風船は、
自分でプロパティを作って追加できるよ
それじゃ、またね!
