FPSの処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
たこやき

FPSの処理について

#1

投稿記事 by たこやき » 15年前

FPSのプログラムを作ったのですがこのソースを実行して少しするとSleep(team)のところで止まってしまいます。
なぜ止まってしまうのでしょうか?
ソース載せます。
static DWORD befoer_time,befoer,Count0t;
DWORD now_time,t;
static int count=0;
DWORD team=0;
TCHAR buff[100],buff2[10];
float f[FPS];
static DWORD surprus_Time=0;

now_time=timeGetTime();
if(!befoer_time)
befoer_time=timeGetTime();
if(!befoer)
befoer=timeGetTime();
surprus_Time+=1000/FPS-(now_time-befoer_time);
if(surprus_Time<=0)
team=0;
else
{
if(team!=surprus_Time)
team=surprus_Time;
surprus_Time=0;
count++;
}
if(team>0)
Sleep(team);
befoer_time=timeGetTime();
t=timeGetTime()-befoer;
if(t>=1000)
{
FpsDraw=count*1000/t;
count=0;
befoer=timeGetTime();
}
環境はVC++2005です。

Mist

Re:FPSの処理について

#2

投稿記事 by Mist » 15年前

> 止まってしまいます。

「止まる」とは、プログラムが終了してしまうという意味ですか?
それとも、Sleepから抜けなくなるという意味ですか?
後者だとすると計算ミスでteamが大きくなりすぎているのかなと予想しますが。
FPSはどう定義されているんですか?

たこやき

Re:FPSの処理について

#3

投稿記事 by たこやき » 15年前

回答有難うございます。Sleepから抜けなくなるという意味です。
FPSは60と定義しています。確かに実行途中count++;のところ
でブレークポイントを付けて止めて見るとsurprus_Timeで理由
がわからない数字が出ます。どこら辺で計算ミスされているので
しょうか?

Mist

Re:FPSの処理について

#4

投稿記事 by Mist » 15年前

コメントが全く無いのであなたの考え(設計)が非常に理解しづらいです。
全体的にコメント付けてもらえないでしょうか。
(字下げがぐちゃぐちゃで読みにくいってのもありますが)

原因とは違うかもしれませんが、ざっと見て気になったのは

surprus_Time+=1000/FPS-(now_time-befoer_time);

です。
足しこんでいる(+=)理由は何ですか?

予想ですが、(now_time-befoer_time)がFPS(=60)を超え続ける(この関数に戻ってくるまでに60msec以上経過している)場合、surprus_Timeはずっと値を引かれ続けることになりマイナスの最大値を超えたときに正のとんでもない値になります。
(now_time-befoer_time)はどれぐらいで推移していますか?

あと、この式にはもうひとつまずい点があり
(now_time-befoer_time)=60
となるとき、1000/0となりますので0割が発生します。
割り算を使用する場合は、割る数が0にならないことを事前にチェックしなければなりません。

たこやき

Re:FPSの処理について

#5

投稿記事 by たこやき » 15年前

static DWORD befoer_time,befoer;
DWORD now_time,t;
static int count=0;
DWORD team=0;
float f[FPS];
static DWORD surprus_Time=0;

now_time=timeGetTime();
if(!befoer_time)
befoer_time=timeGetTime();
//余剰時間の計算(マイナスの場合、ウェイトをかけなくてよい)
surprus_Time+=(1000/FPS)-(now_time-befoer_time);
//ウェイトの時間かどうか?
if(surprus_Time<=0)
team=0;
else {
 if(team!=surprus_Time)
   team=surprus_Time;
surprus_Time=0;
count++;
}
//ウェイト時間
if(team>0)
Sleep(team);
//前の時間の計算
befoer_time=timeGetTime();
if(!befoer)
befoer=timeGetTime();
//1秒間のうちどれぐらいたったか
t=timeGetTime()-befoer;
//1秒間たったかどうか?
if(t>=1000) {
FpsDraw=count*1000/t;
count=0;
befoer=timeGetTime();
}
> surprus_Time+=1000/FPS-(now_time-befoer_time);
>です。
>足しこんでいる(+=)理由は何ですか?
前の余分の時間(マイナス)を足しているためです。

>予想ですが、(now_time- befoer_time)がFPS(=60)を超え続ける(この関数に戻ってくるまでに60msec以上経過している)場合、surprus_Timeは
>ずっと値を引かれ続けることになりマイナスの最大値を超えたときに正のとんでもない値になります。
>(now_time-befoer_time)はどれぐらいで推移していますか?
特に推移はしていません。
ただ60msecを越える場合ってあるのでしょうか?

わかりにくいとは思いますがよろしくお願いします。

たこやき

Re:FPSの処理について

#6

投稿記事 by たこやき » 15年前

>あと、この式にはもうひとつまずい点があり
>(now_time-befoer_time)=60
>となるとき、1000/0となりますので0割が発生します。
>割り算を使用する場合は、割る数が0にならないことを事前にチェックしなければなりません。
1000/60-60場合先に1000が/60が先に計算されると思うので0割が発生しないと思うのですが?
どういうことなのでしょうか。まだまだ自分では初心者だと思うのでよろしくお願いします。

たこやき

Re:FPSの処理について

#7

投稿記事 by たこやき » 15年前

あとif(surprus_Time<=0)で0以下の時の処理しているので、マイナスになったとしてもここでteam=0になり
Sleep(team)は処理されないと思うのですが、どういうことなのでしょうか?

Mist

Re:FPSの処理について

#8

投稿記事 by Mist » 15年前

ごめんなさい。
0割の件は私の見間違いです。
あと、コメントの次の行が改行されてなかったり、字下げが変なのはここの掲示板のせいみたいですね。(私の環境だけ? FX 3.5.7)

1000/16だから17msec以上かかればマイナスになりますね。
デバッグ用のコードを追加してみました。(コンパイルしていないので間違ってたらごめんなさい)
これで値の遷移をチェックしてみてはどうでしょうか。

static DWORD befoer_time,befoer;
DWORD now_time,t;
static int count=0;
DWORD team=0;
float f[FPS];
static DWORD surprus_Time=0;

now_time=timeGetTime();
if(!befoer_time)
befoer_time=timeGetTime();

//余剰時間の計算(マイナスの場合、ウェイトをかけなくてよい)
surprus_Time+=(1000/FPS)-(now_time-befoer_time);

// <@@>現在の値をデバッグウィンドウに出力
char strtmp[128];
sprintf(strtmp, "now_time = %d, befoer_time = %d, surprus_Time = %d\n", now_time, befoer_time, surprus_Time);
OutputDebugString(strtmp);
// <@@>

//ウェイトの時間かどうか?
if(surprus_Time<=0)
team=0;
else {
if(team!=surprus_Time)
team=surprus_Time;
surprus_Time=0;
count++;
}
//ウェイト時間
if(team>0)
Sleep(team);
//前の時間の計算
befoer_time=timeGetTime();
if(!befoer)
befoer=timeGetTime();

//1秒間のうちどれぐらいたったか
t=timeGetTime()-befoer;

//1秒間たったかどうか?
if(t>=1000) {
FpsDraw=count*1000/t;
count=0;
befoer=timeGetTime();
}

たこやき

Re:FPSの処理について

#9

投稿記事 by たこやき » 15年前

上記のプログラムをやりましたが、13が当分続き-3になり止まるみたいです。
あとif(surprus_Time<=0)で0以下の時の処理しているので、マイナスになったとしてもここでteam=0になり
Sleep(team)は処理されないと思うのですが、どういうことなのでしょうか?

バグ

Re:FPSの処理について

#10

投稿記事 by バグ » 15年前

DWORD型は非負整数型だから、マイナス値にはならないでしょ?

それどころか、マイナスになるように計算すると、DWORD型の最大値に限り無く近い数値に変わるんやないかなぁ?
一番手っ取り早いのはDWORD型を、LONGLONG型とかに変えてみてはいかがかな?

たこやき

Re:FPSの処理について

#11

投稿記事 by たこやき » 15年前

回答ありがとうございます。longに変えてみたら処理してくれました。回答誠に有難うございました。

たこやき

Re:FPSの処理について

#12

投稿記事 by たこやき » 15年前

すみません。intでやると大丈夫なのですがなぜか、longとlong longでやると止まってしまします。
signedを付けてもダメでした。なぜなのでしょうか?

たこやき

Re:FPSの処理について

#13

投稿記事 by たこやき » 15年前

どの辺かというとteamの宣言のところをlong longとやると止まります。

たこやき

Re:FPSの処理について

#14

投稿記事 by たこやき » 15年前

何度もすいません。static DWORD surprus_Time=0;をstatic long long surprus_Time=0;にすると
という話です。あともう一つteamの宣言のところをlong longとunsigned longとやると止まります。
マイナスをする必要がないので、unsignedをしても大丈夫のような気がしますが・・・

バグ

Re:FPSの処理について

#15

投稿記事 by バグ » 15年前

いまいち質問の真意が伝わってこないのですが、teamという変数に動きがある場所にブレイクポイントを設定して中身の確認はしましたか?

たこやき

Re:FPSの処理について

#16

投稿記事 by たこやき » 15年前

回答ありがとうございます。
質問し直します。static DWORD surprus_Time=0; のところをstatic long longにして、DWORD team=0; のところの
DWORDをlong longか unsigned longにするのと、
DWORD team=0;のところをstatic long longにしてstatic DWORD surprus_Time=0; のところのDWORDをlong longにすると
Sleep(team)のところを抜けないで処理されて(止まっている状態)になるのですがどうして止まってしまうのでしょうか?
足りないのは補足しますのでよろしくお願いします。

たこやき

Re:FPSの処理について

#17

投稿記事 by たこやき » 15年前

>teamという変数に動きがある場所にブレイクポイントを設定して中身の確認はしましたか?
ブレークポイントというかOutputDebugString()でやったらlong long,unsigned long両方とも-13で止まってしまいます。

バグ

Re:FPSの処理について

#18

投稿記事 by バグ » 15年前

ですから、ブレイクポイントを設定してteamという変数の中身を確認して報告していただけますか?
ついでにunsignedでなければ駄目な理由もお願いします。

バグ

Re:FPSの処理について

#19

投稿記事 by バグ » 15年前

どうして、非負整数なのにマイナス値が表示されるのでしょうか?
そこを変だとは思いませんでしたか?

たこやき

Re:FPSの処理について

#20

投稿記事 by たこやき » 15年前

変だと思いました。それでなぜそうなったのかわからなくなったので質問させていただきました。

たこやき

Re:FPSの処理について

#21

投稿記事 by たこやき » 15年前

unsignedでなければ駄目な理由は特にないのですが・・・

y

Re:FPSの処理について

#22

投稿記事 by y » 15年前

Sleep関数の引数は、DWORD(= unsigned int)型です。
DWORD型以外の値を渡した場合は、DWORD型に勝手にキャストされます。
いくら計算結果を入れる変数が符号付きのsigned intでも、
結局unsigned int(= DWORD)にキャストされるので、意味が無いです。
マイナスにならないように計算させるか、
マイナスになったときは別の処理をさせるなどしたらいいと思います。


あと、sprintfの%dで表示させるとint型で扱われます。
unsigned intの場合は%uを使うべきです。

たこやき

Re:FPSの処理について

#23

投稿記事 by たこやき » 15年前

そういうことでしたか、盲点でした。誠に回答ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る