ページ 1 / 1
太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月01日(日) 23:01
by hss12
こんにちは。
サンプルプログラミングの館の太鼓の鉄人のプログラムを改造しているのですが、
今、赤青の2色から4色に増やすところまで成功したのですが、ini.cppの
humen.knd=c-'0';
のc-'0'はどういう意味なのでしょうか?
あと、これだと9色までしかできないので、
humenのtxtデータを、aなら10、bなら11、cなら12のようにすればいけるかと思ったのですが、
この変換をうまく書く方法はありますか?
ちなみに色ではなく文字を流そうと思っています。タイピングソフトのような感じです。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月01日(日) 23:06
by SCI
>humen.knd=c-'0';
>のc-'0'はどういう意味なのでしょうか?
「文字」から「数値」に変換しています。
文字である「'0'」と数値「0」が別の値である、というのはOKですか?
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月01日(日) 23:13
by hss12
分かります。
humen.kndはintですね。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月01日(日) 23:16
by SCI
この変換を別の(2桁以上でもできる)方法でやるには、例えばatoi()やstrtol()が簡単だと思います。
これなら、変換元が2桁以上でも関数1つで実現できます。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月01日(日) 23:54
by SooA
読み込んでいる txt の内容が分からないのですが
'0' というのは 16進数で 0x30 です、
'1' は 0x31
'2' は 0x32
'3' は 0x33
|
9 は 0x39
つまり '1'-0x30 とすれば数値としての 1 を得ることが出来ます。
アルファベットの場合だと
'A' ~ 'Z' 0x41 ~ 0x5A
'a' ~ 'z' 0x61 ~ 0x7A
となり、16進数で連続した数値になっています。
これを利用してテキストデータから数値へ変換すれば
良いかと思います。
'0'~'9'は そのまま '?'-0x30 で数値に
'A'~'Z'は '?'-0x41+10
'a'~'z'は '?'-0x61+36
これで 0~9、A~Z、a~z に対応する値を付けることが出来ます。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 00:08
by SCI
>これで 0~9、A~Z、a~z に対応する値を付けることが出来ます。
これでもほとんどの場合、その動作は保証されていますが、厳密に言うと「値の一貫性」が保証されていません。
どういうことかというと、A-Z、a-zの値が連続しているかどうかは保証されているわけではなく、実際に値が不連続となる文字コードも存在します。
「ほとんどの場合」ちゃんと動きますが、一応、念頭においておくといいかもしれません。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 00:37
by hss12
分かりました。16進数は苦手なので10進数にさせてもらいますが
例えば読み込んだcの値が'1'だとすると
cの文字コードが49となり'0'の文字コードが48ですので
c-'0'は49-48で1となるわけですね。
ということは'A'の文字コードが65ですので
'A'-55で10になりますね。
つまり、関数使わなくても
if(48<=c && c<=57)
humen.knd=c-48;
else if(65<=c && c<=90)
humen.knd==c-55;
で大丈夫でしょうか。
(小文字なら97から122ですね。)
txtは元データそのまま10000200030004000のような感じです。
A000I000U000E000のようにしたかったので。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 00:52
by SCI
>例えば読み込んだcの値が'1'だとすると
>cの文字コードが49となり'0'の文字コードが48ですので
>c-'0'は49-48で1となるわけですね。
その通りです。
>ということは'A'の文字コードが65ですので
>'A'-55で10になりますね。
多くの場合、これで大丈夫でしょう。
テキストとして保存しなければならないのなら、このくらいしか方法は思いつきませんね・・・
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 00:54
by SooA
比較の部分は見た目で分かりやすく書けますよ。
if( c >= '0' && c <= '9' )
humen.knd=c-48;
else if( c >= 'A' && c <= 'Z' )
humen.knd=c-55;
まず無いとは思いますが
SCIさんの仰るようなケースもあるので
その点だけ注意してください。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 02:44
by Dixq (管理人)
入力ファイルのデータは0か1しかないので、「c-'0'」のようなコードでも問題無いかと思いましたが、
アルファベットを含むような場合、他の回答者様が仰っているようなことを考慮する必要がありますね。
まぁサンプルの場合は
if( c == '0' )
.knd = 0;
else if( c == '1' )
.knd = 1;
みたいな処理でも大丈夫ですね。
ただ、仰るようにこれを拡張するなら、まず、適切な音譜データの格納の仕方を勉強してみた方がいいかもしれません。
私は適当に何も調べずに作りましたが、
ダンスマニアや、名前忘れましたがDTXmaniaでしたっけ?
あの手の自作出来る音楽ゲーのデータがどのようになっているか調べてみると良いかもしれません。
きっとこれだけ出回っているソフトですから、効率の良い方法で格納されていると思います。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 03:03
by hss12
なるほど、そのほうが見やすいですね。
追加で質問なのですが、これは作った管理人さんじゃないと分かりにくいかもしれないですが、
コンボを表示する機能がなかったので付けたのですが
連続で弾が来た場合、例えば4つしかないのに連打で5回押しても
combo 4と表示されてしまいます。無駄にキーを押しているのにノーミス判定になってしまうんです。
管理人さんのコメントに
/*
本当はここで、ヒットした弾IDと弾の座標を記憶しておき、
ヒットが近かった物を結果ヒットとする処理と、
もし同じ距離の2つヒットした弾があれば左側をヒットとする処理を追加する必要がある
*/
とあったのでこれが原因かなとも思うのですが、どんなものでしょうか。
私自身処理の流れがまだ分かっていないので、どう直せばよいかヒントもらえないでしょうか。
一応作りかえたbullet.cppを付けておきます。
add_combo()を追加して、ヒットした時はcombo++
外れた時はcombo=0としています。
あと変更しているところは
input_key[0]は下キー
input_key[1]は右キー
input_key[2]は左キー・・・のようになります。
donとkaで書いてあったので全部直すのに苦労しました。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 03:14
by hss12
音譜データの格納の仕方ですが、案外今の状態がけっこう編集しやすいです。
ただ、作るのに時間かかりますね。コメントで歌詞でも書ければ楽なんですが。
char.cppも付けてみます。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 03:25
by kazuoni
>無駄にキーを押しているのにノーミス判定になってしまうんです。
最近のDJMax等はこの辺の判定あいまいですね。
押されたデータを記憶させておいて、
次にくるものと、先ほどの格納したデータを比較し、
ある程度(自分でラインを引くのですが、)
離れていたらミスって自分はしてました。
これを利用すると、例えば今押された奴がb1,次に来るやつがb2だとすると、
もし、b1が通り過ぎてしまっても、
(押すタイミング)<(b2-b1)
ならば、b1が押されたことにできます。
そしたらあとは距離使ってperfect,good,soso,booなんてので分けれます。
追記
同期は自分も一概には言えませんが、最近の曲(リズム変化が激しい曲)
にはかなり苦労すると思います。
自分が経験しましたので・・・w
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 03:29
by Dixq (管理人)
graph.cppも変更してます?
コンボ表示は何処で行ってます?
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 03:59
by hss12
graph.cpp中で
//ヒットしたときの結果表示描画
void graph_kekka(){
int i,flag=0;
for(i=0;i<KEKKA_MAX;i++){
if(kekka.flag==1){
if(kekka.knd==0 || kekka.knd==1){
DrawRotaGraphF(kekka.x, kekka.y, kekka.range, 0.0, img_kekka[kekka.knd], TRUE); //結果表示
DrawRotaGraphF(kekka.x-20.0, kekka.y-16.0, kekka.range, 0.0, img_combo[0], TRUE); //コンボと表示
DrawFormatString(kekka[i].x+8.0, kekka[i].y-25.0,color[1],"%d",ch.combo); //コンボ数表示
}
}
}
}
のようにしています。臨時でDrawFormatStringですが、画像データで行く予定です。
GOODなどの文字と一緒に出て消えます。
ちなみにBOOの字は出してないです。コンボがリセット=BOOなので。
表示させても連打中はBOOとは出ないです。
ところでDrawFormatStringはintしかダメなんですね。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月02日(月) 15:19
by SooA
>ところでDrawFormatStringはintしかダメなんですね。
char dat1[/url] = {"ABCDE"};
double dat2 = 1.123456;
int dat3 = 12345;
DrawFormatString( 8, 24, 0xffffff, "文字列[%s]", dat1 ) ;
DrawFormatString( 8, 48, 0xffffff, "浮動小数点[%0.4f]", dat2 ) ;
DrawFormatString( 8, 72, 0xffffff, "整数[%d]", dat3 ) ;
DrawFormatString( 8, 96, 0xffffff, "dat3の16進数[%x]", dat3 ) ;
画像を使うようなので無用かもしれませんが、
% の後に続くフォーマットで型を指定します。
詳しくはprintf関数を調べてみてください。
意図するところが間違っていたらすみません。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月03日(火) 04:17
by hss12
すみません。言いたかったのは座標のことです。
この場合座標のkekka.xとkekka.yはdoubleのようですが、
DrawFormatStringの座標はintしか対応していないようで
そのままだとコンパイルのとき警告が出るんですね。
(int)kekka.xのように書けば良いのだろうとは思いますが
画像にする予定なのでそのまま書いています。
画像を表示しているDrawRotaGraphFはfloat座標のようですが、
graph.cppの最初でdoubleからfloatに変換しているのですかね。
最初何やってるのだろうと思いましたが勉強になります。
ところで
DrawRotaGraph (int座標)と
DrawRotaGraphF (float座標)
は表示したとき違いが出るのでしょうか?
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月03日(火) 04:56
by Dixq (管理人)
Fが後ろに付く関数は小数点座標が指定出来ます。
y=10x
のような大きな傾きのある直線をF無し関数で飛ばしてみて下さい。きっとカクカクして見えると思います。
■
■
■■
■
■
■■
■
■
■
こんな感じで飛んでいくと思います。しかし小数点座標が指定出来ると滑らかに飛んでいきます。
通常描画ではよくわからないですが、バイリニア法で描画するとよくわかります。
バイリニア法での描画は龍神録プログラミングの館59章で使っているのでよければご覧下さい。
Re:太鼓の鉄人のプログラムを改造中ですが
Posted: 2009年3月05日(木) 21:15
by hss12
ありがとうございます。
参考にする人がいるかわかりませんが、
DrawFormatString(kekka
.x+8.0, kekka.y-25.0,color[1],"%d",ch.combo); //コンボ数表示
の部分を画像表示にしてみました。
龍神録プログラミングの館の41章を参考にさせてもらいましたが
左のいらない0を表示したくなかったのと、左寄せしたかったのですこし苦労しました。
うまく書けたと思いましたが、他にも書き方があれば教えてください。
例えば、combo 0012 を combo 12と表示したかったわけです。
LoadDivGraph( "num.png" , 10 , 10 , 1 , 16 , 18 , img_num );//0~9の数字画像を分割してimg_num配列に保存
//-----------
int keta;
int combo;
combo=ch.combo;
for(keta=0; combo !=0; keta++) combo/=10;//コンボが何桁か調べる
combo=ch.combo;
for(int k=keta; k>0; k--){//コンボ数表示
DrawRotaGraphF(kekka.x+15.0*k, kekka.y-18.0, kekka.range,0.0,img_num[combo%10],TRUE);
combo/=10;
}