【Pygame Zero】簡単なゲーム13:星集めVSビーム攻撃
こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です

【Pygame Zero】簡単なゲーム13:マウス操作!星集めVSビーム攻撃

スックです。よろしくね!
BGM提供: DOVA-SYNDROME
https://dova-s.jp/
・ 「おはようタートル」 written by Masuo
効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical02」 : 魔法 マジカル02
・ 「maou_se_magical06」 : 魔法 マジカル06
・ 「maou_se_onepoint17」: ワンポイント17
・ 「maou_se_system49」 : システム音 システム49

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


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


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

学習の流れ
マウスで boonを動かす
がいこつの 動きアニメーション
ゲームの結果

プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「スマイルboonを 探せ!」では、
・ ビームを がいこつの口元に 置く
・ 星を ランダムに 表示する
プログラムがあります。
そこで、2つのモジュールを 用意しました



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

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


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

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

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

リストstars から 星を削除しちゃうと
エラーが起きる場合があるんだ


3つの関数のローテーションで 動いているんだね

これで、がいこつの動きを 好きな時に止められるね


クリアとゲームオーバーのプログラムを まとめたよ


ゲームオーバーになる条件だよ
マウスで boonを動かす

最初に 30個の星を ランダムに表示しましょう
空の リストstars を 作成して
30個の 星を 生成して 追加していきます。

skull = Actor("skull", (700, 100))
stars = [] #1 空のリストstars を作成する
for i in range(30): #2 30回繰り返す
x = random.randint(20, WIDTH-20) #3 x座標に 20~680からランダムに選んだ数値を 代入する
y = random.randint(20, HEIGHT-20) #4 y座標に 20~580からランダムに選んだ数値を 代入する
star = Actor("star", (x, y)) #5 星を生成する
stars.append(star) #6 リストstars に 星を追加するdef draw():
screen.fill("dimgray")
for star in stars: #7 リストstarsから 星を取り出す
star.draw() #8 星を表示する
skull.draw()- randint関数とは

- append( )メソッドとは


星の画像の大きさは、
40 × 40 px です


つぎに boon を動かすスイッチとして
プロパティ:on を 追加します。

boon = Actor("boon", (100, 500))
boon.on = True #1 プロパティon を Trueにするdef on_mouse_move(pos): #2 マウスを動かす関数を 定義する
if boon.on: #3 もし プロパティon が Trueなら
boon.angle = boon.angle_to(pos) #4 boonの向きに マウスへ向く角度を 代入する
def update():- on_mouse_move(pos) 関数とは

- angle_to( )メソッドとは


boonが 動き出したぞ

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

boon.on = True
mouse.pos = 100, 500 #1 追加プロパティpos に (100, 500)を設定する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 もし プロパティonが Trueなら
boon.move_towards(mouse.pos, 5) #5 マウスの方へ 5pxずつ動く
def update():
boon_move() #6 boonを 動かす- move_towards( )メソッドとは


collide_pixel( )メソッドで、
星に触れたら 削除するようにプログラムを書くよ
量産された星は、リストstarsの順番に削除されないため
リストstarsを コピーしたものから 星を取り出すよ
def boon_move():
if boon.on:
boon.move_towards(mouse.pos, 5)
for star in stars[:]: #1 コピーリストstarsから 星を取り出す
if star.collide_pixel(boon): #2 boonに 触れたら
sounds.maou_se_system49.play() #3 効果音を 出す
stars.remove(star) #4 リストstars から 星を削除する効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_system49」 : システム音 システム49
- collide_pixel( )メソッドとは

- play( )メソッドとは
-

- remove( )メソッドとは
-

がいこつの 動きアニメーション

次には、がいこつの動きを プログラミングしていきます。
3つの関数が 連携して できているんだ


回転して、動いて、発射!

まずは、skull_turn( )関数を 定義しましょう。
skullオブジェクトに
・ プロパティ:next … 動いた時の到着地点の 座標を 入れる
・ プロパティ:anim … アニメーションオブジェクトを 入れる
を 追加します。
skull = Actor("skull", (700, 100))
skull.next = (700, 100) #1 プロパティnextに (700, 100)を設定する
skull.anim = None #2 プロパティanimに None(無し)
3つの関数とも
animation( )関数を 使って がいこつの動きを作ります。


がいこつのアニメーションは、
プロパティ:animに 代入しておきます。
ゲームオーバーやクリアの時、
がいこつの動きのアニメーションの途中で止めることができるんだ。
def skull_turn(): #3 skull_turn関数を 定義する
x = random.randint(50, WIDTH-50) #4 x座標に 50~750からランダムに選んだ数値を設定する
y = random.randint(50, HEIGHT-50) #5 y座標に 50~650からランダムに選んだ数値を設定する
skull.next = x, y #6 プロパティnextに x, yを 代入する
next_angle = skull.angle_to(skull.next) #7 到達地点への角度を 計算して 振り向く角度を 変数next_anlgeに 代入する
skull.anim = animate(skull,
angle = next_angle,
duration=1.0,
) #8 プロパティanimに 振り向きアニメーションを代入する
skull_turn() #9 skull_turn関数を 実行する
def update():- angle_to( )メソッド とは?


おおっ!がいこつが 振り向いたぞ

がいこつが 振り向いた後、到達地点へ動くプログラムを
skull_move関数で 定義しましょう
変数move_time には、到達地点までの時間を 入れるよ
def skull_turn():
x = random.randint(50, WIDTH-50)
y = random.randint(50, HEIGHT-50)
skull.next = x, y
next_angle = skull.angle_to(skull.next)
skull.anim = animate(skull,
angle = next_angle,
duration=1.0,
on_finished= skull_move) #1 アニメーション終了後 skull_move関数を 実行する
def skull_move(): #2 skull_move()関数を 定義する
move_time = random.uniform(0.5, 5.0) #3 変数move_timeに 0.5~5.0からランダムに選んだ数値を代入する
skull.anim = animate(skull,
pos = skull.next,
duration = move_time) #4 プロパティanimに 動くアニメーションを 代入する- uniform( )関数とは?


動いたね

がいこつが 到着地点に着いた後、ビームを発射するプログラムを
skull_shoot関数で 定義しましょう
がいこつのビームを発射する向きの範囲を
-200から200にします。

ここで、
beamオブジェクトをActor()クラスを使って生成します。

プロパティ:on は、ビームを表示するスイッチに設定するよ

boon.on = True
beam = Actor("beam", (400, 100)) #1 ビーム生成
beam.on = False #2 プロパティonに Falseを設定するdef skull_turn():
beam.on = False #3 プロパティonに Falseを設定する
x = random.randint(50, WIDTH-50) def skull_move():
move_time = random.uniform(0.5, 5.0)
skull.anim = animate(skull,
pos = skull.next,
duration = move_time,
on_finished = skull_shoot) #4 終了後 skull_shoot関数を実行する
def skull_shoot(): #5 skull_shoot()関数を 定義する
shoot_angle = random.randint(-200, 200) #6 変数shoot_angleに -200~200からランダムに選んだ数値を 代入する
shoot_time = random.uniform(0.5, 1.5) #7 変数shoot_timeに 0.5~1.5からランダムに選んだ数値を 代入する
beam.on = True #8 プロパティonを Trueに設定する
sounds.maou_se_magical06.play() #9 効果音を 再生する
skull.anim = animate(skull,
angle = skull.angle + shoot_angle,
duration= shoot_time) #10 プロパティanimに アニメーションを 代入する
skull_turn() def draw():
screen.fill("dimgray")
for star in stars:
star.draw()
skull.draw()
if beam.on: #11 もし プロパティonが Trueなら
beam.draw() #12 ビームを表示する
boon.draw()- play( )メソッドとは?


赤い細い棒が ビームなの?

プロパティonが Trueになったら、ビームが現れたね
その時に、move( )メソッドを使って
プロパティonが Trueの時は、がいこつの 前に 表示しましょう

skull_turn()
def beam_move(): #1 beam_move()関数を 定義する
if beam.on: #2 もし プロパティonが Trueなら
beam.pos = move(skull.x,
skull.y,
skull.angle,
550) #3 ビームの座標に がいこつより 550px動かした地点を 代入する
def update():
boon_move()
beam_move() #4 beam_move()関数を 実行する
あれれ…⁉ がいこつの口から 出てないよ

おおぉぉぉ…と、いけない!
これだけでは、ビームの位置が動くだけに なります。
ビームの角度を がいこつを同じ向きにします。
skull_turn()
def beam_move():
if beam.on:
beam.pos = move(skull.x,
skull.y,
skull.angle,
550)
beam.angle = skull.angle #1 ビームの向きを がいこつの向きに設定する
def update():
いいね!がいこつの口から ビームが出てきたぞ

最後に、skull_shoot( )関数が 終了したら
skull_turn関数が 実行するようにしましょう
そうすれば、がいこつの動きのアニメーションが 完成します
def skull_shoot():
shoot_angle = random.randint(-200, 200)
shoot_time = random.uniform(0.5, 1.5)
sounds.maou_se_magical06.play()
beam.on = True
skull.anim = animate(skull,
angle = skull.angle + shoot_angle,
duration= shoot_time,
on_finished = skull_turn) #1 終了後 skull_turn関数を 実行する
skull_turn()効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical06」 : 魔法 マジカル06

これで、がいこつの動きのアニメーションが 完成だよ
ゲームの結果


最後の場面での
game_end( )関数を 定義しましょう


プロパティbg には、
ゲームオーバーやクリアになった時の背景画像を 入れます。
初期値は、None (無し) です。

boon = Actor("boon", (100, 500))
boon.on = True
boon.bg = None #1 プロパティ:bgに None(無し)を設定するbeam.on = False
music.play("おはようタートル") #2 BGMを 再生する
stars = [] def game_end(bg, sound, costume): #3 game_end()関数を 定義する
music.stop() #4 BGMを 止める
boon.bg = bg #5 プロパティbgに 引数bgを代入する
sound.play() #6 引数soundを 再生する
boon.image = costume #7 プロパティimageに 引数costumeを代入する
boon.on = False #8 プロパティonに Falseを設定する
skull.anim.stop() #9 がいこつのアニメーションを 止める
def update():
boon_move()
beam_move()
def draw():
screen.fill("dimgray")
if boon.bg: #10 もし プロパティbgに データがあったら
screen.blit(boon.bg, (0, 0)) #10 背景画像を 表示する
for star in stars: - musicオブジェクトとは?

- blit()メソッドとは?
-

BGM提供: DOVA-SYNDROME
https://dova-s.jp/
・ 「おはようタートル」 written by Masuo

最初に、
星をすべてゲットしたら クリアにするプログラムを作りましょう
リストstars が 空になったら クリアです
def boon_move():
if boon.on:
boon.move_towards(mouse.pos, 5)
for star in stars[:]:
if star.collide_pixel(boon):
sounds.maou_se_system49.play()
stars.remove(star)
if not stars: #1 もし リストstarsが 空になったら
game_end("bg_clear",
sounds.maou_se_onepoint17,
"boon_clear") #2 game_end()関数を実行する 効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_onepoint17」: ワンポイント17

がいこつは、わざと動かないようにしたよ

最後に、ゲームオーバーのプログラムです。
ゲームオーバーは、2通りあります。
・ がいこつに 触れる
・ ビームに 触れる
上記を判定するcheck_hit( )関数を 定義しましょう

def check_hit(): #1 check_hit()関数を 定義する
if boon.on: #2 もし プロパティonが Trueなら
hit_skull = boon.collide_pixel(skull) #3 変数hit_skullに がいこつに触れたか判定を 代入する
hit_beam = boon.collide_pixel(beam) and beam.on #4 変数hit_beamに ビームに触れたか判定を 代入する
if hit_skull or hit_beam: #5 もし 変数hit_skull または、変数hit_beamが Trueなら
game_end("bg_over",
sounds.maou_se_magical02,
"boon_over") #6 game_end関数を 実行する
def update():
boon_move()
beam_move()
check_hit() #7 check_hit()関数を 実行する効果音提供:魔王魂
https://maou.audio/
・ 「maou_se_magical02」 : 魔法 マジカル02

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

今回は、
がいこつの攻撃をよけながら 星をゲットするプログラムを作りました。
import pgzrun
from pgzhelper import *
import random
WIDTH = 800
HEIGHT = 600
boon = Actor("boon", (100, 500))
boon.on = True
boon.bg = None
mouse.pos = 100, 500
skull = Actor("skull", (700, 100))
skull.next = (700, 100)
skull.anim = None
beam = Actor("beam", (400, 100))
music.play("おはようタートル")
stars = []
for i in range(30):
x = random.randint(20, WIDTH-20)
y = random.randint(20, HEIGHT-20)
star = Actor("star", (x, y))
stars.append(star)
def on_mouse_move(pos):
if boon.on:
boon.angle = boon.angle_to(pos)
mouse.pos = pos
def boon_move():
if boon.on:
boon.move_towards(mouse.pos, 5)
for star in stars[:]:
if star.collide_pixel(boon):
sounds.maou_se_system49.play()
stars.remove(star)
if not stars:
game_end("bg_clear",
sounds.maou_se_onepoint17,
"boon_clear")
def skull_turn():
beam.on = False
x = random.randint(50, WIDTH-50)
y = random.randint(50, HEIGHT-50)
skull.next = x, y
next_angle = skull.angle_to(skull.next)
skull.anim = animate(skull,
angle = next_angle,
duration=1.0,
on_finished= skull_move)
def skull_move():
move_time = random.uniform(0.5, 5.0)
skull.anim = animate(skull,
pos = skull.next,
duration = move_time,
on_finished = skull_shoot)
def skull_shoot():
shoot_angle = random.randint(-200, 200)
shoot_time = random.uniform(0.5, 1.5)
beam.on = True
sounds.maou_se_magical06.play()
skull.anim = animate(skull,
angle = skull.angle + shoot_angle,
duration= shoot_time,
on_finished=skull_turn)
skull_turn()
def beam_move():
if beam.on:
beam.pos = move(skull.x,
skull.y,
skull.angle,
550)
beam.angle = skull.angle
def game_end(bg, sound, costume):
music.stop()
boon.bg = bg
sound.play()
boon.image = costume
boon.on = False
skull.anim.stop()
def check_hit():
if boon.on:
hit_skull = boon.collide_pixel(skull)
hit_beam = boon.collide_pixel(beam) and beam.on
if hit_skull or hit_beam:
game_end("bg_over",
sounds.maou_se_magical02,
"boon_over")
def update():
boon_move()
beam_move()
check_hit()
def draw():
screen.fill("dimgray")
if boon.bg:
screen.blit(boon.bg, (0, 0))
for star in stars:
star.draw()
skull.draw()
if beam.on:
beam.draw()
boon.draw()
pgzrun.go()
3つのanimate( )関数を 連携して
がいこつが自動的に動くプログラムを 作りました


キーワード引数:on_finished で、
関数をつなげることができるんだね。みんなも使ってみよう
それじゃあ、またね!













