シューティングゲームにBGMを追加する
Python向けレトロゲームエンジン「Pyxel(ピクセル)」を使ってのゲーム作成を通してプログラミングを学習します。
シューティングゲーム作成の記事「Pyxel ボスキャラを登場させる - 勉強ボックス管理者ブログ」のコードを例に,BGM再生処理の追加方法を紹介します。
※処理の追加方法だけで,音楽の作り方の記載はありません。例ではサンプルリソースの音をそのまま使います。
※本記事のエディタ画面はPyxel 1.9版のものです。
サンプルリソースファイルの音源
sample.pyxres に入っているサウンドとミュージックを見てみましょう。
Pyxelではサウンドエディタで音を編集して,ミュージックエディタでサウンドの再生順を編集できます。
サウンド
エフェクト (None / Slide / Vibrato / FadeOut) Fで音を分離できます。サウンド0の後半は空欄ですが,指定したエフェクトが繰り返されます。
- サウンド4(ドラム:Noise)
音色(tones)に N:Noise を指定(レトロゲームサウンドではドラムにノイズが使われている)
音量(volumes)で音ごとに音量(0-7)が設定されている。
<参考>
音色の矩形波や三角波について,ゲームでの使われ方は下記ページの動画がわかりやすいです。(音が大きめなので音量は注意)
「さまようけんばん」くだダヰナさん
qdadino.net
ソースコード例
ソースファイルの内容は下記を参照してください。
シューティングゲーム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を指定するとループ再生します。
<デフォルト引数値を持つ関数の例>
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サウンド
音楽 コードの基本