したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | |
レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。

おちゃめくらぶ掲示板

1451御茶目菜子:2013/01/14(月) 23:58:48
あきらめたらそこで試合終了だよ
先週から作っていた1画面ギタープログラム「PETITGUITAR」がついにできたにょ。
http://ww5.tiki.ne.jp/~ochame/petitcom/2page.htm#guitar
http://www.youtube.com/watch?v=Ura6mHkGkPQ

プチコンでギタープログラムというと私が知っている限りではSHIROさんのプチギターと
彬兄さんのギターの弾き語りができるツールがあるにょ。
彬兄さんのは初代プチコンで作られていてBEEP命令によるコード演奏が可能ではある
もののボタンに割り当てられたコードを演奏するものとなっているにょ。
SHIROさんのはmkIIに対応しており、BGMPLAY命令を使っているもののコード演奏は
できず単音のみとなっているにょ。
そうなると、少なくとも私が知る限りでは画面上の弦を弾いてコード演奏ができる
ギタープログラムはプチコンではないことになるにょ。
ということで、今回「画面上の弦を弾いてギターを演奏するような雰囲気を感じられる
もの」を作ろうと思ったにょ。
きっかけは、先日作った1行プログラムの「SOUND PAD」なんだけどね。
これを作る際に左手で[A][B][X][Y]ボタン操作をするという手法を思いついたけどこれで
ギターを作ればそれっぽいものが出来そうと感じたからにょ。

さて、思いついたのはいいけど問題となるのは操作体系にょ。
右手は演奏に集中したかったので左手のみでコードが自由に変えられるようにしなくては
ならないからね。
コードを選んでそれをボタンに割り当てるという方法で8通り([A][B][X][Y]の単独押し
および、[R]ボタンとの併用)ならば簡単にできるのだけどあくまで「1画面」というのが
目指すものなのでそれではサイズ的に厳しいにょ。
というわけで、考えたのがコードを登録せずに理論上12音階×16種別=192通りが選択可能
となるPETIT GUITARに採用されている方式にょ。

UIは決まったので制作に入ったのだけど最初にやったのはコードではなくすべて開放弦で
演奏ができるプログラムにょ。
これによって画面の弦の位置や快適な反応が得られるかが分かるにょ。
ここで陥りがちなのが当たり判定を鍵盤楽器と同じようにすることにょ。
つまり、弦そのものに当たり判定を用意するということにょ。
鍵盤のように面積が大きいものならば単純に鍵盤に対する当たり判定でもいいけど弦は幅が
ほとんどない(細いものは1ドット)ということで当たり判定が非常にシビアになって
しまうにょ。
弦と弦の間隔を30ドットと仮定して0.1秒でコードを弾いた際には1フレームの移動量は3ドット
となるため3ドット幅未満の弦だと反応されない恐れがあるにょ。
これがゲーム内の移動量ならば上限が分かるけど人がどれくらいの速度で弾くかなんて
分からないため常識的に考えられる限界までの速度に対応したいにょ。
別に当たり判定は見た目と同じにする必要はないため隣の弦ギリギリまで当たり判定を
大きくしたら反応は良くなるものの「コレジャナイ」感が強くなったにょ。

というわけで、すぐに改善したのが画面を7つのエリアに分割してタッチした状態で隣の
エリアに入ったら反応するというものにょ。
私がどれだけ速く操作しても1フレームで20数ドットだったので30ドット幅にすればこの
方法によってどれだけ速く弾いても取りこぼしは100%無くなるにょ。

次に問題となるのがBGMPLAY命令の仕様にょ。
BEEPを使用すれば何も考えなくても勝手に和音演奏が可能だけどBGMPLAY命令の場合は
ユーザーがチャンネル指定をしないと和音演奏にはならないにょ。
BGMPLAY命令はあらかじめ用意されたMMLを演奏するならば簡単に和音(コード)を鳴らす
ことができるけどリアルタイム演奏をするならばチャンネル指定をあらかじめ行うという
ことが足かせになってくるにょ。
何せBGMPLAY "0:C":BGMPLAY "1:E":BGMPLAY "2:G"としてもドミソの和音は鳴らずドの音と
ミの音とソの音が交互に鳴るだけだからね。
これは、BGMPLAYでMMLを直接指定した場合には記述していないチャンネルは自動的に無音と
見なされるからにょ。
そこで、考えたのがBGMSET命令で半音単位で必要な音を1音ずつ定義していくというものにょ。
あらかじめ定義されたMMLならばチャンネル単位で独立して鳴らすことが可能だからね。

これで、何とか形になったので次はコードを入れることになったにょ。
当面は動作確認のため最も単純な押すフレット番号をDATA文で入力していくことにしたにょ。
Amならば002210(「0」は開放弦を示す)となり、1つのコードが6桁の数字になり、これを
12音階分入力すれば1種類のコードに対応できるにょ。
データ量の問題があるためメジャー、マイナー、セブン、マイナーセブンに絞ったにょ。
これより少ないと実用にならないというギリギリのラインに感じるけど1画面に収めるという
ことが最終目標なのでこれでも限界にょ。

さて、とりあえず操作性や動作確認をして一応はプログラムとしては完成となったわけだけど
これからが本番にょ。
現在はシステム部分だけでほぼ1画面となる24行分となっており、それにコードデータが別途
16行もある(1種別4行×4種別)わけだからね。
そこで出てくるのがデータ圧縮にょ。
もちろん、圧縮効率の高さと展開ルーチンの小ささを考慮して合算で最も小さくなるような
ものを選択する必要があるにょ。
ルート音が分かってるのだからそこから自動生成するという方法もあるけど自動生成も
そんなに短くできないからね。
人間の指の配置を考慮しないと人間の手には弾けないようなコードデータが生成されてしまう
恐れがあるにょ。
そういう例外処理を行う必要性を考えるならばデータ圧縮をした方が遙かに簡単で短く済む
と考えたにょ。

ギターコード表を見る限りフレット番号は0〜8が使われているにょ。
単純に考えると1つの弦あたり4ビットなので6本の弦では3バイトになるにょ。
とはいえ、8が使われているのは一部だけなのでそれを例外として処理すれば3ビットで表すと
18ビットで済むにょ。
256進数表記する場合には8ビット単位で扱うことになるので8ビット単位でないと展開
ルーチンが複雑化してしまいデータは小さくなってもトータルでは小さくならないという
可能性があるためさらに別の方法を考えたにょ。
それは押さえるフレット番号は(人間の指の可動範囲を考えると当たり前だけど)どのコード
であっても3つ以下しかないにょ。
つまり、差分を取れば1つの弦を2ビットで表現できるにょ。
12ビットで表現できるため8ビット単位で扱うとすれば16ビットで残り4ビット余るにょ。
その4ビットをフレット番号の最大と最小の差分の数に充てたにょ。
あとは、CHR$(0)、CHR$(13)、CHR$(34)などが圧縮データとして生成されないようにコードを
ずらせば圧縮の完成にょ。
これによって16行あったデータはわずか4行になったにょ。(3分の1のはずなのに4分の1に
なっているのは区切りコードも無くしたため)

その圧縮ルーチンはこんな感じにょ。

INPUT D$
A=9
FOR I=0TO 5
 P=VAL(MID$(D$,I,1))
 A=A+!!P*(P<A)*(P-A)
P(I)=P
NEXT
A=A-1
FOR I=0TO 5
 P(I)=P(I)-A*!!P(I)
NEXT
E$=CHR$(A+P(0)*16+P(1)*64+1)+CHR$(P(2)+P(3)*4+P(4)*16+P(5)*64+1)

さて、これで1画面に収まるかというと全然そんなこともないにょ。
まだデータ展開ルーチンはリスト短縮が不十分であるものの約4〜5行分あり、それにデータを
合わせると8〜9行分になるにょ。
すでにシステム部分で24行使っているためそこから8〜9行分短縮する必要があるにょ。
最初から無駄だらけのプログラムならばそれも可能だけどすでにある程度はリスト短縮が
されているためここから大きな短縮は難しいにょ。
というわけで、一昨日も書いたようにほぼ1画面化はあきらめていたにょ。

とはいえ、やってみたら案外できるかも・・・ということでまずは上画面の表示をばっさりと
切り捨てたにょ。
これによって3行開いたので残りは約5行にょ。
あとは地道なリスト短縮で何とか残り1行までたどり着いたにょ。
そして、使用チャンネルを0〜5ではなく1〜6にすることでIF文を1つ減らしなんとか1画面に
収まる目処が付いたけどその代わりS=S+1というのをどこかに入れる必要が出てきたにょ。
すでにリスト短縮によって0〜2文字分しか開いてなかったため連続で5文字開いた行を捻出する
なんて不可能な状態にょ。(実際に入れる場所は音を鳴らす直前にしないといけないので
S=S+1を入れるために元々その行にあった何かを別の行に移動する必要がある)
そこで目を付けたのがD=C*2-(C>2)-(C>5)+E-2という論理式にょ。
これはD=0OR(C*5-4)/3+Eという変形が可能になるため何とかS=S+1を入れることができたにょ。
あと開いた場所におまけ程度に上画面表示を追加して完成したにょ。(数字で表示するだけ
ならば2文字の空きがあれば入る)

こうやって、ほとんど無理と思われたプログラムの1画面化が多少の妥協があるものの
完成したにょ。
あきらめずに1画面化にチャレンジして本当に良かったにょ。
しかし、音に関しては全く妥協はせず当初のものを完全に入れることができたにょ。
もしも、改造点にあるようなシンプルな表示であってもメインとなる音の部分をかなり
削らないと実現できなかったからね。
今回書いたことは今月末〜来月くらいに第9回のプチコン講座で具体例を交えて書くので
お楽しみに!(といっても、鍵盤楽器よりもさらに需要が少なそうだけど)




掲示板管理者へ連絡 無料レンタル掲示板