【Pygame Zero】簡単なゲーム07:障害物をたくさん置くプログラム
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!
BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「A Cat in Palm Beach 」 by 北見ヒツジ
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Kiga Nukeru [01] (Long)」:アニメ

基礎プログラムと 画像を入れた
「簡単なゲーム07 ゴールを ねらえ!」zipフォルダを ダウンロードしてください


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

学習の流れ
boonを マウスで動かす
雲を 動かす
ゲーム終了

BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「A Cat in Palm Beach 」 by 北見ヒツジ
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Kiga Nukeru [01] (Long)」:アニメ
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「ゴールをめざして!」では、
・他の雲に重ならないように表示する
プログラムがあります。
そこで、このモジュールを 用意しました


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

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


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

今回は、
10個の雲が 現れて 左へ動くプログラムを 作っていきます。
scratchで言う「クローン」。
pygama zeroでは、次の手順で プログラムします

リスト:cloudsを作成して、その中に雲を 追加していくんだ


10個の雲を表示する 条件だよ


クリアとゲームオーバーのプログラムを まとめたよ
boonを マウスで動かす

boonを動かすスイッチとして
プロパティ:on を追加します。
スペースキーを押したら、動くようにしましょう

boon.on = False #1 追加プロパティ:on に Falseを設定するdef on_key_down(key): #2 キーを押す関数を 定義する
if key == keys.SPACE: #3 もし スペースキーが 押されたら
boon.on = True #4 プロパティon に Trueを設定する
def on_mouse_move(pos): #5 マウスを動かす関数を 定義する
if boon.on: #6 もし プロパティonが trueなら
boon.angle = boon.angle_to(pos) #7 boonの向きに マウスへ向く角度を 代入する

mouseオブジェクトに マウスの座標を 入れる
プロパティ:posを 追加します

boon.on = False
mouse.pos = 100, 500 #1 追加プロパティpos に (100, 500)を設定する
move_towards( )メソッドで、boonを 動かします。

def on_mouse_move(pos):
if boon.on:
boon.angle = boon.angle_to(pos)
mouse.pos = pos #2 プロパティposに マウスの座標(pos)を代入するdef boon_move(): #3 boonの動きを 定義する
if boon.on: #4 もし スイッチが Trueなら
boon.move_towards(mouse.pos, 2) #5 マウスの方へ 2pxずつ動くdef update():
boon_move() #5 boonを 動かす
これで、boonの動きは、O.K!
雲を 動かす

つぎは、空のリストclouds を作成して、
10個の雲を スクリーンに 表示します。

clouds = [] #1 リストclouds に 空リストを代入する
for i in range(10): #2 10回繰り返す
x = random.randint(50, 750) #3 x座標に 50~750 からランダムに決めて代入する
y = random.randint(50, 565) #4 y座標に 50~565 からランダムに決めて代入する
cloud = Actor("cloud", (x, y)) #5 雲を 生成する
clouds.append(cloud) #6 リストcloudsに 追加する
def draw():
screen.fill("lightcyan")
sun.draw()
boon.draw()
for cloud in clouds: #7 リストcloudsから 雲を取り出す
cloud.draw() #8 雲を 表示する
あれれっ!
雲が boonや太陽に 触れるいる時があるよ


スタートや ゴールができないじゃん!

おぉぉぉ…と、いけない!
雲を表示するときに 条件を 作ろう
★ 雲を 表示する条件 ★
1. 変数check_boon : boonから 200px以上 離す
2. 変数check_sun : 太陽から 100px以上 離す
3. 変数check_cloud: 他の雲と 重ならない

distance_to( )メソッドを使えば、
boonと 雲との距離を 計算してくれるよ


雲の重なりは、
collidelist_pixel()メソッドを使えば 判定してくれます



while True: 構文で 雲の場所を決めましょう
3つの条件が Trueになったら
break で このwhile構文を抜けて、 リストcloudsに 追加しましょう

for i in range(10):
while True: #1 繰り返す
x = random.randint(50, 750)
y = random.randint(50, 565)
cloud = Actor("cloud", (x, y))
check_boon = boon.distance_to(cloud) > 200 #2 変数check_boonに 条件:boonと雲の距離が 200px以上を 代入する
check_sun = sun.distance_to(cloud) > 100 #3 変数check_sunに 条件:太陽と雲の距離が 100以上を 代入する
check_cloud = cloud.collidelist_pixel(clouds) == -1 #4 変数check_cloudに 条件:他の雲に重ならないを 代入する
if check_boon and check_sun and check_cloud: #5 もし 3つの条件が Tureなら
break #6 抜け出す
clouds.append(cloud) 
おおっ!お見事!

プロパティ:speed を追加して、
ここに randint( )メソッドを使って、雲が動く速さを ランダムに決めます

for i in range(10):
while True:
x = random.randint(50, 750)
y = random.randint(50, 565)
cloud = Actor("cloud", (x, y))
cloud.speed = random.randint(1, 3) #1 プロパティspeedに 1~3からランダムに決めた数値を 設定する
check_boon = boon.distance_to(cloud) > 200 
雲の動きを def boon_move() 関数に 定義しよう
1.boonの x座標を プロパティspeedずつ 減らします
2.雲のx座標が o より小さくなったら x座標800 にする
これで、雲は、左へ動いて、左端に着いたら 右端に現れるよ
def cloud_move(): #1 cloud_move関数を 定義する
if boon.on: #2 もし プロパティon が Trueなら
for cloud in clouds: #3 リストcloudsから 雲を 取り出す
cloud.x -= cloud.speed #4 雲のx座標を プロパティspeedずつ 減らす
if cloud.x < 0: #5 もし 雲のx座標が 0 以下なら
cloud.x = 800 #6 雲のx座標を 800に する
def update():
boon_move()
cloud_move() #7 cloud_move関数を 実行する
これで、雲の動きはO.K!
ゲーム終了


まず、変数bg_imageを作成し、
背景画像が代入されたら、blit( )メソッドで 表示する
プログラムを 作りましょう

clouds = []
bg_image = None #1 変数bg_imageを 宣言する 初期値:None(無し)def draw():
screen.fill("lightcyan")
if bg_image: #2 もし 変数bg_imageに 背景画像が代入されたら
screen.blit(bg_image, (0, 0)) #3 背景画像を 表示する
sun.draw()
次に、クリアとゲームオーバーのプログラムを
game_end関数に まとめて定義しましょう
引数に
・ bg : 背景画像
・ costume: boon画像
・ sound: 変数sounds(効果音オブジェクトを 入れる)

def game_end(bg, costume, sound): #1 game_end関数を 定義する
global bg_image #2 グローバル変数 bg_image
boon.on = False #3 プロパティonに Falseを設定する
music.stop() #4 BGMを 止める
bg_image = bg #5 変数bg_imageに 引数bgを 代入する
boon.image = costume #6 プロパティimageに 引数costumeを 代入する
sound.play() #7 変数soundに入っている効果音を 再生する
BGMと効果音のデータを フォルダに いれるよ

BGM提供:DOVA-SYNDROME
https://dova-s.jp/
・ 「A Cat in Palm Beach 」 by 北見ヒツジ
効果音提供:Chisato’s Website
https://chisatosound.sakura.ne.jp/index.html
・ 「Accent. Brilliant [02] (Low)」:アクセント
・ 「Kiga Nukeru [01] (Long)」:アニメ

musicモジュールのplay()メソッドで、BGMを 再生します


soundsモジュールのplay()メソッドで、効果音を鳴らすよ


collide_pixel()メソッドを使って
boonが、太陽、雲に触れたら game_end関数を 実行させよう

def boon_move():
if boon.on:
boon.move_towards(mouse.pos, 2)
if boon.collide_pixel(sun): #2 もし 太陽に 触れたら
game_end("bg_clear", "boon_goal", sounds.accent_brilliant_02_low) #3 game_end関数を 実行する
for cloud in clouds: #4 リストcloudsから 雲を取り出す
if boon.collide_pixel(cloud): #5 もし 雲に触れたら
game_end("bg_gameover", "boon_over", sounds.kiga_nukeru_01_long) #6 game_end関数を 実行するmusic.play("a_cat_in_palm_beach") #1 BGMを再生する
今回の学習は、これで 終了! おつかれさま
まとめ

今回は、
10個の雲を重ならないように表示するプログラムを 作りました。
import pgzrun
from pgzhelper import *
import random
WIDTH = 800
HEIGHT = 600
boon = Actor("boon", (100, 500))
sun = Actor("sun", (700, 100))
boon.on = False
mouse.pos = 100, 500
clouds = []
bg_image = None
for i in range(10):
while True:
x = random.randint(50, 750)
y = random.randint(50, 565)
cloud = Actor("cloud", (x, y))
cloud.speed = random.randint(1, 3)
check_boon = boon.distance_to(cloud) > 200
check_sun = sun.distance_to(cloud) > 100
check_cloud = cloud.collidelist_pixel(clouds) == -1
if check_boon and check_sun and check_cloud:
break
clouds.append(cloud)
def draw():
screen.fill("lightcyan")
if bg_image:
screen.blit(bg_image, (0, 0))
sun.draw()
boon.draw()
for cloud in clouds:
cloud.draw()
def on_key_down(key):
if key == keys.SPACE:
boon.on = True
def on_mouse_move(pos):
if boon.on:
boon.angle = boon.angle_to(pos)
mouse.pos = pos
def game_end(bg, costume, sound):
global bg_image
boon.on = False
music.stop()
bg_image = bg
boon.image = costume
sound.play()
def boon_move():
if boon.on:
boon.move_towards(mouse.pos, 2)
if boon.collide_pixel(sun):
game_end("bg_clear", "boon_goal", sounds.accent_brilliant_02_low)
for cloud in clouds:
if boon.collide_pixel(cloud):
game_end("bg_gameover", "boon_over", sounds.kiga_nukeru_01_long)
def cloud_move():
if boon.on:
for cloud in clouds:
cloud.x -= cloud.speed
if cloud.x < 0:
cloud.x = 800
def update():
boon_move()
cloud_move()
music.play("a_cat_in_palm_beach")
pgzrun.go()
重ならない条件を 変数に 代入すると、True/Falseを 返すので、
if 文に 使えて 便利です。


これで、if 文も シンプルになるね
それじゃ、またね!
