Pyxel BGMの再生

シューティングゲームにBGMを追加する

 Python向けレトロゲームエンジン「Pyxel(ピクセル)」を使ってのゲーム作成を通してプログラミングを学習します。

 シューティングゲーム作成の記事「Pyxel ボスキャラを登場させる - 勉強ボックス管理者ブログ」のコードを例に,BGM再生処理の追加方法を紹介します。

 ※処理の追加方法だけで,音楽の作り方の記載はありません。例ではサンプルリソースの音をそのまま使います。
 ※本記事のエディタ画面はPyxel 1.9版のものです。
 

サンプルリソースファイルの音源

 sample.pyxres に入っているサウンドとミュージックを見てみましょう。
 Pyxelではサウンドエディタで音を編集して,ミュージックエディタでサウンドの再生順を編集できます。
 

サウンド

 音色(tones)に P:Pulse(パルス波),S:Square(矩形波 くけいは)を指定
 エフェクト (None / Slide / Vibrato / FadeOut)  Fで音を分離できます。サウンド0の後半は空欄ですが,指定したエフェクトが繰り返されます。

 音色(tones)にT:Triangle(三角波)を指定


 音色(tones)に N:Noise を指定(レトロゲームサウンドではドラムにノイズが使われている)
 音量(volumes)で音ごとに音量(0-7)が設定されている。

 
 <参考>
 音色の矩形波三角波について,ゲームでの使われ方は下記ページの動画がわかりやすいです。(音が大きめなので音量は注意)
 「さまようけんばん」くだダヰナさん

qdadino.net

 

ミュージック

 作成したサウンドを組み合わせてミュージック(0-7)に登録します。こちらもサンプルリソースに設定済みのミュージック0を見てみましょう。

  • ミュージック0

 
 チャンネル0:メロディー用のサウンド0に続けて1を再生
 チャンネル1:ベース用のサウンド2に続けて3を再生
 チャンネル2:ドラム用のサウンド4を再生

 Pyxelでは4音まで同時に再生できます。(チャンネル0-3)
 次のソースコードの例では,空いているチャンネル3で効果音を再生させます。
 

ソースコード

 ソースファイルの内容は下記を参照してください。
 シューティングゲーム05 - Google ドライブ

sound.py と デフォルト引数値を持つ関数

 音関連の処理を記述するソースファイルを新規に追加します。(自機クラスで弾を撃ち,AppクラスでBGM再生と爆発音を鳴らすため,pyxelの命令の記述を1ファイルにまとめておく意図があります)
【ソースコード】はこちらのリンクから確認してください(Googleドキュメント)

sound.py

import pyxel

SND_SHOT = 60
SND_BLAST = 61
BGM = 0
SE_CH = 3

def init():
    pyxel.sound(SND_SHOT).set("a3a2c1a1", "p", "7", "s", 5)
    pyxel.sound(SND_BLAST).set("a3a2c2c2", "n", "7742", "s", 10)

def shot():
    pyxel.play(SE_CH, SND_SHOT)

def blast():
    pyxel.play(SE_CH, SND_BLAST)

def bgm():
    pyxel.playm(BGM, loop=True)

・pyxel.sound(SND_SHOT).set("a3a2c1a1", "p", "7", "s", 5)
 サウンド0とサウンド1をリソースファイルから読み込んだものにするため,ソースでset()する効果音をサウンド60と61に変更しました。

・pyxel.play(SE_CH, SND_SHOT)
 効果音用のチャンネルを3だけにしたので,弾を撃つときの音と爆発の音が重なるときは期待した音にならない点に注意。

・pyxel.playm(BGM, loop=True)

playm(msc, [tick], [loop])
 ミュージックmsc (0-7) を再生します。
 再生開始位置はtick (1 tick = 1/120 秒) で指定できます。
 loopにTrueを指定するとループ再生します。

 ※APIリファレンスで省略可能となっている引数を渡すときは「仮引数名=値」で記述して,何の値か判別できるようにします。

<デフォルト引数値を持つ関数の例>

def myfunc( num=99, msg="default" ):
    print(num,msg)

myfunc()
myfunc(num=10)
myfunc(msg="new!")

実行結果

99 default
10 default
99 new!

 関数の定義で引数を「仮引数名=デフォルト値」のように記述すると,その関数はデフォルト引数値を持つようになります。
 呼び出し時にその引数が省略された場合は,定義の値がデフォルト値として使用されます。
 呼び出し元がその値を変更したいときは「仮引数名=値」で記述して呼び出します。

 

player.py

【ソースコード】はこちらのリンクから確認してください(Googleドキュメント)
player.py抜粋

import sound as snd
・・・
class Player:

    def update(self):
・・・
        if pyxel.btnp(pyxel.KEY_SPACE,15,15) or pyxel.btnp(pyxel.GAMEPAD1_BUTTON_A,15,15):
            Bullet(
                self.x + PLAYER_WIDTH - BULLET_WIDTH / 2,
                self.y + (PLAYER_HEIGHT - BULLET_HEIGHT) / 2
            )
            snd.shot()

・sound.pyの関数 shot() を呼び出して効果音を再生するように変更。

 

stg_main.py

【ソースコード】はこちらのリンクから確認してください(Googleドキュメント)

stg_main.py抜粋

import sound as snd
・・・
class App:
    
    def __init__(self):
        pyxel.init(240, 160, title="Pyxel Shooter r")
        pyxel.load("sample.pyxres")
        snd.init()
        snd.bgm()
・・・

    def update_play_scene(self):
・・・
        for enemy in en.enemies:
・・・
                        if enemy.life <= 0 and en.TYPE_NORMAL == enemy.type:
                            enemy.is_alive = False
                            ef.blasts.append(
                                ef.Blast(enemy.x + enemy.w / 2,
                                      enemy.y + enemy.h / 2)
                            )
                            snd.blast()

・snd.init()
 リソースファイルの読み込み後に,効果音追加処理を呼び出してサウンド60と61を上書きしています。

・snd.bgm()
 タイトル画面の時点でBGM再生を開始しています。

※ゲームの進行に合わせて曲を切り替えたいときは,pyxel.stop()命令で停止してからpyxel.playm()で再生を開始するとよいでしょう。

stop([ch])
 指定したチャンネルch (0-3) の再生を停止します。
 stop()で全チャンネルの再生を停止します。

 

【参考】ソースコードでのサウンド設定からリソースファイルへの変換

 弾を撃つときと爆発の効果音をソースコードで設定しています。
 この音をリソースファイルで設定する場合は,以下のようになります。サウンド番号は適宜変更してください)

  • pyxel.sound(0).set("a3a2c1a1", "p", "7", "s", 5)

 

  • pyxel.sound(1).set("a3a2c2c2", "n", "7742", "s", 10)

 

 鍵盤の位置(ピアノロール)との関係は以下の記事を参照してください。kinutani.hateblo.jp


 BGM再生の追加の仕方については以上です。まずは自由にサウンドを編集して鳴らしてみましょう。
 ゲームの雰囲気に合わせた音楽の作り方は,下記のような内容を調べてみてください。
  レトロゲームサウンド 作り方
  8bitサウンド
  音楽 コードの基本

 

関連記事

シューティングゲームのアプリを単独で動作するHTMLファイルに変換する手順の記事です。
kinutani.hateblo.jp

kinutani.hateblo.jp