ニャオニャオ21世紀

レトロゲーム(MSX、PCエンジン、セガサターン)と、MSXぽいアプリ開発と、最新ゲーム(PS4、SWITCH)、身体(身体意識など)、ライフハックほか雑記を綴っています

MSX BASICの基礎 その9 ゲーム中にPLAY文でBGMを流す方法! 当時の投稿は無音のゲームが多かったですね^^






f:id:nyaonyaokun:20181023064954j:plain

 

BASICでBGMを流すのは、

普通にPLAY文でMML(ドレミみたいなの^^)を書くだけでは

ダメなのです。

 

当時は全く知らなかったです(^^;)

 

ベーマガとか、MSX FANの投稿BASICゲームでは、

タイトルのみ音楽が流れて、ゲーム中は無音というゲームが多かったのを覚えています。

 

BGMを鳴らす方法としては、

1/60とかで、インターバル割り込みをかけて、短く区切ったPLAY文を鳴らすという方法をとります。

(MSXマガジン 永久保存版1で初めて方法を知りました^^;) 

 サンプル実行はこちらWebMSX

 

ダウンロード

スポンサーリンク

 

 

 

ソースコード

10 COLOR15,1,1:SCREEN2:SCREEN1,2:COLOR15,1,1:WIDTH32:DEFINTA-Z:KEYOFF
20 DEFUSR=&H7E:A=USR(0)
30 KEY1,"SCREEN1"+CHR$(13)
40 'EN<TEKI NO NUMBER>,EK<TEKI NO KAZU>,EX()<TEKI X ZAHYOU>,EY()<TEKI Y ZAHYOU>,EM()<TEKI NO MOVE RYOU>
44 EN=0:EK=4:DIMEX(4):DIMEY(4):DIMEM(4):DIMUX(4):DIMUY(4)
45 X=160:Y=120:H=0
46 EX(0)=160:EY(0)=8:EX(1)=96:EY(1)=32:EX(2)=160:EY(2)=144:EX(3)=96:EY(3)=104
47 EM(0)=8:EM(1)=-8:EM(2)=8:EM(3)=-8
48 IF GO=1 THEN GO=0:GOTO500
50 'MOJI TEIGI
51 N=ASC("A")
52 FOR J=0 TO 25
53 FOR I=0 TO 7
54 VPOKE &H800+N*8+I,VPEEK(N*8+I)
55 VPOKE &H1000+N*8+I,VPEEK(N*8+I)
56 'COLOR TEIGI
57 VPOKE &H2000+N*8+I,&HF1
58 VPOKE &H2800+N*8+I,&HF1
59 VPOKE &H3000+N*8+I,&HF1
60 NEXT
61 N=N+1
62 NEXT
63 LOCATE10,10:PRINT"PLEASE WAIT!"
70 'SPRITE TEIGI
75 RESTORE 2000
77 FOR J=0 TO 9
80 S$=""
90 FOR I=0 TO31
100 READ DT$:
110 S$=S$+CHR$(VAL("&H"+DT$))
120 NEXT
130 SPRITE$(J)=S$
140 NEXT
160 'BLOCK TEIGI
170 M=ASC("a")
175 RESTORE 4000
178 FOR J=0 TO 10
180 FOR I=0 TO 7
190 READ BG$
200 VPOKE M*8+I,VAL("&H"+BG$)
210 VPOKE &H800+M*8+I,VAL("&H"+BG$)
220 VPOKE &H1000+M*8+I,VAL("&H"+BG$)
222 NEXT
225 M=M+1
230 NEXT
234 M=ASC("a")
235 RESTORE 5000
236 FOR J=0 TO 10
240 FOR I=0 TO 7
250 READ CR$
260 VPOKE &H2000+M*8+I,VAL("&H"+CR$)
270 VPOKE &H2800+M*8+I,VAL("&H"+CR$)
280 VPOKE &H3000+M*8+I,VAL("&H"+CR$)
283 NEXT
285 M=M+1
290 NEXT
490 'MAP
500 LOCATE 0,0:PRINT "caaaaaaaaaaaaaaaaaaaaaaaaaaaaaad"
510 LOCATE 0,1:PRINT "b b"
520 LOCATE 0,2:PRINT "b b"
530 LOCATE 0,3:PRINT "b j haaaaaaad haaaaaaaaaai b"
540 LOCATE 0,4:PRINT "b b b b"
550 LOCATE 0,5:PRINT "b b b b"
560 LOCATE 0,6:PRINT "b eaaaaaaai b caaaaaaaaaad b"
570 LOCATE 0,7:PRINT "b b b b b"
580 LOCATE 0,8:PRINT "b k b b b"
590 LOCATE 0,9:PRINT "b cd caaad b j cad b b"
600 LOCATE 0,10:PRINT"b bb b b b b b b b b"
610 LOCATE 0,11:PRINT"b bb b b j b b eaf k b"
620 LOCATE 0,12:PRINT"b ef eaaaf b b b b"
630 LOCATE 0,13:PRINT"b b b b b"
640 LOCATE 0,14:PRINT"b b b eaaaaaaai b"
650 LOCATE 0,15:PRINT"b cd caaaaaab b b"
660 LOCATE 0,16:PRINT"b bb b b b b"
670 LOCATE 0,17:PRINT"b ef b k eaaaaaaaaaai b"
680 LOCATE 0,18:PRINT"b b b"
690 LOCATE 0,19:PRINT"b b b"
700 LOCATE 0,20:PRINT"eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaf"
890 'BGM WARIKOMI
900 RESTORE 21000
910 GOSUB 1860
920 ON INTERVAL=80 GOSUB 1860
930 INTERVAL ON
995 'MAIN LOOP
996 'PLAYER
998 M=ASC("a")-1
999 H=4
1000 S=STICK(0) OR STICK(1)
1005 'PLAYER
1010 TX=X:TY=Y
1020 IF S=1 THEN Y=Y-8:H=(H+1)MOD 2
1040 IF S=3 THEN X=X+8:H=( (H+1)MOD 2)+2
1060 IF S=5 THEN Y=Y+8:H=( (H+1)MOD 2)+4
1080 IF S=7 THEN X=X-8:H=( (H+1)MOD 2)+6
1100 A$=CHR$(VPEEK(&H1800+(X\8)+(Y\8)*32))
1110 B$=CHR$(VPEEK(&H1800+(X\8)+1+(Y\8)*32))
1120 C$=CHR$(VPEEK(&H1800+(X\8)+(Y\8+1)*32))
1130 D$=CHR$(VPEEK(&H1800+(X\8)+1+(Y\8+1)*32))
1140 IF ASC(A$)>M THEN X=TX:Y=TY
1150 IF ASC(B$)>M THEN X=TX:Y=TY
1160 IF ASC(C$)>M THEN X=TX:Y=TY
1170 IF ASC(D$)>M THEN X=TX:Y=TY
1210 'ENEMY
1220 UX(EN)=EX(EN):UY(EN)=EY(EN)
1230 EX(EN)=EX(EN)+EM(EN)
1240 AE$="#":BE$="#":CE$="#":DE$="#"
1250 AE$=CHR$(VPEEK(&H1800+(EX(EN)\8)+(EY(EN)\8)*32))
1260 BE$=CHR$(VPEEK(&H1800+(EX(EN)\8)+1+(EY(EN)\8)*32))
1270 CE$=CHR$(VPEEK(&H1800+(EX(EN)\8)+(EY(EN)\8+1)*32))
1280 DE$=CHR$(VPEEK(&H1800+(EX(EN)\8)+1+(EY(EN)\8+1)*32))
1290 IF ASC(AE$)>M THEN EX(EN)=UX(EN):EY(EN)=UY(EN)
1300 IF ASC(BE$)>M THEN EX(EN)=UX(EN):EY(EN)=UY(EN)
1310 IF ASC(CE$)>M THEN EX(EN)=UX(EN):EY(EN)=UY(EN):EM(EN)=-EM(EN)
1320 IF ASC(DE$)>M THEN EX(EN)=UX(EN):EY(EN)=UY(EN):EM(EN)=-EM(EN)
1322 'ATARI HANTEI
1325 GOSUB1680
1327 'GAME OVER HANTEI
1330 IF GO=1 THEN GOTO1820
1332 'SPRITE HYOUJI
1333 PUT SPRITE 0,(X ,Y-1),11,H
1335 PUT SPRITE EN+1,(EX(EN),EY(EN)-1),13,8
1340 EN=EN+1:IF EN>EK-1 THEN EN=0
1350 GOTO1000
1680 'PLAYER ATARI HANTEI
1690 ED=99
1700 FOR I=0 TO EK-1
1710 IF ABS(X-EX(I))<16 AND ABS(Y-EY(I))<16 THEN ED=I
1720 NEXT
1730 IF ED=99 THEN RETURN
1740 X=TX:Y=TY
1747 'PLAYER OUT SPRITE
1750 PUT SPRITE 0,(X,Y-1),8,9
1760 'WAIT
1770 FOR I=0 TO 25
1775 BEEP
1780 NEXT
1790 GO=1
1800 RETURN
1810 'GAME OVER
1820 LOCATE 11,10:PRINT"GAME OVER"
1830 LOCATE 10,12:PRINT"PUSH RETURN"
1840 IF INKEY$<>CHR$(13) GOTO1840
1850 GOTO45
1855 'BGM
1860 IF PEEK(&HFB40)<>0 THEN RETURN
1870 READ U$
1880 IF U$="##" THEN RESTORE 21000:READ U$
1890 PLAY"L4O5"+U$
1900 RETURN
1995 'SPRITE UP0 DATA
2000 DATA 0F,1F,3F,7F,7F,7F,7F,7F,3F,1F,0F,30,03,01,1C,1C
2010 DATA F0,F8,FC,FE,FE,FE,FE,FE,FC,F8,F0,0C,CC,C0,38,00
2015 'SPRITE UP1 DATA
2020 DATA 0F,1F,3F,7F,7F,7F,7F,7F,3F,1F,0F,18,1B,03,1C,00
2030 DATA F0,F8,FC,FE,FE,FE,FE,FE,FC,F8,F0,0C,C0,B8,38,38
2035 'SPRITE RIGHT2 DATA
2040 DATA 0F,1F,3D,7D,7F,7F,7F,7F,3F,1F,0F,00,03,19,04,0E
2050 DATA F0,F8,F0,E0,C0,80,00,00,80,E0,F0,0C,CC,C0,30,38
2055 'SPRITE RIGHT3 DATA
2060 DATA 0F,1F,3F,7F,7F,7F,7E,7F,3F,1F,0F,00,1B,19,03,03
2070 DATA E0,F0,B8,B8,FC,FC,FC,00,F8,F0,E0,00,D8,C0,60,60
2075 'SPRITE DOWN4 DATA
2080 DATA 0F,1F,3B,7B,7B,7F,7F,77,38,1F,0F,30,03,1D,1E,1C
2090 DATA F0,F8,DC,DE,DE,FE,FE,EE,1C,F8,F0,0C,CC,C0,38,00
2095 'SPRITE DOWN5 DATA
2100 DATA 0F,1F,3B,7B,7F,7F,7B,7B,3C,1F,0F,18,1B,03,1C,00
2110 DATA F0,F8,DC,DE,FE,FE,DE,DE,3C,F8,F0,0C,C0,B8,78,38
2115 'SPRITE LEFT6 DATA
2120 DATA 0F,1F,0F,07,03,01,00,00,01,07,0F,30,33,03,0C,1C
2130 DATA F0,F8,BC,BE,FE,FE,FE,FE,FC,F8,F0,00,C0,98,20,70
2135 'SPRITE LEFT7 DATA
2140 DATA 07,0F,1D,1D,3F,3F,3F,00,1F,0F,07,00,1B,03,06,06
2150 DATA F0,F8,FC,FE,FE,FE,7E,FE,FC,F8,F0,00,D8,98,C0,C0
3275 'SPRITE SLIME DATA
3280 DATA 3F,7F,FF,FF,FF,CF,F3,FF,EB,E3,FF,FF,FF,FF,FF,ED
3290 DATA FC,FE,FF,FF,E7,DB,FF,C7,D7,C7,FF,FF,FF,FF,FF,B7
3300 'SPRITE DAMAGE
3310 DATA 00,01,21,11,09,04,00,78,00,04,09,11,21,01,00,00
3320 DATA 00,00,08,10,20,40,00,3C,00,40,20,10,08,00,00,00
3990 'YUKA
4000 'DATAE7,E7,E7,00,7E,7E,7E,00
4010 DATAFF,FF,00,00,00,00,FF,FF
4020 DATAC3,C3,C3,C3,C3,C3,C3,C3
4030 DATA0F,1F,38,70,E0,C0,C1,C3
4040 DATAF0,F8,1C,0E,07,03,83,C3
4050 DATAC3,C1,C0,E0,70,38,1F,0F
4060 DATAC3,83,03,07,0E,1C,F8,F0
4070 DATAC3,83,03,07,0E,1C,F8,F0
4080 DATA7F,FF,E0,C0,C0,E0,FF,7F
4090 DATAFE,FF,07,03,03,07,FF,FE
4100 DATA7E,FF,E7,C3,C3,C3,C3,C3
4110 DATAC3,C3,C3,C3,C3,E7,FF,7E
4990 'COLOR
5000 DATAF1,51,41,41,41,41,51,41
5010 DATA41,41,41,41,41,41,41,41
5020 DATAF1,51,41,41,41,41,41,41
5030 DATAF1,51,41,41,41,41,41,41
5040 DATA41,41,41,41,41,41,51,41
5050 DATA41,41,41,41,41,41,51,41
5060 DATA41,41,41,41,41,41,41,41
5070 DATAF1,51,41,41,41,41,51,41
5080 DATAF1,51,41,41,41,41,51,41
5090 DATAF1,51,41,41,41,41,41,41
5100 DATA41,41,41,41,41,41,51,41
20990 'MUSIC DATA
21000 DATAG4E8E4F8E8D8C8
21010 DATAG4E8E8D4R4
21020 DATAE8E8G8G8A8A8R8A8
21030 DATAO6C4O5E8E8G4R4
21040 DATAGE8E8F8E8D8C8
21050 DATAGE8E8D4R4
21060 DATAGE8E8A4G8G8
21070 DATAA8A8B8B8O6C4O5R4
21080 DATA##

 

 

BGMの解説

解説

890 'BGM WARIKOMI
900 RESTORE 21000
910 GOSUB 1860
920 ON INTERVAL=80 GOSUB 1860
930 INTERVAL ON

最初に、割り込みをかける宣言をします。

920 ON INTERVAL=80 GOSUB 1860
930 INTERVAL ON

 80 * 1/60秒ごとに、1860行を呼び出します。

 

1860行以降にPLAY文を書きます。

1855 'BGM
1860 IF PEEK(&HFB40)<>0 THEN RETURN
1870 READ U$
1880 IF U$="##" THEN RESTORE 21000:READ U$
1890 PLAY"T120O5"+U$
1900 RETURN

1870行で、曲のデータを読み込みます。

1880行で、DATAで##の値がでたら、曲の最初のDATA文に戻ります。

つまり曲をリピートする訳です。

 

1890行で、曲全体のテンポですとかを設定しておきます。

 

曲のデータです。

1行ごと演奏しています。

20990 'MUSIC DATA
21000 DATAG4E8E4F8E8D8C8
21010 DATAG4E8E8D4R4
21020 DATAE8E8G8G8A8A8R8A8
21030 DATAO6C4O5E8E8G4R4
21040 DATAGE8E8F8E8D8C8
21050 DATAGE8E8D4R4
21060 DATAGE8E8A4G8G8
21070 DATAA8A8B8B8O6C4O5R4
21080 DATA##

 

今回のプログラムで一番大切なのが、

1860 IF PEEK(&HFB40)<>0 THEN RETURN

です^^

 

メモリの&HFB40のデータをチェックしています。

この&HFB40のアドレス(ワークエリア内)には何があるかといいますと、

MSXマガジン 永久保存版3にはこう書かれています。

”キューイングされているPLAY文の数"

 

つまり、今音楽がなっているかどうか?がチェックできるのです!

このプログラムでは、PLAY文の予約数がゼロのときに、

1870行以降の、BGMデータを読み込んでPLAY文を実行します。

 

BASICでPLAY(0)という、曲がなっているかどうか知ることができる命令もあるのですが、反応が遅いというか、ぶちぶちの音になってしまいます(~~;)

A = PLAY(0)

3音のうちどれかがなっていれば-1が入り、無音なら0が入ります。 

 

 

あとはどんな音楽をつけるか?ですね^^

僕は、音楽についてな にも知らないので、今勉強しています^^;

 

PLAY文の基礎MMLについて

 

ドレミファソラシ -> CDEFGAB

 O4

ド  ->  C

レ  ->  D

ミ  ->  E

ファ ->  F

ソ    ->  G

ラ    ->  A

シ    ->  B

 

ド -> O5C

となっています。

 

音階 :  O1 ~ O8

普通のド?はO4のCです(^^;)

数字の大きい方が、高い音です。

 

音程 : N   0 ~ 96

うーん、よくわかりません^^;

N95とか書きます。

 

音長 : L  音長を( 1 / 数値 )音に設定します。

    初期値が4です。

    L1が全音符、L2が2分音符、L64の64分音符まで。

    僕はC4D4E8F8とかって曲を書いてます。

    

. (ピリオド)   音長を3/2倍にします。2個続けると9/4倍、3個で27/8倍とか。

    わかりません( ・∇・)

 

テンポ : T   演奏のテンポです。32 ~ 255の間です。

     よく聞くBPMとかいうやつでしょうか?

     初期値はT120だそうです。

 

音量 :  V   0が無音、15が最大です。PLAY"V15C8V14C8V13C8V12C8V11C8V10C8V9C8V8C8V7C8V6C8V5C8V4C8V3C8V2C8V1C8"  

ってやるといい感じの音がでます(^∇^)

 

音色 : S  エンベロープ形状(音量変化の波形)を設定します。

              1 ~ 65535までになります。

          M 周期

  PLAY"SM1000CDEFG"などとやります。

   

      どこかで見かけたマリオのコイン音は、

    PLAY"O6S1M5000L16CE2"

      これはすごい^^

 

小学校の時に習った、

三和音がどうだこうだというのも、

全部忘れているので勉強しています。

 

やっぱり自分で作曲したBGMを流したいですし、ね^^

 

以外にネットでMSXのMMLを公開している方がいなくて苦労しています(~~;)

 

とりあえずは、PSGの3音を鳴らします。

FM音源の音とか好きですが、まぁMSX1にはあまり関係ないのかな^^

 

 時々チェックすると、いいものがあるかもしれないです^^

 

MSX ゲーム・本体・雑誌など

 

 

 

 


「ニャオニャオ21世紀は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。」

当サイトは第三者配信の広告サービス「Google Adsense グーグルアドセンス」を利用しています。 広告配信事業者は、ユーザーの興味に応じた広告を表示するためにCookie(クッキー)を使用することがあります。 Cookie(クッキー)を無効にする設定およびGoogleアドセンスに関する詳細は「広告 – ポリシーと規約 – Google」をご覧ください