効果音(2/2) |
まとめますと、以下の通りです。
; プログラム起動時の初期設定 dsinit ; SEを読み込む dsloadfname "explodes.wav",1 ; ザコ爆発音 dsloadfname "explodem.wav",2 ; 中型敵、ボス爆発音 dsloadfname "damage.wav",3 ; 敵ダメージ音 dsloadfname "crushed.wav",4 ; 自機爆発音 dsloadfname "itemget.wav",5 ; アイテム取得音 dsloadfname "oneup.wav",6 ; ワンアップ音 dsloadfname "bomb.wav",7 ; ボム音 dsloadfname "shot.wav",8 ; 自機のショット音 ; 自機弾の射出 if ((playerf=1)|(playerf=2))&(ckey=1) { shotcnt=shotcnt+1 if shotcnt=4 { shotcnt=0 repeat noption+1 i=cnt n=-1 repeat 4 if shotf.i.cnt=0 { n=cnt break } loop if n!-1 { dsplay 8 if i=0 { shotx.i.n=playerx+14 shoty.i.n=playery-16 } else { j=i-1 shotx.i.n=optionx.j+14 shoty.i.n=optiony.j-16 } shotf.i.n=1 } loop } } ; 自機と敵、敵弾の当たり判定 if playerf=1 { f=0 repeat 10 k=enekind.cnt l=32*(eneclass.k+1)-1 if ((enemyf.cnt=1)|(enemyf.cnt=2))&((playerx+15)<=(enemyx.cnt+l)) &((playerx+16)>=enemyx.cnt) &((playery+15)<=(enemyy.cnt+l)) &((playery+16)>=enemyy.cnt) { f=1 enemyno=cnt gosub *Enemy_Dmg } loop repeat 100 if (eshotf.cnt=1)&((playerx+15)<=(eshotx.cnt+7)) &((playerx+16)>=eshotx.cnt) &((playery+15)<=(eshoty.cnt+7)) &((playery+16)>=eshoty.cnt) { f=1 eshotf.cnt=0 } loop if f=1 { dsplay 4 playerf=3 peplcnt=0 } } ; 自機とアイテムの当たり判定 if ((playerf=1)|(playerf=2))&(itemf=1)&(playerx<=(itemx+31))&((playerx+31)>=itemx) &(playery<=(itemy+31))&((playery+31)>=itemy) { dsplay 5 itemf=0 if ikind=0 { if noption<2 { noption=noption+1 } else { score=score+500 if score>hiscore { hiscore=score } if score>=oneup { dsplay 6 nplayer=nplayer+1 oneup=oneup+100000 } } } else { nbomb=nbomb+1 } } ; ボム爆発の描画 if bombcnt!-1 { if bombcnt\15=0 { dsplay 7 repeat 10 rnd bombx.cnt,xsize-64 rnd bomby.cnt,ysize-64 loop } repeat 10 gdx=bombx.cnt:gdy=bomby.cnt i=bombcnt\15 if i<5 { gdox=$140 } if (i>=5)&(i<10) { gdox=$180 } if i>=10 { gdox=$1C0 } gdoy=$C0 gdw=64:gdh=64 gosub *Graphic_Draw loop } ; 敵の爆発を描画 repeat 10 if enemyf.cnt=3 { k=enekind.cnt if eneclass.k=0 { if eplcnt.cnt=0 { dsplay 1 } gdx=enemyx.cnt:gdy=enemyy.cnt if eplcnt.cnt<5 { gdox=0 } if (eplcnt.cnt>=5)&(eplcnt.cnt<10) { gdox=$20 } if eplcnt.cnt>=10 { gdox=$40 } gdoy=$20 gdw=32:gdh=32 gosub *Graphic_Draw } if eneclass.k=1 { if eplcnt.cnt=0 { dsplay 2 } gdx=enemyx.cnt:gdy=enemyy.cnt if eplcnt.cnt<5 { gdox=$180:gdoy=$80 } if (eplcnt.cnt>=5)&(eplcnt.cnt<10) { gdox=$1C0:gdoy=$80 } if eplcnt.cnt>=10 { gdox=$100:gdoy=$C0 } gdw=64:gdh=64 gosub *Graphic_Draw } if (eneclass.k=2)&(eplcnt.cnt<150) { n=cnt if eplcnt.cnt\15=0 { dsplay 2 repeat 5 rnd r,96 explosionx.cnt=enemyx.n-32+r rnd r,96 explosiony.cnt=enemyy.n-32+r loop } i=eplcnt.n\15 repeat 5 gdx=explosionx.cnt:gdy=explosiony.cnt if i<5 { gdox=$180:gdoy=$80 } if (i>=5)&(i<10) { gdox=$1C0:gdoy=$80 } if i>=10 { gdox=$100:gdoy=$C0 } gdw=64:gdh=64 gosub *Graphic_Draw loop } } loop ; 敵のダメージ処理 *Enemy_Dmg ; enemyno : 敵の要素番号 enemyf.enemyno=2 dmgcnt.enemyno=0 enelife.enemyno=enelife.enemyno-1 if enelife.enemyno=0 { enemyf.enemyno=3 eplcnt.enemyno=0 kind=enekind.enemyno if eneclass.kind=0 { score=score+200 } if eneclass.kind=1 { score=score+10000 } if eneclass.kind=2 { score=score+30000 } if score>hiscore { hiscore=score } if score>=oneup { dsplay 6 nplayer=nplayer+1 oneup=oneup+100000 } } else { dsplay 3 } return
ひとくちメモ: |
・効果音のファイルって、どうやって用意するの? |
一番手っ取り早いのは、フリー素材を探して拝借することです。インターネット上に、「自由に、ただで使っていいですよ」として、作った音声ファイルを配布しているサイトがあります。 自分で作る場合、手軽にできるツールとしては例えばKanaWaveがあります。「ぴん」、「ぼーん」と擬音を仮名で入力するだけでそれらしい音ができてしまうという、世界一簡単な効果音作成ツールです。そのかわり、あまり凝った音は作れません。 一般的なツールは波形をああでもない、こうでもないといじくり回して、自分の求める音を作りますので、少々面倒くさいです。 サクラ(音楽作成用ツール)で作って、MIDIからWAVEに変換するというのも手軽な方法です。変換の仕方はdexさんのサイトで詳しく解説されています(トップページ→番外編→他形式からMP3への変換)。これだと、より凝った音が作れます。 ちなみに、中型敵、ボス爆発音、ワンアップ音、自機のショット音はサクラで、他はKanaWaveで作った音です。 |
・snd命令を使う時に必要な工夫 |
sndload命令で読み込み、snd命令で鳴らします。それぞれdsloadfname、dsplayに対応します。違いは、HSPの標準命令で、DirectXとは関係ないという点です。1度に1つの音しか鳴らせません。「それでも俺は(私は)snd命令の方がいいのだ!」という人もいるかもしれません。 snd命令を使う場合は、音に優先順位をつけるといいです。今、3つの音があるとします。 (a)中型敵の爆発音 (b)ザコ敵の爆発音 (c)自機のショット音 自機のショット音が鳴っている時に敵の爆発音が鳴らないのは違和感がありますが、爆発音が鳴っている時にショット音が鳴らないのはそれほど気になりません。つまり、(a)か(b)が鳴っている最中は、自機が弾を撃っても(c)を鳴らさなければいいのです。同様に、(b)や(c)が鳴ったために(a)が途切れてしまうととても違和感があります。これも、(a)が鳴っている間は(b)も(c)も鳴らさないようにすればいいのです。まとめますと、
f=0 repeat 10 k=enekind.cnt if (eneclass.k=1)&(enemyf.cnt=3) { f=1 } loop if f=0 { snd 1 } ただし、中型敵が爆発している時間は適当に決めたのであって、爆発音の長さに合わせたわけではありません。これでもだいぶマシになりますが、より正確にしたい場合は、「現在中型敵の爆発音が鳴っているかどうか」を判別する必要がありますが、残念ながらそういう命令はありません。 そこで、音の再生時間を調べておいて、その時間を過ぎれば音が鳴り終わったと判断することにします。時間は、Windows Media Playerなりなんなりで調べて下さい。中型敵の爆発音(explodem.wav)の再生時間は約2秒です。 中型敵の爆発音を鳴らしたと同時に変数eplmsndcnt(explodem sound countの略)に0を入れます。これは、メインループを1回処理するごとに1増えるものとします。"await 16"で、メインループ1回の処理時間を16msとしていますから、eplmsndcntが2000/16=125以上であれば、鳴り終わっているはずです。 if eplmsndcnt>=125 { snd 1 } 「優先順位ってよく分からないし、面倒くさそう」という人のために、もっと簡単な方法があります。「重なって鳴りそうな音は一切使わない」という方法です。例えば、自機のショット音は鳴らさないのです。実際、多くのフリーソフトのシューティングはショット音を省略しています。 中型敵の爆発音は使わず、ザコ敵も中型敵も爆発音は同じとします。でもそれでは中型敵の爆発がしょぼいですから、ザコ敵は1回だけ、中型敵は複数回爆発させると良いでしょう。 なお、snd命令では、WAVEは複数の音を重ねて鳴らせないのであって、MIDIとWAVEはいっしょに鳴らせます。つまりBGMを流している状態で効果音を鳴らすことはできます。 |