【Pygame Zero】量産03:複数のキャラクターを動かす
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「口笛ショッピング 」 by ゆうり(from Yuli Audio Craft)
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01a_mono」:アクセント

基礎プログラムと 画像を入れた
「量産03 ボールを よけろ!」zipフォルダを ダウンロードしてください



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

学習の流れ
マウスで boonを 動かす
ボールが 3秒ごと出現して ななめに動く
ボールに当たったらセリフを言う
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「口笛ショッピング 」 by ゆうり(from Yuli Audio Craft)
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01a_mono」:アクセント
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「本物を 探せ!」では、
・ boonが ボールに当たる
・ boonを ランダムな場所へ
・ boon が セリフを言う
プログラムが あります
そこで、3つのモジュールを 用意しました




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

今回は、
3個のボールを動かすプログラムを 作っていきます。
scratchで言う「クローン」。
pygama zeroでは、次の手順で プログラムします

リスト:balls作成して、その中に3個のボールを 入れるんだ


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


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 マウスの方へ 5pxずつ 動く
これで、boon の動きは 完了です
3秒ごと ボールが出現して 動く

まず、
3秒ごとに ボールを表示するプログラムを作ります。
ボールの数は3個までにします。

ボールを3個作るということは…⁉
scratchでいうクローンだ。
最初に空のリストを 作るんだったよね


schedule_interval( ) メソッドを使って
3秒ごとに ボールを 作るよ
balls = [] #1 リストballsに 空のリストを代入する
def draw():
screen.blit("background", (0, 0))
boon.draw()
for ball in balls: #10 リストballsから ボールを取り出して
ball.draw() #11 ボールを 表示するdef create_ball(): #2 ボールを作成する関数を 定義する
if len(balls) < 3: #3 もし リストballsの要素の数が 3未満なら
x = random.randint(35, WIDTH-35) #4 x座標に 35~765からランダムに決めて代入する
y = random.randint(35, HEIGHT-35) #5 y座標に 35~555からランダムに決めて代入する
ball = Actor("ball", (x, y)) #6 ボールを 作る
ball.angle = 45 #7 ボールの向きを 45度にする
balls.append(ball) #8 リストballsに 追加するclock.schedule_interval(create_ball, 3.0) #9 3秒ごとに ボールを作成するdef cleate_ball( ) : ボールを作る関数を 定義する
ポイント1
44. if len(balls) < 3:

ボールを作るのは、3個までと制限するために
len( ) 関数を使って
リストballsの要素の数が 2個までなら 作れるようにします
ポイント2
49. balls.append(ball)

Actor( ) クラスで ボールを作ったら リストballsに 追加していきます。
ポイント3
66. clock.schedule_interval(cleate_ball, 3.0)
schedule_interval( ) メソッドを使って
3秒ごとに ボールを作るcleate_ball関数を実行します。

リストballsには、3秒ごとに ボールが追加されます。


ここまでが、ボールが作られるポイント!
まだ、スクリーンには表示されないよ
def draw( ) : ボールを表示する
ポイント4
18. for ball in balls:
19. ball.draw( )
for 文を使って、リストballsに入っているボールを
順番に 変数ballに代入して draw( ) メソッドで 表示します。

リストに入っているボールが 表示されるよ


つぎは、
for 文を使ってboonを 動かします。
def ball_move(): #1 ボールを動かす関数を定義する
if game == "play": #2 もし 変数gameが playなら
for ball in balls: #3 リストballsから 順に取り出す
ball.move_forward(10) #4 ボールを 10pxずつ動かす
if ball.x < 35 or ball.x > WIDTH-35: #5 ボールのx座標が 35未満 または 765以上なら
ball.angle = 180 - ball.angle #6 ボールの向きに 180-ボールの向き の角度を代入する
if ball.y < 35 or ball.y > HEIGHT-35: #7 もし ボールのy座標が 35未満 または 555以上なら
ball.angle = -ball.angle #8 ボールの向きに -(ボールの向き)の角度を代入する
def update():
boon_move()
ball_move() #9 ボールを動かすボールの動き
ポイント
54. for
ball in balls:
55. ball.move_forward(10)
for 文を使って、リストballsからボールを取り出して
ボールを動かします
ポイント
ボールが 壁に跳ね返る角度の求め方です
57. if ball.x < 35 or ball.x > WIDTH-35:
58. ball.angle = 180 – ball.angle
59. if ball.y < 35 or ball.y > HEIGHT-35:
60. ball.angle = –ball.angle


おおっ! 3つのボールが 別々に 動いているぞ!
ボールに当たると セリフを言う

collidelist_pixel( )メソッドを使って、
ボールに当たったら セリフを言うようにします。

def draw():
screen.blit("background", (0, 0))
boon.draw()
for ball in balls:
ball.draw()
text_display.draw(screen) #1 テキストディスプレイを装備する
def boon_move():
global game
if game == "play":
boon.move_towards(mouse.pos, 5)
if boon.collidelist_pixel(balls) != -1: #2 もし ボールにぶつかったら
game = "over" #3 変数gameを overを代入する
clock.unschedule(create_ball) #4 ボールを作り出す関数を中止する
boon.image = "boon_ouch" #5 boonの画像を boon_ouchにする
boon.say("Ouch!", 2 , color= "red", size=70, y_offset=-70) #6 「Ouch!」と2秒間 言うボールに当たったら セリフを言う
ポイント1
15. def draw ( ):
20. text_display .draw ( screen )
39. boon.say ( “Ouch!”, 2 color = “red”, size = 70, y_offset = -70 )
boonに セリフを言わせるために、
draw( ) 関数の定義で テキストディスプレイを装備します。
say( ) メソッドを使って、 セリフを言わせよう

ポイント2
37. clock.unschedule ( cleate_ball )
1個目や2個目のボールに当たった場合、
schedule_interval ( cleate_ball, 3.0 ) メソッドは働いているため
それ以降も3個まで 出現してしまいます。
そのため、unschedule ( )メソッドで、
cleate_ball ( )関数を 止めます。


36. game = “over”
これによって、boonとボールの動きが止まったんだ
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「口笛ショッピング 」 by ゆうり(from Yuli Audio Craft)
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01a_mono」:アクセント

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

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

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

def boon_move():
global game
if game == "play":
boon.move_towards(mouse.pos, 5)
if boon.collidelist_pixel(balls) != -1:
game = "over"
clock.unschedule(create_ball)
music.stop() #2 BGMを 止める music.play("口笛ショッピング") #1 BGMを 流す
今回のプログラムに「DOVA-SYNDROME」サイトから
・ 「口笛ショッピング 」 by ゆうり(from Yuli Audio Craft)
BGMの曲として お借りしました。 ありがとうございます。

最後に
boonが ボールに当たった時に 効果音をつけましょう!
Python zeroには、soundsオブジェクトが標準装備であります。
次の手順で 行います
効果音のつけ方
1. WAVファイルの効果音を 用意する

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

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

今回のプログラムに『Chisato’s Website」サイトから
・ アクセント: accent_synth_bell_e_major_01a_mono
効果音を お借りしました。 ありがとうございます。
def boon_move():
global game
if game == "play":
boon.move_towards(mouse.pos, 5)
if boon.collidelist_pixel(balls) != -1:
game = "over"
clock.unschedule(create_ball)
music.stop()
sounds.accent_synth_bell_e_major_01a_mono.play() #1 効果音を 入れるBGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「口笛ショッピング 」 by ゆうり(from Yuli Audio Craft)
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01a_mono」:アクセント

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

今回は、
3個のボールを動かすプログラムを 作りました。
import pgzrun
from pgzhelper import *
import random
from say import text_display
WIDTH = 800
HEIGHT = 590
boon = Actor("boon", (400, 300))
game = "play"
mouse.pos = 400, 300
balls = []
def draw():
screen.blit("background", (0, 0))
boon.draw()
for ball in balls:
ball.draw()
text_display.draw(screen)
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)
if boon.collidelist_pixel(balls) != -1:
game = "over"
clock.unschedule(create_ball)
music.stop()
sounds.accent_synth_bell_e_major_01a_mono.play()
boon.image = "boon_ouch"
boon.say("Ouch!", 2 , color= "red", size=70, y_offset=-70)
def create_ball():
if len(balls) < 3:
x = random.randint(35, WIDTH-35)
y = random.randint(35, HEIGHT-35)
ball = Actor("ball", (x, y))
ball.angle = 45
balls.append(ball)
def ball_move():
if game == "play":
for ball in balls:
ball.move_forward(10)
if ball.x < 35 or ball.x > WIDTH-35:
ball.angle = 180 - ball.angle
if ball.y < 35 or ball.y > HEIGHT-35:
ball.angle = -ball.angle
def update():
boon_move()
ball_move()
clock.schedule_interval(create_ball, 3.0)
music.play("口笛ショッピング")
pgzrun.go()
複数のキャラクターを動かすときは、
for 文: for ball in balls: を使って
ball に 動かすプログラムを 書いていこう

1.リストballsから 順にボールを取り出して
2.ボールを 動かす
これを 一瞬で 行っているから
複数のキャラクターが動くように見えているんだ
すごいよね
それじゃ、またね!
