プチコン3号 8日目 BGMや効果音をつける

ゲームに効果音やBGMが付くと、それだけで意外と印象が変わります。
プチコン3号には、最初からゲーム用の効果音が134種、BGMが43曲ついています。
また、オリジナルの曲をMMLで記述してBGMとして使うこともできます。

まずはダイレクトモードで音を出してみました。

pc8-0.jpg

BEEPの使い方は以下の通りです。

BEEP 音の番号,音の高さ,音量,パンポット

音の番号は0~133、音の高さは-32768〜32767、音量は0~127、パンポットは0~127です。
音の高さはセント(半音の1/100)単位で、負の値にすると元の音より低くなります。-1200で1オクターブ下がります。
パンポットは左端が0、中央が64、右端が127です。

BGMはBGMPLAYコマンドで流します。
パラメータはトラック番号(0~7)、曲番号(0~42)、音量(0~127)です。
異なるトラック番号を指定することで、8つまでのBGMを同時に流すことができます。
あるいは、同じ曲を別のトラックで再生すれば、最大音量よりも大きな音で鳴らすこともできます。

EFCSET命令でエフェクトをかけることができます。
パラメータは0~3で、大きいほど強くリバーブ(いわゆるエコー)がかかります。

BGMはプログラムの動作とは関係なく流れっぱなしになりますので、止めるにはBGMSTOPコマンドを使います。

全般的にプチコン3号の音関連の命令はよくできていて、音を鳴らすプログラミングに手をかける必要はあまり無さそうです。

今日は、「プチコン3号 3日目 絵をボタン操作で動かす」で作ったプログラムにBGMと効果音をつけてみました。
やったことは
・BGMを流す
・移動時に、移動スピードに合わせて音を出す
・ジャンプ時に音を出す
の3つです。

プログラムはこちらです。
スプライトをスライドパッドで操作する部分については、3日目に説明しましたので省略します。
7行目・8行目のMIN、MAXの使い方も、前回説明しましたのでそちらを見てください。

pc8-1.jpg
X=192:Y=112:Z=500
DZ=0
SPSET 0,310
BGMPLAY 26
@LOOP
STICK OUT DX,DY
X=MIN(MAX(X+DX*3,0),368)
Y=MIN(MAX(Y-DY*3,0),208)
IF WALK_CNT < 1 THEN
V=DX*DX+DY*DY
IF DZ == 0 && V > 0 THEN BEEP 2,-1500
V=FLOOR(V*7)
WALK_CNT = 20 / (1+V)
ELSE
DEC WALK_CNT
ENDIF
IF DZ==0 THEN
DZ=16 AND BUTTON(2)
IF DZ >0 THEN BEEP 8, 1500
ENDIF
Z=Z-DZ
IF Z<-200 THEN DZ=-DZ
IF Z>500 THEN DZ=0:Z=500
SPOFS 0,X,Y,Z
S=1.0+(500-Z)/500
SPSCALE 0,S,S
VSYNC 1
GOTO @LOOP

4行目でBGMを開始しています。
BGM関連の処理はこれだけです。

移動しているときに音を出す処理が9行目からのIF文です。
移動スピードに合わせて音を変える方法は、いろいろなものが考えられます。

たとえば
・移動している速さによって音の高さを変える
・移動している速さによって音の種類を変える
・移動している速さによって音のタイミングを変える
などです。

今回は、早く移動しているときは短い間隔で、ゆっくり移動しているときは長い間隔で音を出してみました。

変数WALK_CNTでBEEP文を実行する間隔を調整しています。
WALK_CNTは0になるとBEEPを実行します。
0でなければ、15行目のDEC文でWALK_CNTを1減らします。
(ちなみにDECは英語のdeclimentに由来します。)

BEEPを実行する前にまず、Vに移動速度に比例する正の数をセットしています。
DX、DYは-1.0~1.0の値を取りますので、2乗して正の数にします。
そして、「ジャンプ中でなく(DZ==0)」「停止中でなければ(V>0)」BEEPを実行します。

そのあと、次のBEEPの実行までの間隔を、WALK_CNTに設定します。
設定する値は「20/(1+V)」となっています。Vの最小値は0ですので、設定する値の最大値は20です。
ループの一周は1/60秒ですので、もっとも間隔が長いときは毎秒3回BEEPが実行されることになります。

もし、速さに関係なく一定間隔でBEEPを実行するだけなら、このプログラムでWALK_CNTに代入する値を一定値にするか、さらに簡単にはシステム変数MAINCNTを使い、

IF MAINCNT MOD 16 == 0 THEN BEEP 2

とする方法もあります。

ジャンプしたときの効果音は、19行目で出しています。
ジャンプについては処理はこれだけです。
音量やパンポットの設定もしていませんが、たとえばXの値(0~368)に応じてパンポットを設定しても良いかもしれませんね。
その場合はこのBEEP文は

BEEP 8, 1500, 127, X*127/368

というようになるでしょう。

プチコンのサウンドプログラミングはすごく楽ですね。

最後に注意点ですが、非常に短い間隔でBEEPを繰り返し呼ぶと、プチコン3号そのものが不安定になるようです。
作成中のプログラムが消えてしまう場合もあります。
たとえば以下の1行プログラムは実行するとプチコンが再起動してしまいました。

@1:BEEP 2:GOTO @1

ループの中でBEEPを呼ぶ場合には、ループの中に少なくともVSYNCは入れましょう。

コメント