【Pygame Zero】簡単なゲーム12:えさをねらえ!虫を避けて進め!
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!
BGM提供: DOVA-SYNDROME
https://dova-s.jp/
・ 「Pixel Twinkle」 written by Kei Morimoto
効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical06」 : 魔法 マジカル06
・ 「maou_se_onepoint17」: ワンポイント17
・ 「maou_se_system43」 : システム音 システム43

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



このゲームで使用している音声ファイルは、
以下のサイトからお借りしています。
各自でダウンロードして、該当するフォルダに入れてください!
BGM提供: DOVA-SYNDROME
https://dova-s.jp/
・ 「Pixel Twinkle」 written by Kei Morimoto
効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical06」 : 魔法 マジカル06
・ 「maou_se_onepoint17」: ワンポイント17
・ 「maou_se_system43」 : システム音 システム43

学習の流れ
左右キーで てんとう虫を動かす
5匹の 虫を 動かす
ゲームオーバー
クリア
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「えさを ねらえ!」では、
・ てんとう虫を 動かす
・ てんとう虫の口を 配置する
・ 10個のボールを ランダムな場所で 表示する
プログラムがあります。
そこで、2つのモジュールを 用意しました



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

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


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

今回のプログラミングには、ポイントが 3つあります

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

max( )メソッドとmin( )メソッドを使って
動ける範囲を 決めたよ


10秒以内でえさをたべたか判定のプログラムを まとめたよ

てんとう虫が 後ろ向きに触れても クリアにならないよ
てんとう虫を 左右キーで動かす

てんとう虫を動かすスイッチとして
プロパティ:on を追加します。

ladybug = Actor("ladybug", (100, 500))
ladybug.on = True #1 プロパティ:on を 追加するdef ladybug_move(): #2 てんとう虫の動きを 定義する
if ladybug.on: #3 もし プロパティonが Trueなら
ladybug.move_forward(3) #4 3px 進む
def update():
ladybug_move() #5 てんとう虫が 動く- move_forward( )メソッドとは


つぎに、
on_key_down(key) 関数を使って
左右キーで てんとうむ虫の向きを 90度ずつ変えます

def on_key_down(key): #1 キーを押した時の動きを 定義する
if ladybug.on: #2 プロパティonが Trueなら
if key == keys.RIGHT: #3 もし 右キーなら
ladybug.angle -= 90 #4 てんとう虫の向きを 90度減らす
elif key == keys.LEFT: #5 もし 左キーなら
ladybug.angle += 90 #6 てんとう虫の向きを 90度増やす
def update():
あれれっ⁉ てんとう虫が スクリーンから 消えちゃうよ…

おぉぉぉ…と!
上下左右の壁に 跳ね返るように しましょう
今回は、max( ) 関数と min( )関数を使って
てんとう虫が動ける範囲をプログラムします。
- max関数、min関数とは


左右に壁の跳ね返りの角度の出し方です

def ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
if ladybug.x < 50 or ladybug.x > WIDTH-50: #1 壁に触れたら
ladybug.x = max(50, min(ladybug.x, WIDTH-50)) #2 x座標の範囲
ladybug.angle = 180 - ladybug.angle #3 跳ね返る
上下の壁も跳ね返るようにします
今度は、てんとう虫のy座標の範囲を 決めます
- max関数、min関数とは

def ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
if ladybug.x < 50 or ladybug.x > WIDTH-50:
ladybug.x = max(50, min(ladybug.x, WIDTH-50))
ladybug.angle = 180 - ladybug.angle
elif ladybug.y < 50 or ladybug.y > HEIGHT-50: #1 上下の壁に触れたら
ladybug.y = max(50, min(ladybug.y, HEIGHT-50)) #2 y座標の範囲
ladybug.angle = -ladybug.angle #3 跳ね返る
これで、てんとう虫の動きのプログラムは 完成です
5匹の虫を 動かす

空のリスト:bugs を作成して、
5匹の虫を ランダムに表示しよう

bg_image = "bg"
bugs = [] #1 空のリストbugsを 用意する
for i in range(5): #2 5回繰り返す
x = random.randint(200, 750) #3 x座標に 200~750からランダムに選んだ数値を代入する
y = random.randint(50, 550) #4 y座標に 50~550からランダムに選んだ数値を代入する
bug = Actor("bug", (x, y)) #5 虫を生成する
bugs.append(bug) #6 リストbugsに 虫を追加する
def ladybug_move(): def draw():
screen.blit(bg_image, (0, 0))
prey.draw()
ladybug.draw()
for bug in bugs: #7 リストbugsから 虫を取り出す
bug.draw() # 8 虫を 表示する- randint関数とは

- append( )メソッドとは


てんとう虫と 重ならないように表示したよ

虫のプロパティ
・ angle(向き):上下左右の 4方向
・ speed(動くスピード): 3~10px
上記の2点で 動くようにします
for i in range(5):
x = random.randint(200, 750)
y = random.randint(50, 550)
bug = Actor("bug", (x, y))
bug.angle = 90 * random.choice([-1, 0, 1, 2]) #1 プロパティangleに -90, 0, 90, 180 からランダムに選んだ数値を代入する
bug.speed = random.randint(3, 10) #2 プロパティspeedに 3~10からランダムに選んだ数値を代入する
bugs.append(bug) - choice( )関数とは
-
21. bug.angle = 90 * random.choice([-1, 0, 1, 2])
90に choice( )関数で 選ばれた数値を かけます。
値を プロパティ:angle(向き)に 代入します

def bug_move( )関数で 虫の動きを定義しましょう
def bug_move(): #1 bug_move()関数を 定義する
if ladybug.on: #2 もし プロパティonが Trueなら
for bug in bugs: #3 リストbugsから 虫を 取り出す
bug.move_forward(bug.speed) #4 プロパティspeedで 動く
def on_key_down(key): def update():
ladybug_move()
bug_move() #5 bug_move()関数を 実行する
虫が バラバラに 動き出したぞ!

虫も てんとう虫と同じように 動ける範囲を決めて
壁に当たったら 跳ね返るように しましょう

虫の画像の大きさは、
50 × 50 px です

def bug_move():
if ladybug.on:
for bug in bugs:
bug.move_forward(bug.speed)
if bug.x < 25 or bug.x > WIDTH-25: #1 もし 虫のx座標が 25より小さい または 775より大きいなら
bug.x = max(25, min(bug.x, WIDTH-25)) #2 虫のx座標の範囲は 25~775まで
bug.angle = 180- bug.angle #3 跳ね返る
elif bug.y < 25 or bug.y > HEIGHT-25: #4 もし 虫のy座標が 25より小さい または 575より大きいなら
bug.y = max(25, min(bug.y, HEIGHT-25)) #5 虫のy座標の範囲は 25~575まで
bug.angle = -bug.angle #6 跳ね返る
おおっ!いいねえ

collide_pixel( )メソッドを使って
虫に触れたら てんとう虫は 50px後退させよう

def bug_move():
if ladybug.on:
for bug in bugs:
bug.move_forward(bug.speed)
if bug.x < 25 or bug.x > WIDTH-25:
bug.x = max(25, min(bug.x, WIDTH-25))
bug.angle = 180- bug.angle
elif bug.y < 25 or bug.y > HEIGHT-25:
bug.y = max(25, min(bug.y, HEIGHT-25))
bug.angle = -bug.angle
elif bug.collide_pixel(ladybug): #1 もし てんとう虫に触れたら
sounds.maou_se_system43.play() #2 効果音を 鳴らす
ladybug.move_forward(-50) #3 50px後退する- play( )メソッドとは
-

効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_system43」 : システム音 システム43

なかなか、前に進まないね!
ゲームオーバー

10秒以内に えさに たどり着かなかったら ゲームオーバーです。
変数count を宣言して 秒数を 表示させましょう

count_down関数で、
・ 変数count のデータから 1 減らす
・ 変数count が 0 になったら 動きを 止める
を 定義して ます。
bg_image = "bg"
count = 10 #1 変数countを 宣言 初期値:10def count_down(): #2 カウントダウンの関数を 定義する
global count #3 グローバル変数 count
if ladybug.on: #4 もし プロパティonが Trueなら
count -= 1 #5 変数coutnを 1減らす
if count == 0: #6 もし 変数カウントが 0 なら
clock.unschedule(count_down) #7 count_down関数を 停止する
ladybug.on = False #8 プロパティonを Falseにする
def on_key_down(key):- unschedule( )メソッドとは


schedule_interval()メソッドで、
1秒ごとに count_down関数を 実行させよう

def draw():
screen.blit(bg_image, (0, 0))
screen.draw.text(f"TIME: {count}",
(10, 10),
fontsize=70,
color="blue") #9 カウント表示する
prey.draw()
ladybug.draw()
for bug in bugs:
bug.draw()
clock.schedule_interval(count_down, 1) #10 1秒ごとに count_down関数を実行する- text( )メソッドとは
-

- f 文字列
-

79. screen.draw.text(f” TIME : {count}”,
変数countのデータが 10,9,8…0と スクリーンに表示されます

タイムが 0 になったら, 動きが止まったね

10秒以内にえさを ふれたか 判定を
game_end()関数に 定義します。

def game_end(bg,sound): #2 ゲームエンド関数を定義する
global bg_image #3 グローバル変数 bg_image
music.stop() #4 BGMを止める
bg_image = bg #5 引数bgを 変数bg_imageに 代入する
sound.play() #6 効果音を 再生する
def on_key_down(key): clock.schedule_interval(count_down, 1)
music.play("pixel_twinkle") #1 BGMを 流す- musicモジュールとは

BGM提供: DOVA-SYNDROME
https://dova-s.jp/
・ 「Pixel Twinkle」 written by Kei Morimoto

「pixel twinkle」と 大文字の『P』『T』を小文字にしてね
pygame zeroプログラムでは、大文字はエラーになっちゃうんだ

それでは、変数countが 0 になったら、
game_end( )関数で ゲームオーバーに しましょう
def count_down():
global count
if ladybug.on:
count -= 1
if count == 0:
clock.unschedule(count_down)
game_end("bg_over", sounds.maou_se_magical06) #1 game_end( )関数を 実行する
ladybug.on = False 効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical06」 : 魔法 マジカル06

おおっ!いいね。
クリア

collide_pixel( )メソッドを使って
えさを食べたら クリアになるプログラムを 作りましょう
def ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
mouth.pos = move(ladybug.x,
ladybug.y, elif ladybug.y < 50 or ladybug.y > HEIGHT-50:
ladybug.y = max(50, min(ladybug.y, HEIGHT-50))
ladybug.angle = -ladybug.angle
if ladybug.collide_pixel(prey): #1 えさに 触れたら
game_end("bg_clear", sounds.maou_se_onepoint17) #2 game_end()関数を 実行する
ladybug.on = False #3 プロパティon を Falseに設定する
効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_onepoint17」: ワンポイント17

あれっ⁉ おしりでも クリアに なるの…?

そうですね。お尻で クリアは 納得しませんね
そういう場合は、口のオブジェクトを てんとう虫につけて
口が えさに触れたら クリアになるように しましょう

ladybug.on = True
mouth = Actor("mouth", (100, 500)) #1 口を 生成する
mouth.visible = True #2 プロパティvisibleを Trueにするdef ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
mouth.pos = move(ladybug.x,
ladybug.y,
ladybug.angle,
35) #3 口の座標(pos)に てんとう虫の座標から35px前に 設定するdef draw():
screen.blit(bg_image, (0, 0))
screen.draw.text(f"TIME: {count}",
(10, 10), for bug in bugs:
bug.draw()
if mouth.visible: #4 プロパティvisibleが Trueなら
mouth.draw() #5 口を 表示する- プロパティvisibleとは


プロパティ:visible の Ture / False で
口の 表示 / 非表示 を するよ

口は、ちゃんと てんとう虫に くっついているね

それでは、
クリアの条件を てんとう虫が えさに触れたではなく
if ladybug.collide_pixel(prey): #1 もし えさに触れたらladybug を mouth に 変えます
if mouth.collide_pixel(prey): #1 もし えさに触れたらdef ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
mouth.pos = move(ladybug.x,
ladybug.y, elif ladybug.y < 50 or ladybug.y > HEIGHT-50:
ladybug.y = max(50, min(ladybug.y, HEIGHT-50))
ladybug.angle = -ladybug.angle
if mouth.collide_pixel(prey): #1 口が えさに 触れたら
game_end("bg_clear", sounds.maou_se_onepoint17)
ladybug.on = False 
おおっ!口の方で クリアしたぞ!

最後に
プロパティvisible を False にして 非表示にしておけば
みんなには 口の存在が わからないよ
mouth = Actor("mouth", (100, 500))
mouth.visible = True #1 プロパティvisibleを False にする
今回の学習は、これで 終了! おつかれさま
まとめ

今回は、
5匹の虫を よけながら えさへたどり着くプログラムを作りました。
import pgzrun
from pgzhelper import *
import random
WIDTH = 800
HEIGHT = 600
ladybug = Actor("ladybug", (100, 500))
ladybug.on = True
mouth = Actor("mouth", (100, 500))
mouth.visible = False
prey = Actor("prey", (700, 100))
bg_image = "bg"
count = 10
bugs = []
for i in range(5):
x = random.randint(200, 750)
y = random.randint(50, 550)
bug = Actor("bug", (x, y))
bug.angle = 90 * random.choice([-1, 0, 1, 2])
bug.speed = random.randint(3, 10)
bugs.append(bug)
def ladybug_move():
if ladybug.on:
ladybug.move_forward(3)
mouth.pos = move(ladybug.x,
ladybug.y,
ladybug.angle,
35)
if ladybug.x < 50 or ladybug.x > WIDTH-50:
ladybug.x = max(50, min(ladybug.x, WIDTH-50))
ladybug.angle = 180 - ladybug.angle
elif ladybug.y < 50 or ladybug.y > HEIGHT-50:
ladybug.y = max(50, min(ladybug.y, HEIGHT-50))
ladybug.angle = -ladybug.angle
if mouth.collide_pixel(prey):
game_end("bg_clear", sounds.maou_se_onepoint17)
ladybug.on = False
def bug_move():
if ladybug.on:
for bug in bugs:
bug.move_forward(bug.speed)
if bug.x < 25 or bug.x > WIDTH-25:
bug.x = max(25, min(bug.x, WIDTH-25))
bug.angle = 180- bug.angle
elif bug.y < 25 or bug.y > HEIGHT-25:
bug.y = max(25, min(bug.y, HEIGHT-25))
bug.angle = -bug.angle
elif bug.collide_pixel(ladybug):
sounds.maou_se_system43.play()
ladybug.move_forward(-50)
def count_down():
global count
if ladybug.on:
count -= 1
if count == 0:
clock.unschedule(count_down)
game_end("bg_over", sounds.maou_se_magical06)
ladybug.on = False
def game_end(bg,sound):
global bg_image
music.stop()
bg_image = bg
sound.play()
def on_key_down(key):
if ladybug.on:
if key == keys.RIGHT:
ladybug.angle -= 90
elif key == keys.LEFT:
ladybug.angle += 90
def update():
ladybug_move()
bug_move()
def draw():
screen.blit(bg_image, (0, 0))
screen.draw.text(f"TIME: {count}",
(10, 10),
fontsize=70,
color="blue")
prey.draw()
ladybug.draw()
for bug in bugs:
bug.draw()
if mouth.visible:
mouth.draw()
clock.schedule_interval(count_down, 1)
music.play("pixel_twinkle")
pgzrun.go()
てんとう虫や虫が動く 範囲は、
max( )と min( ) 関数を 使うと 便利だったね

また、
てんとう虫 に 口 をつけることで
クリアの仕方が よくなったね

これは、いろいろなゲームに使えるよ
それじゃあ、またね!










