LoginSignup
3
6

More than 5 years have passed since last update.

Pyxel上でPygameを使ったイントロ付きのループBGMを流す方法

Last updated at Posted at 2018-12-13

この記事はゲームサウンド制作 Advent Calendar 2018の13日目として参加しました。
https://adventar.org/calendars/3229

はじめに

最近Pyxel( https://github.com/kitao/pyxel/blob/master/README.ja.md )を触る機会があった。
Pyxel内でも楽曲を作ることもできるが、自作のチップチューン楽曲を組み込みたかったので音源ファイルを呼び出す形で再生する方法としてPygameを使うことに。

ゲーム中にBGMを再生したい時、BGMによってはイントロを流した後、そのイントロを除いて楽曲をループさせたいという要件は少なからずある。しかし、現時点(2018/12/13)でのPygameのpygame.mixer.musicモジュールにある関数ではそのような要件を満たすことはできなかった。

ならば作ってしまおう、ってことで作ってみた。
ちなみに、stack overflowの「Pygame Music Queue not functioning」の質問の回答コードがとても良いヒントだったのでこれを参考にした。
https://stackoverflow.com/a/52578305

サンプルコードではPyxelの 01_hello_pyxel.py をベースにしている。

実装前提は以下のとおり。

Pyxel,Pygame インストール済み
01_hello_pyxel.py の主処理は省略

サンプルコード

mp3,oggファイルの場合

01_hello_pyxel_mp3.py
  1 import pygame
  2 import pyxel
  3 
  4 class MusicPlayer:
  5     def __init__(self,filename):
  6         pygame.mixer.init()
  7         pygame.mixer.music.load(filename)
  8         pygame.mixer.music.play(1) #イントロ有りで1曲丸々再生
  9         
 10     def loop(self,time=0.0):
 11         pos = pygame.mixer.music.get_pos() #再生している音楽の再生時間を取得する
 12         if int(pos) == -1: #再生が終了するとposは-1を返すんだって!知らなかった!
 13             pygame.mixer.music.play(-1,time) #-1を指定することでループ再生、timeの指定秒数からスタートさせる
 14             
 15             
 16 class App:  
 17     def __init__(self):
            ~~
 20         self.music_player = MusicPlayer('test.mp3')
 21         pyxel.run(self.update, self.draw)
 22         
 23     def update(self):
 24         self.music_player.loop(time=3.0) #time(ミリ秒まで指定可能)を指定することで指定秒数からスタートさせる
 25         ~~
 28             
 29     def draw(self):
            ~~
 33 App()

wavファイルの場合

Pygameの仕様で、mp3とoggファイルは再生位置指定をすれば1つのファイルだけで済むが、wavファイルは再生位置指定ができないから、イントロ部(intro_~.wav)とループ部(main_~.wav)の2つのファイルを用意しないといけない。

01_hello_pyxel_wav.py
  1 import pygame
  2 import pyxel
  3 
  4 class MusicPlayer:
  5     def __init__(self,filename):
  6         self._filename = filename
  7         pygame.mixer.init()
  8         pygame.mixer.music.load('intro_'+self._filename) #イントロ部分のwavファイルを読み込む
  9         pygame.mixer.music.play(1)
 10     
 11     def loop(self):
 12         pos = pygame.mixer.music.get_pos()
 13         if int(pos) == -1:
 14             pygame.mixer.music.load('main_'+self._filename) #メインループのwavファイルを読み込む
 15             pygame.mixer.music.play(-1) #-1でループ再生
 16 
 17 
 18 class App:
 19     def __init__(self): 
            ~~
 22         self.music_player = MusicPlayer('test.wav')
 23         pyxel.run(self.update, self.draw)
 24     
 25     def update(self):
 26         self.music_player.loop()
            ~~
 30     
 31     def draw(self):
            ~~
 35 App()

おわりに

サンプルコードはPyxel上で動くものだが、Pygame本体でもメインループ内にloop関数を仕込めばできるはずなので、作ってみたい人は作ってみて欲しい。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6