qnote Advent Calendar 2020 の17日目です。
はじめに
私は猫が大好きで、会社にも、自宅にも、実家にも、ついでに姉の家や祖母の家にも猫がいるのですが、プログラムの中でも猫に関わっていたい… と常々思っていました。
今回はそんなときに出会った Nyan という Python ライブラリをご紹介したいと思います。
Nyan とは
https://github.com/ducaale/nyan
https://pypi.org/project/nyan/
Nyan - a fork of Python Play - is an open-source code library for the Python programming language that makes it as easy as possible to start making games.
Nyan は Python Play というプロジェクトを fork して作成された Python 用のオープンソースコードライブラリで、ゲーム作りが簡単に始められるよ。というものらしいです。
README が充実しているので、詳しくは上記サイトをご参照ください。
ソースコードに nyan が溢れていて幸せになります
使い方
python と pip が導入済であれば、下記のインストールコマンドを打つだけで導入完了です。
$ pip install nyan
※ 私の場合 python も pip もバージョンが古くエラーが出てしまったので、python を 3.7.9、pip を 20.1.1 にバージョンアップしたら上手くいきました。
まず試しにサンプルを動かしてみます。
import nyan
cat = nyan.new_text('=^.^=', font_size=70)
@nyan.repeat_forever
async def move_cat():
cat.x = nyan.random_number(-200, 200)
cat.y = nyan.random_number(-200, 200)
cat.color = nyan.random_color()
cat.show()
await nyan.sleep(seconds=0.4)
cat.hide()
await nyan.sleep(seconds=0.4)
@cat.when_clicked
def win_function():
cat.show()
cat.text = 'You won!'
nyan.start_program()
サンプルコードをコピペした py ファイルを作成し、python コマンドで実行。
$ python sample.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
が、起動して pygame のウィンドウは立ち上がるものの、何も表示されません。。
調べてみたところ、Mojave 以降の Mac OS で Python 3.7.x と pygame 1.9.6 だとこの現象が起こるらしいです。
pygame を 2.0.0 にアップデートしたところ、ちゃんと動いてくれました。
$ python sample.py
pygame 2.0.0 (SDL 2.0.12, python 3.7.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
猫社員に変えてみた
クリック対象を 弊社猫社員1 の画像に変更し、クリックされたら猫社員の名前とクリックされるまでに掛かった秒数を表示するようなゲームに変更してみました。
※ 全猫社員をコンプリートしようと奮闘したところ動画が大変長くなってしまったため一部カット編集した都合で、途中カーソルがワープしたりクリア秒数がおかしかったりしますがそこは無視してください。。
ソースコード全文は以下になります。
import nyan
# 画像用意
cats = {
'ふたば': 'images/futaba.png',
'みるく': 'images/milk.png',
'はな': 'images/hana.png',
'ちまき': 'images/chimaki.png',
'りぼん': 'images/ribon.png',
'さくら': 'images/sakura.png',
'みぃ': 'images/mii.png',
'ごまお': 'images/gomao.png',
'チャコ': 'images/chaco.png',
'ミーシャ': 'images/misha.png'
}
key = next(iter(cats))
cat = nyan.new_image(cats[key])
# メッセージ用意
msg = nyan.new_text(text='', x=0, y=-270, font_size=50, font='fonts/font.ttf')
# タイマー用意
timer = nyan.new_timer()
# 初期化処理
def init():
cat.hide()
msg.hide()
timer.reset()
# 初期化してスタート
init()
# 画像の表示/非表示を繰り返す
@nyan.repeat_forever
async def move_cat():
if msg.is_hidden:
# ランダムで画像を指定
global key
key = nyan.random_item(list(cats.keys()))
cat.image = cats[key]
# ランダムでサイズを指定
cat.size = nyan.random_number(30, 70)
# ランダムで表示位置を指定
cat.x = nyan.random_number(-200, 200)
cat.y = nyan.random_number(-200, 200)
# たまにドアップ
if nyan.random_number(1, 30) == 1:
cat.size = 200
cat.x = 0
cat.y = 0
# 画像表示
cat.show()
await nyan.sleep(seconds=0.5)
if msg.is_hidden:
# 画像非表示
cat.hide()
await nyan.sleep(seconds=0.5)
# 画像がクリックされたらクリアタイムを表示
@cat.when_clicked
def clear():
if msg.is_hidden:
cat.size = 175
cat.x = 0
cat.y = 30
cat.show()
msg.text = '(ΦωΦ) ' + key + ' < ' + str(timer.seconds) + '秒!'
msg.color = nyan.random_color()
msg.show()
# メッセージがクリックされたらリスタート
@msg.when_clicked
def restart():
init()
nyan.start_program()
画像とフォントファイルに関しては、プロジェクト内に assets
ディレクトリを作成してその中に格納しておく必要があります。
※今回は assets
配下に更に fonts
、images
ディレクトリを作成していますが、assets
直下にファイル直置きでも大丈夫です。
project_dir
├── qnote_cats.py
└── assets
├── fonts
│ └── font.ttf
└── images
├── chaco.png
├── chimaki.png
├── futaba.png
├── gomao.png
├── hana.png
├── mii.png
├── milk.png
├── misha.png
├── ribon.png
└── sakura.png
軽く解説
画像表示
nyan.new_image() で画像を配置できます。
今回は # 画像用意
の部分で一度スプライトを定義しておき、# 画像の表示/非表示を繰り返す
内で image(画像ファイル)
, size(サイズ)
, x/y(表示位置)
を毎回ランダムに指定する形で使用しています。
表示/非表示は sprite.show()
/ sprite.hide()
で制御できます。
テキスト表示
nyan.new_text() でテキストを配置できます。
今回は # メッセージ用意
の部分で一旦 x/y(表示位置)
, font_size(サイズ)
, font(フォント)
を指定したスプライトを定義しておき、# 画像がクリックされたらクリアタイムを表示
内で text(テキスト文字列)
に猫社員の名前とクリアタイム、 color(文字色)
に nyan.random_color() で取得したランダムな色を指定する形で使用しています。
表示/非表示は画像と同様 sprite.show()
/ sprite.hide()
で制御できます。
タイマー
nyan.new_timer() でタイマーを生成し、timer.seconds
/ timer.milliseconds
で経過時間を取得できます。
また、timer.reset()
でタイマーをリセットできます。
今回は # 初期化処理
内でタイマーをリセットし、# 画像がクリックされたらクリアタイムを表示
内で経過秒数をテキストに表示する形で使用しています。
繰り返し処理
@nyan.repeat_forever と記述することで処理を繰り返し実行させることができます。
今回は画像の表示/非表示処理を繰り返し実行させる形で使用しています。
クリック時の処理
@sprite.when_clicked と記述することでスプライトがクリックされた時に処理を実行させることができます。
今回は画像がクリックされた時はメッセージを表示、メッセージがクリックされた時は初期化処理を実行させる形で使用しています。
さいごに
今回は使用しませんでしたが、Nyan にはオーディオやキー入力等の制御も用意されています。
鳴き声とかも入れたら面白いかなと思ったのですが、素材集めが大変そうだったので断念しました…
いつか素材が集まったら反映してみたいと思います。