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


スックです。よろしくね!
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「I’M IN 」 by SHUNTA
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01b_poly」:アクセント
・ 「power_up_item_01_fast」:ボタン音

基礎プログラムと 画像を入れた
「量産02 本物を探せ!」zipフォルダを ダウンロードしてください



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

学習の流れ
20個のboonを 重ならないように 表示する

boonを クリックすると 本物は セリフを言う 偽物は消える
BGM・効果音を 入れる
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「I’M IN 」 by SHUNTA
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01b_poly」:アクセント
・ 「power_up_item_01_fast」:ボタン音
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

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




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

今回は、
20個のboonを 表示するプログラムを 作っていきます。
scratchで言う「クローン」。
pygama zeroでは、次の手順で プログラムします


リスト:boonを作成して、その中に20個のboonを 入れるんだ


pgzhelperモジュールの collidelist_pixel( ) メソッドを 使います
20個の風船を 重ならないように表示する


最初に、
20個のboonを ランダムに表示します。

boons = [] #1 リストboons 空リストを代入する
target = random.randint(0, 20) #2 変数target 初期値:0~19からランダムに選んだ数値
for i in range(20): #3 20回繰り返す
x = random.randint(50, WIDTH-50) #4 変数xに 50~750からランダムに選んだ数値を代入する
y = random.randint(50, HEIGHT-50) #5 変数yに 50~540からランダムに選んだ数値を代入する
boon = Actor("boon", (x, y)) #6 boonインスタンスを作る
boon.num = i #7 プロパティnum に 変数i を代入する
boons.append(boon) #8 リストboonsに boonを追加するdef draw():
screen.blit("haikei", (0, 0))
for boon in boons: #9 リストboonsから boonを取り出し
boon.draw() #10 boonを 表示する
boonを ゆっくり表示させました。
本当は、一瞬で20個のboonを 表示させます。
また、
変数targetは、本物のboonの番号を入れる変数です
ポイント1
Actor( )クラスで boonインスタンスを作ったら リストboons 追加する
19. boons.append (boon)

これを for文を 使って 20回 繰り返します。
*今回、カウンター変数:i は プロパティnum に代入されます


リストboonsに 20個のboonが 入りました。

まだ、スクリーンには表示されないよ
ポイント2
表示させるためには、for文を使い
リストboonsから順番に変数boonに代入し、 draw( )メソッドで 表示させます

この作業を リストboonsの最後の要素まで 行いますが
パソコンは一瞬に処理し、パッと画面に 表示します。

さあ、今度は、
collidelist_pixel( )メソッドを使って
boonを 重ならないように 表示させよう

for i in range(20):
for _ in range(100): #1 100回 繰り返す
x = random.randint(50, WIDTH-50)
y = random.randint(50, HEIGHT-50)
boon = Actor("boon", (x, y))
boon.num = i
if boon.collidelist_pixel(boons) == -1: #2 もし 他のboonに 触れてなければ
boons.append(boon)
break #3 繰り返しを 抜けるポイント1
生成されたboonは、
collidelist_pixel( ) メソッドで 表示されたboonに 重ならないか 判定させます。

・ 重なっていたら:○
最初からboonを生成させる
・ 重なっていない: -1
リストboonsに 追加する

collidelist_pixel( ) メソッドは、とても便利だよ
みんなも使ってみてね
ポイント2
なぜ、最大100回試すのか
13. for _ in range(100):
重ならない場所をランダムに見つけるため、
boonや画面の大きさにより、スペースを見つけられない場合
無限に繰り返さます。
それを、防ぐために必ず最大回数を あらかじめ決めておきます。

for i in range(100)でもいいけど、
カウター変数:i に入っているデータを使わないので、
「 _ 」に したよ
本物のboonを クリックして探す

変数targetに 数値(データ)が入っています。
同じ数値が プロパティ:numに入っているboonが 本物です
def draw():
screen.blit("haikei", (0, 0))
for boon in boons:
boon.draw()
text_display.draw(screen) #1 テキストディスプレイを装備する
def on_mouse_down(pos): #2 マウスがクリックした座標(pos)を取得する
for boon in boons: #3 リストboonsから boonを順に取り出す
if boon.collidepoint_pixel(pos): #4 もし boonがクリックされたら
if boon.num == target: #5 プロパティ:numが 変数targetのデータと一緒なら
boon.image = "boon_ok" #6 画像を "boon_ok"にする
boon.say("O.K!", 2, color="red", size=70, y_offset = -70) #7 「O.K!」と2秒間言う
else: #8 その他
boons.remove(boon) #9 リストboonsから クリックしたboonを 削除するポイント
リストboonsから 順番にboonを取り出し
collidepoint_pixel(pos)メソッドを使って クリックしているか判定します
30. for boon in boons:
31. if boon.collidepoint_pixel(pos)

ポイント
if : else 文を使って、
クリックされたboonが本物・それ以外のプログラムを 作ります
32. if boon.num == target:
35. else:
・ 画像を “boon_ok”にする
・ 「O.K!」と 2秒間言う

・ boonを 削除する

remove( ) メソッドを使って
リスト:boonsから 削除して boonの姿を消しました


次に、clear( ) メソッドを使って
本物のboonをクリックされたら、他のboonを消しちゃおう!

def on_mouse_down(pos):
for boon in boons:
if boon.collidepoint_pixel(pos):
if boon.num == target:
boon.image = "boon_ok"
boon.say("O.K!", 2, color="red", size=70, y_offset = -70)
boons.clear() #1 リストboonsを すべて削除する
boons.append(boon) #2 クリックされたboonを リストboonsに追加する
else:
boons.remove(boon) 
おおっ! すっきりしたね
BGM・効果音を 入れる

今回は、2か所に 効果音を入れました。
boonをクリックした音:
・ 本物
・ それ以外

def on_mouse_down(pos):
for boon in boons:
if boon.collidepoint_pixel(pos):
if boon.num == target:
music.stop()
sounds.accent_synth_bell_e_major_01b_poly.play() #1 本物をクリックした効果音
boon.image = "boon_ok"
boon.say("O.K!", 2, color="red", size=70, y_offset = -70)
boons.clear()
boons.append(boon)
else:
sounds.power_up_item_01_fast.play() #2 その他をクリックした効果音
boons.remove(boon)効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「accent_synth_bell_e_major_01b_poly」:アクセント
・ 「power_up_item_01_fast」:ボタン音

うん。いいねぇ

最後に、BGMを入れてみよう

def on_mouse_down(pos):
for boon in boons:
if boon.collidepoint_pixel(pos):
if boon.num == target:
music.stop() #2 BGMを 止める
sounds.accent_synth_bell_e_major_01b_poly.play()
boon.image = "boon_ok"
boon.say("O.K!", 2, color="red", size=70, y_offset = -70)
boons.clear()
boons.append(boon)
else:
sounds.power_up_item_01_fast.play()
boons.remove(boon)
music.play("i'm in") #1 BGMを 流すBGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「I’M IN 」 by SHUNTA
★ 注意★
pygame zero プログラミングでは、大文字が使えません。エラーが出ます。
小文字に直して、「i’m in」プログラムに 入力してください

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

今回は、
boonを 量産したプログラムを 作りました。
import pgzrun
import random
from pgzhelper import *
from say import text_display
WIDTH = 800
HEIGHT = 590
boons = []
target = random.randint(0, 20)
for i in range(20):
for _ in range(100):
x = random.randint(50, WIDTH-50)
y = random.randint(50, HEIGHT-50)
boon = Actor("boon", (x, y))
boon.num = i
if boon.collidelist_pixel(boons) == -1:
boons.append(boon)
break
def draw():
screen.blit("haikei", (0, 0))
for boon in boons:
boon.draw()
text_display.draw(screen)
def on_mouse_down(pos):
for boon in boons:
if boon.collidepoint_pixel(pos):
if boon.num == target:
music.stop()
sounds.accent_synth_bell_e_major_01b_poly.play()
boon.image = "boon_ok"
boon.say("O.K!", 2, color="red", size=70, y_offset = -70)
boons.clear()
boons.append(boon)
else:
sounds.power_up_item_01_fast.play()
boons.remove(boon)
music.play("i'm in")
pgzrun.go()
キャラクターを重ならないように表示するプログラムです。
boons = [] #ポイント1:手順1
for i in range(20): #ポイント1:手順2
for _ in range(100): #ポイント2:手順1
x = random.randint(50, WIDTH-50)
y = random.randint(50, HEIGHT-50)
boon = Actor("boon", (x, y))
if boon.collidelist_pixel(boons) == -1: #ポイント2:手順1
boons.append(boon)
break
def draw():
screen.blit("haikei", (0, 0))
for boon in boons: #ポイント1:手順3
boon.draw()


みんなも 重ならないように表示を試してください
それじゃ、またね!
