【Pygame Zero】キャラクターにモザイクを入れてみよう

こんにちは!
「Pythonしよう!楽しく学べるプログラミング教室」の
ラッチ先生です


スックです。よろしくね!

今回のプロジェクトには、
boonの他に 矢印、星が 登場します。
基礎プログラムと 画像を入れた
「見た目05 boonを ねらえ!No.3」zipフォルダを ダウンロードしてください



この基礎プログラムは、こちらの記事で解説しています

学習の流れ
回転する矢印を クリックすると 星が 飛ぶ
1秒ごと 矢印に触れない所で 表示する
星に当たると モザイクが かかって 消える

スペースキーを押すと 再び boonが動き出す
プログラムを 実行してみよう
プログラミングの仕方を説明します
モジュールを 用意する

今回の「boonを ねらえ!No.3」ゲームでは、
・ 星が 飛び出す
・ boonが ランダムな場所へ 移る
・ boon に モザイクをかける
プログラムが あります
そこで、3つのモジュールを 用意しました




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

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


これで、変数boonに「 . (ドット)」を付ければ 使えるよ


process_animation( )メゾットは、
アニメーション終了時に キャラクターを非表示にするよ


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


両方 2つに 分けたよ
矢印を クリックすると 星が 飛ぶ

最初に、
矢印を動かすプログラムを 作りましょう
star_state = "ready" #1 変数star_state(状態) 初期値:"ready(準備)"
arrow_direction = 1 #2 変数arrow_direction(方向)初期値:1
def arrow_move(): #3 矢印の動きをまとめる
global arrow_direction #4 グローバル変数:arrow_state
if star_state == "ready": #5 もし 変数star_stateが"ready"なら
arrow.angle += arrow_direction #6 矢印の向きを 変数arrow_directionずつ 増やす
if arrow.angle > 90 or arrow.angle < 0: #7 もし 矢印の向きが90度より大きく、また、0度より小さいなら
arrow_direction = -arrow_direction #8 変数arrow_directionに -1×arrow_directionを代入する
def update(): #9 更新する
arrow_move() #10 矢印を動かす


update()関数に
arrow_move() 関数を 入れることによって 矢印が 動くからね

次は、
def on_mouse_down(pos) 関数を使って、
矢印を クリックしたら 星が 飛び出すプログラムを作るよ

def on_mouse_down(pos): #1 マウスがクリックしたpos(座標)を取得する
global star_state #2 グローバル変数: arrow_state
if star_state == "ready" and arrow.collidepoint_pixel(pos): #3 もし 変数star_stateが "ready" かつ 矢印を クリックしたら
star.angle = arrow.angle #4 矢印の向きを 星の向きに 代入する
star.move_forward(60) #5 星を 60px前に出す
star_state = "shoot" #6 変数star_stateを "shoot(発射)"にする
ポイント
collidepoint_pixel(pos) メゾットで、
矢印が クリックされたか 判定されます。

73. if arrow.collidepoint_pixel(pos):
if 文では、
arrow.collidepoint_pixel(pos) が 「1」になると 『True』になります

へぇ~、クリックすると
星は、矢印の前に 出てくるんだ

Actor( )クラスになるプロパティ:visible を使って
発射する前は 星を非表示にしよう

star.visible = False #1 星を 非表示にする
def draw():
screen.fill("white")
boon.draw()
arrow.draw()
if star.visible: #2 もし 星が表示なら
star.draw() #3 星を 表示する
def star_move(): #4 星の動きをまとめる
global star_state #5 グローバル変数 star_state
if star_state == "shoot": #6 もし変数star_stateが "shoot(発射)なら
star.visible = True #7 星を 表示する
star.move_forward(30) #8 30pxずつ 動かす
if star.x > WIDTH or star.y < 0: #9 もし 星が端より先へ行ったら
star.pos = 100, 500 #10 星の座標を 100, 500
star.visible = False #11 星を 非表示にする
star_state = "ready" #12 変数star_stateを "ready"にする
def update():
arrow_move()
star_move() #13 星を 動かす

星が 発射できるようになったね!
1秒ごとに 矢印に当たらないように現れる

schedule_interval( ) メゾットを使って
1秒ごと boonをランダムに決めた場所へ 表示されるよ

boon_state = "move"
def boon_move(): #1 boonの動きを まとめる
while True: #2 繰り返す
boon.x = random.randint(50, WIDTH-50) #3 boonのx座標を 50~750から ランダムに選んで代入する
boon.y = random.randint(50, HEIGHT-50) #4 boonのy座標を 50~750から ランダムに選んで代入する
if not boon.collide_pixel(arrow): #5 もし 矢印に触れてなければ
break #6 繰り返しから 外れる
clock.schedule_interval(boon_move, 1.0) #7 boon_move()関数を 1秒ごとに 実行する
ポイント
58. While True:
boon.x = random.randint(50, WIDTH-50)
boon.y = random.randint(50, HEIGHT-50)
While文を 使って 矢印触れない場所になるまで 繰り返します。


boonの最初の場所は、決まっているの
狙われるよ

そうだね。
最初の座標もランダムに決められた場所にしよう!
ただし、矢印に触れられない 範囲にするよ
boon = Actor("boon", (random.randint(200, WIDTH-50), random.randint(50, HEIGHT-50)))

最初だけ、boonを表示する 範囲を 決めたよ
星に当たると モザイクが かかって 消える


boonに モザイクを かけるのに
VisualEffect( )を使います
boon = VisualEffect("boon", (random.randint(200, WIDTH-50), random.randint(50, HEIGHT-50))) #1 変数boonに ビジュアルエフェクト(設計図)で作るboonを 代入する
def draw():
screen.fill("white")
boon.draw(screen) #2 スクリーンに boonを 表示する
arrow.draw()
if star.visible:
star.draw()


星に触れたら、
mozaic_animation( ) メゾットと使って、
boonに モザイクを かけていくよ

def star_move():
global star_state
if star_state == "shoot":
star.visible = True
star.move_forward(30)
if star.x > WIDTH or star.y < 0:
star.pos = 100, 500
star.visible = False
star_state = "ready"
elif star.collide_pixel(boon): #1 もし 星が boonに 触れたら
clock.unschedule(boon_move) #2 boon_move()関数を 止める
boon.mozaic_animation() #3 モザイクアニメーションを 開始する
def update():
global boon_state
arrow_move()
star_move()
result = boon.process_animation() #4 アニメーションを 実行する
if result == "finished": #5 変数result(結果)が、finished(終了) なら
boon_state = "reset" #6 変数boon_stateに reset(リセット)を代入する
ポイント
55. clock.unschedule(boon_move)
unschedule( )メゾットで、boonの動きを 止めます

56. boon.mozaic_animation( )
ここから、boonに モザイクをかけます。

71. result = boon.process_animation()
これで、モザイクをかけるアニメーションが 実行します。

このprocess_animation()メゾットは、返り値があるので
変数result(結果)の 中に 代入します。
72. if result == “finished“:
73. boon_state = “reset”
変数result の中に “finished“が 入ったら アニメーション終了です
変数boon_state に、”reset“を 代入します

モザイクをかける速さを変えたい場合は、
3つのプロパティを使って調整できます。

ピクセルの増加量で モザイクになっていく速さが 変わるよ
ポイント
animation_speed(アニメーションのスピード)
フレーム数で モザイクにする時間を変えます
def update( ) 関数では、1秒間に約60フレーム更新されます。
・ animation_speed = 5 : 5フレームごと アニメーション更新
・ animation_speed = 10 : 10フレームごと アニメーション更新
・ animation_speed = 20: 20フレームごと アニメーション更新

animation_speedは、数字が大きくなると 遅くなるよ

モザイクの途中で 止めることが できるよ
みんなも いろいろ試してみてね
スペースキーを押して、リセットする

最後に、
on_key_down(key)関数を使って
スペースキーを押したら、リセットされて動き出すプログラムを
作るよ
def on_key_down(key): #1 押されたキーを 取得する
global boon_state #2 グローバル変数:boon_state
if boon_state == "reset" and key == keys.SPACE: #3 もし 変数が"reset" かつ スペースキーが 押されたら
boon.reset_effects() #4 boonを リセット(元に戻す)する
boon.x = random.randint(200, WIDTH-50) #5 boonのx座標を 200~750からランダムに 決める
boon.y = random.randint(50, HEIGHT-50) #6 boonのy座標を 50~540からランダムに 決める
boon_state = "move" #7 変数boon_stateに "move"を代入する
clock.schedule_interval(boon_move, 1.0) #8 boon_move関数を 1秒後ごとに 実行する

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

今回は、
boonに 当てると モザイクがかかる的当てゲームの
プログラムを 作りました。
import pgzrun
from pgzhelper import *
from visual import VisualEffect
import random
WIDTH = 800
HEIGHT = 590
boon = VisualEffect("boon", (random.randint(200, WIDTH-50), random.randint(50, HEIGHT-50)))
arrow = Actor("arrow", (100, 500))
star = Actor("star", (100, 500))
star_state = "ready"
arrow_direction = 1
star.visible = False
boon_state = "move"
def draw():
screen.fill("white")
boon.draw(screen)
arrow.draw()
if star.visible:
star.draw()
def arrow_move():
global arrow_direction
if star_state == "ready":
arrow.angle += arrow_direction
if arrow.angle > 90 or arrow.angle < 0:
arrow_direction = -arrow_direction
def on_mouse_down(pos):
global star_state
if star_state == "ready" and arrow.collidepoint_pixel(pos):
star.angle = arrow.angle
star.move_forward(60)
star_state = "shoot"
def star_move():
global star_state
if star_state == "shoot":
star.visible = True
star.move_forward(30)
if star.x > WIDTH or star.y < 0:
star.pos = 100, 500
star.visible = False
star_state = "ready"
elif star.collide_pixel(boon):
clock.unschedule(boon_move)
boon.mozaic_animation()
def boon_move():
while True:
boon.x = random.randint(50, WIDTH-50)
boon.y = random.randint(50, HEIGHT-50)
if not boon.collide_pixel(arrow):
break
clock.schedule_interval(boon_move, 1.0)
def update():
global boon_state
arrow_move()
star_move()
result = boon.process_animation()
if result == "finished":
boon_state = "reset"
def on_key_down(key):
global boon_state
if boon_state == "reset" and key == keys.SPACE:
boon.reset_effects()
boon.x = random.randint(200, WIDTH-50)
boon.y = random.randint(50, HEIGHT-50)
boon_state = "move"
clock.schedule_interval(boon_move, 1.0)
pgzrun.go()

キャラクターの見た目を 変えるVisualEffect( )を使って、
boonに モザイクをかけるプログラムを作りました。


キャラクターにモザイクをかけるプログラムを作る手順です。



モザイクをかけるアニメーションの変更は、
この3つのプロパティで 行おう

みんなも試してみてね
それじゃ、またね!