今学校っでアクションRPGを作成することになり、私は先頭システムのメインプログラマになりました。
そこで戦闘中のダッシュ判定で苦しんでいます。
DXライブラリを使いタイム関数を使い、キーを押してる時間を検出してダッシュかどうかを判定してます。
ここでの問題はPCの性能が低かったり、ゲーム中に急に処理が重たくなったりしたときに、ダッシュと歩行を
繰り返してしまうと言うことです。
アルゴリズムの考え方じたいを新しくする必要があるのは分かるのですが、新しいアルゴリズムが浮かんできません、何かヒントでもいいので指摘をお願いします。
パット関数はキーボードを入力したらそれに対して値を返す。
キーに何も入力しないとパット関数は0を返す。
アニメカウントは関数に入ってくる前に+1されてくる。
■変数key = パット関数
|▲上 = パット関数
||自キャラ座標上下 = 時キャラ座標 - 4
|+――――――
|▼
|▲下 = パット関数
||自キャラ座標上下 = 時キャラ座標 + 4
|+――――――
|▼
|
|▲右 = パット関数
||画像送り数 = ダッシュ判定関数(key)
||▲580 > 自キャラ座標左右
|||▲画像送り数 != 0
||||自キャラ左右座標=自キャラ左右座標+6
|||+――――――――――――――――――
||||自キャラ左右座標=自キャラ左右座標+3
|||▼
||+―――――――――――――――――――――――
|||▲画像送り値 != 0
||||背景ダッシュモード値 = 2;
|||+―――――――――――――――
|||▼
||▼
||柱座標左右=柱画像左右+(3+背景ダッシュモード値)
||背景座標左右=背景座標左右+(1+背景ダッシュモード)
||画像送り値=画像送り値+9
|▼
|
|▲左 = パット関数
||画像送り数 = ダッシュ判定関数(key)
||▲30 < 自キャラ座標左右
|||▲画像送り数 != 0
||||自キャラ左右座標=自キャラ左右座標-6
|||+――――――――――――――――――
||||自キャラ左右座標=自キャラ左右座標-3
|||▼
||+―――――――――――――――――――――――
|||▲画像送り値 != 0
||||背景ダッシュモード値 = 2;
|||+―――――――――――――――
|||▼
||▼
||柱座標左右=柱画像左右+(3+背景ダッシュモード値)
||背景座標左右=背景座標左右+(1+背景ダッシュモード)
||画像送り値=画像送り値+9
|▼
|
|▲前回入力キー左右 == 4 && 画像送り値 == 0
||画像送り値 = 前回入力キー左右-1
|+―――――――――――――――――――――――――――
|▼
|画像切り替え時間 = アニメカウント / 6% 自キャラアニメーションに必要な画像枚数
|出力関数 = 自キャラ座標左右・自キャラ上下・自キャラ画像配列[自キャラアニメーションに必要な画|像枚数+画像送り値]
▼
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
DSTIMEを100と見る。
DSTIMEを190と見る。
移動モード=0は歩く 移動モード=1は走る。
移動関数から現在入力された値が来る(key)
■
|画像送り値 = 0;
|▲ループ時間>現在時間関数 && 移動モード=0 || 前回入力キー左右=key || 現在||時間関数>ダッシュ認識限界時間
||ループ時間 = 現在時間関数 + 100
||ダッシュ認識限界時間 = 現在時間関数 + 190
||移動モード = 0
||前回入力キー左右 = key
|+――――――――――――――――――――――
||ダッシュ認識限界時間 = 現在時間関数 + 100 (一度キーを話したら確実に歩くた|| めにループ時間を代入)
||移動モード = 1
||画像送り値 = 画像送り値 + 24
|▼
|
|状態を見るために、key・ループ時間・ダッシュ認識限界時間・移動モードを出力。
|移動関数に画像送り値を返す。
▼
void JicharaMove(){
//キャラムーブ
int b=0 , c=0;
int key = GetJoypadInputState(DX_INPUT_KEY_PAD1); //方向キー代入判定。
if(key & PAD_INPUT_UP) jikidata.y=jikidata.y-idouryou[4];
if(key & PAD_INPUT_DOWN) jikidata.y=jikidata.y+idouryou[4];
//ダッシュ判定
if(key & PAD_INPUT_RIGHT){ //右キーを押されたら。
b = Ds_Hantei(key); //ダッシュ判定関数
if(580>jikidata.x){ //キャラが右端にいなければ移動させる
if(b){
jikidata.x=jikidata.x+idouryou[6];
}
else{
jikidata.x=jikidata.x+idouryou[3];
}
}
else if(b)c=2; //キャラが右端にいない+ダッシュならc=2
hasira.x=hasira.x-idouryou[3+c],haikei.x=haikei.x-idouryou[1+c],b=b+9;
}
if(key & PAD_INPUT_LEFT){ //左キーを押されたら。
b = Ds_Hantei(key); //ダッシュ判定関数
if(30<jikidata.x){ //キャラが左端にいなければ移動させる。
if(b){
jikidata.x=jikidata.x-idouryou[6];
}
else{
jikidata.x=jikidata.x-idouryou[3];
}
}
else if(b)c=2; //キャラが右端にいない+ダッシュならc=2
hasira.x=hasira.x+idouryou[3+c],haikei.x=haikei.x+idouryou[1+c],b=b+6;
}
if(lr==4&&b==0)b=lr-1;//停止時の向き判別
int a = animcounter / 6 % jikidata.animpat; //キャラ画像切り替え時間
DrawGraph(jikidata.x, jikidata.y, jikidata.ghandle[a+b], TRUE);
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
int Ds_Hantei(int key){
int b = 0;
if((D_time_l>GetNowCount() && D_mod==0)|| lr!=key || GetNowCount()>D_time_h){
D_time_l= GetNowCount()+DSTIME_L; //ループ時間代入
D_time_h= GetNowCount()+DSTIME_H; //ダッシュ判定時間限界代入
D_mod = 0;
lr = key;
}
else{
D_time_h= GetNowCount()+DSTIME_L; //ループ時間代入
D_mod = 1;
b = b + 24;
}
printfDx("%d %d %d %d\n",key,D_time_l,D_time_h,D_mod); //明細出力
return(b);
}
C言語レベル多分7です。ダッシュについて。
Re:C言語レベル多分7です。ダッシュについて。
いくつか不明点もあるので、勘違いしているところがあるかもしれません、と断った上で。
実時間(ms)ベースで処理しているところと、毎フレーム毎固定値の処理が
混在しているのが、その原因なのは既に判っているかと思います。
であればどちらかに統一すればうまくいくのではないでしょうか。
例えば、GetNowCount()を使うのを止めて、毎フレーム1ずつ加算される
カウンターを使って判定すればいいのではないかと。
ただPCにスペックによっては何秒押せばダッシュになるのか
変わってしまいます(フレームレートが安定していれば別です)が、
ダッシュと歩行を繰り返すようなことはなくなるかと思います。
実時間(ms)ベースで処理しているところと、毎フレーム毎固定値の処理が
混在しているのが、その原因なのは既に判っているかと思います。
であればどちらかに統一すればうまくいくのではないでしょうか。
例えば、GetNowCount()を使うのを止めて、毎フレーム1ずつ加算される
カウンターを使って判定すればいいのではないかと。
ただPCにスペックによっては何秒押せばダッシュになるのか
変わってしまいます(フレームレートが安定していれば別です)が、
ダッシュと歩行を繰り返すようなことはなくなるかと思います。
Re:C言語レベル多分7です。ダッシュについて。
ご返答ありがとうございます。
GetNowCount()をやめて、フレーム数で判定をするソースを考えて見ます。
後説明不足で申し訳ありません。
結果として欲しい状態が、左右のどちらか一方方向に、Wクリックしたように、
「方向キーを押した後すばやく押しなおして最後に押しっぱなし」で、ダッシュとして判定してたいのです。
その後方向キーを押しなおしたら、歩行にとして判定したいのです。
ですので・・・
D_time_h= GetNowCount()+DSTIME_L;
[GetNowCount()>D_time_h]判定が出てくるのです。
分かり難い説明っで申し訳ありません。<!--2
GetNowCount()をやめて、フレーム数で判定をするソースを考えて見ます。
後説明不足で申し訳ありません。
結果として欲しい状態が、左右のどちらか一方方向に、Wクリックしたように、
「方向キーを押した後すばやく押しなおして最後に押しっぱなし」で、ダッシュとして判定してたいのです。
その後方向キーを押しなおしたら、歩行にとして判定したいのです。
ですので・・・
D_time_h= GetNowCount()+DSTIME_L;
[GetNowCount()>D_time_h]判定が出てくるのです。
分かり難い説明っで申し訳ありません。<!--2
ポインタを使った文字列の連結、コピー
すみません、またわからない問題にあたってしまいました><
私はC言語レベル4~5?くらいなんですが、この問題を教えてほしいのです。
#include <stdio.h>
int main(void){
char strA[/url]="Hello!!";
char strB[/url]="Good!";
char strC[/url]="1234567890123456789"
printf("%s\n",strC);
return(0);
};
はっきりいってポインタがよくわからないのです;;
表示では"Hello!!Good!"のようにしたいのです。
strA、strBの文字数の和はstrCの文字数のように少ないと定義しています。
strCにたくさんの数字が入っているのは仕様です。
普通にstrAとstrBを連結させるのは何とかできそうなのですが「ポインタを使った」
でひっかかってしまいます・・・orz
よくわからない*や&の記号を使ってtうくるのでしょうか@@?
char strCとprintfの間にプログラムを書きのですがわかる方おっしゃったらよろしくお願いします<(_ _)>
私はC言語レベル4~5?くらいなんですが、この問題を教えてほしいのです。
#include <stdio.h>
int main(void){
char strA[/url]="Hello!!";
char strB[/url]="Good!";
char strC[/url]="1234567890123456789"
printf("%s\n",strC);
return(0);
};
はっきりいってポインタがよくわからないのです;;
表示では"Hello!!Good!"のようにしたいのです。
strA、strBの文字数の和はstrCの文字数のように少ないと定義しています。
strCにたくさんの数字が入っているのは仕様です。
普通にstrAとstrBを連結させるのは何とかできそうなのですが「ポインタを使った」
でひっかかってしまいます・・・orz
よくわからない*や&の記号を使ってtうくるのでしょうか@@?
char strCとprintfの間にプログラムを書きのですがわかる方おっしゃったらよろしくお願いします<(_ _)>
Re:ポインタを使った文字列の連結、コピー
ひとつの回答としては……。
まず、「普通に連結」というのを作ってみてください。
多分、配列を使った操作ですよね。
そして、それができたら、
strA[なんとか] を、*(strA + なんとか)
strB[なんとか] を、*(strB + なんとか)
strC[なんとか] を、*(strC + なんとか)
に置き換えると、まずは、「ポインタを使った」ことになります。
多分、模範解答は、そこから、もうちょっといじる必要がありますが。
まず、「普通に連結」というのを作ってみてください。
多分、配列を使った操作ですよね。
そして、それができたら、
strA[なんとか] を、*(strA + なんとか)
strB[なんとか] を、*(strB + なんとか)
strC[なんとか] を、*(strC + なんとか)
に置き換えると、まずは、「ポインタを使った」ことになります。
多分、模範解答は、そこから、もうちょっといじる必要がありますが。
Re:ポインタを使った文字列の連結、コピー
strCに入れたいのですか?
ポインタをわざわざ使って連結する意味がないように思いますけど、練習と言うことでしたらそれでもいいかもしれません。
上記プログラムの意味がわからなければ、先に進めないでしょう。
上記プログラムの意味を説明できますか?
また、アドレスとポインタの違いは説明出来ますか?
ポインタをわざわざ使って連結する意味がないように思いますけど、練習と言うことでしたらそれでもいいかもしれません。
#include <stdio.h> void main(){ int a=2; int *p; p=&a; printf("%d",*p); }まず、ポインタを利用したいのでしたら、ポインタの基礎がわかっているかどうかが重要です。
上記プログラムの意味がわからなければ、先に進めないでしょう。
上記プログラムの意味を説明できますか?
また、アドレスとポインタの違いは説明出来ますか?
Re:ポインタを使った文字列の連結、コピー
↑のプログラムはわかると思います。
ポインタ変数pを宣言してその変数のなかにint型で宣言したaのアドレスを代入することになると
思うのでprintf関数で表示されるのはポインタ変数pの中に入っているアドレスの中身、つまり2が表示される
ようなことは少しあいまいかもしれませんが理解はできます。
まぁ説明しろといわれると厳しいかもしれません;
ん~難しいorz
できればソースを書いていただけるとありがたいのですが・・・
期限があるもので@@;わがままなことをいってすみません<(_ _)>
ポインタ変数pを宣言してその変数のなかにint型で宣言したaのアドレスを代入することになると
思うのでprintf関数で表示されるのはポインタ変数pの中に入っているアドレスの中身、つまり2が表示される
ようなことは少しあいまいかもしれませんが理解はできます。
まぁ説明しろといわれると厳しいかもしれません;
ん~難しいorz
できればソースを書いていただけるとありがたいのですが・・・
期限があるもので@@;わがままなことをいってすみません<(_ _)>
Re:ポインタを使った文字列の連結、コピー
答えは下に書いておきました。
他にも沢山方法はあるでしょうし、strCは動的に配列の大きさを確保した方がいいように思いますが、
今回はstrCは十分に大きいと言うことのようですので、そのままにしておきました。
ただ、ここで「答えを教えて」はダメだという規約にしてあります。
しかし「課題の期限が迫っていてどうしようもない・・」という状況はとても理解出来ます。
とにかくどうにかしたいですよね。
しかし、課題だけ解いて終わりにしてもらいたくないのです。
今回規約違反をして答えをお伝えしてしまった変わりに、宿題を出すのでやってみてください。
先ほどの私の質問で、質問者さんがポインタの基礎は理解していらっしゃるようでしたので、
ポインタが何かは省略します。
文字列はアドレスを利用して様々な方法が取れます。
*strAの示す部分を1文字表示したら何が表示されるか予測できますね?
それでは
課題
上記のような2つの文字列があります。
課題1
strCにおいて、6番目の配列要素をアドレス操作を意識して表示させてください。
課題2
strCにおいて、偶数番目にある配列要素をアドレス操作を意識して表示させてください。
課題3
strCの偶数の文字(0,2,4.....)をstrAにポインタを利用してコピーする関数を作ってください。
あふれないように気をつけて、あふれたものは切り捨てます。
他にも沢山方法はあるでしょうし、strCは動的に配列の大きさを確保した方がいいように思いますが、
今回はstrCは十分に大きいと言うことのようですので、そのままにしておきました。
ただ、ここで「答えを教えて」はダメだという規約にしてあります。
しかし「課題の期限が迫っていてどうしようもない・・」という状況はとても理解出来ます。
とにかくどうにかしたいですよね。
しかし、課題だけ解いて終わりにしてもらいたくないのです。
今回規約違反をして答えをお伝えしてしまった変わりに、宿題を出すのでやってみてください。
先ほどの私の質問で、質問者さんがポインタの基礎は理解していらっしゃるようでしたので、
ポインタが何かは省略します。
文字列はアドレスを利用して様々な方法が取れます。
#include <stdio.h> void main(void){ char strA[/url]="Hello!!"; putchar(*strA); }
*strAの示す部分を1文字表示したら何が表示されるか予測できますね?
それでは
課題
strA[/url]="Hey!!Hello!!"; strC[/url]="0123456789012345678901234567890";
上記のような2つの文字列があります。
課題1
strCにおいて、6番目の配列要素をアドレス操作を意識して表示させてください。
課題2
strCにおいて、偶数番目にある配列要素をアドレス操作を意識して表示させてください。
課題3
strCの偶数の文字(0,2,4.....)をstrAにポインタを利用してコピーする関数を作ってください。
あふれないように気をつけて、あふれたものは切り捨てます。
Re:ポインタを使った文字列の連結、コピー
#include <stdio.h> void strcopy(char *st1, const char *st2 , const char *st3){ while (*st2 != '\0') *st1++ = *st2++; while (*st3 != '\0') *st1++ = *st3++; *st1 = '\0'; } void main(void){ char strA[/url]="Hello!!"; char strB[/url]="Good!"; char strC[/url]="1234567890123456789012345"; strcopy(strC,strA,strB); printf("%s",strC); }