簡易シューティングを作ってみようと思い、現在縦スクロールにて敵が上から下に移動しながら落ちてくるところまでを作成しました。
一応60FPSまでに抑えてあるのですが、画面になんらかの動作(マウス移動やキー押下)を起こし、GetMessageが送られるところで異常に処理落ちしまいます。
まだキーやマウスの判定は入れておらず、ESCで終了とWM_DESTROYくらいです。
一応抜粋:
LRESULT CALLBACK CGAME::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
break;
case WM_DESTROY:
ShowCursor(TRUE);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
また、GetMessageに行く前にはPeekMessageで判定するようにしています。
さらに抜粋:
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)){
if (GetMessage(&Msg, NULL, 0, 0)){
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
デバッグとしてGetMessageだけを仮にコメントとしてみたところ問題なくスムーズに動きます。
また、ウィンドウプロシージャ内を全てコメント化もしてみました。(本当はダメですが)
それでもやはり処理落ちしてしまいます。
GetMessageの後の処理がまったくない状態でも処理落ちしてしまうところからGetMessage自体に処理がかかっている気がします。
意味不明です(´・ω・`)
キーを押しっぱなしですとたしかにWM_KEYDOWNやWM_CHAR等のメッセージが
常に送られてくるとは思うのですが処理落ちするくらいの重さなのでしょうか?
環境はXP,VC6になります。
ぱっと見、PeekMessage の引数が REMOVE なのはダメっぽい。
これだとメッセージが来ていたとしても、そのメッセージが削除対象に
なるわけで。そうすると、そのメッセージが処理されないまま
(Translate〜やDispatch を経る前に) GetMessage で次の
メッセージを待ってませんか?
# KEYDOWN は連続するとリピート回数でまとめられるはず。
# 余談
> if (GetMessage(&Msg, NULL, 0, 0)){
上の書き方では、GetMessage でエラーが発生しても(-1が返っても)抜けられません。
<MSDN>
WM_QUIT 以外のメッセージを取得した場合、0 以外の値が返ります。
WM_QUIT メッセージを取得した場合、0 が返ります。
エラーが発生した場合、-1 が返ります。
</MSDN>
Banさん回答ありがとうございます。
ご指摘の通りPeekMessageをPM_NOREMOVEに変更したところ問題なく稼動しました。
的確な回答ありがとうございます。
助かりました。
さらに上記の文から質問してよろしいでしょうか?(ほんとはダメかもですが)
PeekMessageでメッセージを受け取りキューから削除できるということは
GetMessageの意味はあるのでしょうか?
# Peek〜するときは、NOREMOVE がお約束なので。
> さらに上記の文から質問してよろしいでしょうか?(ほんとはダメかもですが)
私のわかる範囲ならどうぞ....(分らない場合でも他の識者に期待してどうぞ
> PeekMessageでメッセージを受け取りキューから削除できるということは
> GetMessageの意味はあるのでしょうか?
GetMessage は、メッセージが来るまでブロッキングします。
つまり、その間CPU時間を消費しません。
PeekMessage はポーリングなので、ウェイとなしでループをまわすと、
CPU100% になったり、他のプロセスに制御が回りにくくなったりします。
なので、適材適所で使い分けるために二個あるのでしょう。
またまたありがとうございます。
やっと理解しました^^;
うまく使いわけていきたいと思います。
解決とさせて頂きます。
# まぁWaitMessage ってのも別途あるので、コレと Peek を組み合わせれば
# 上の問題もほぼ解決ですが。GetMessage は多分、メッセージループ用の
# 省略形なんじゃないかと思います。(WM_QUIT の扱いとか....)
さらに詳しい詳細ありがとうございます。
関数の用途をよく調べてみようと思います。
助かりました<(_ _)>
ツイート | ![]() |