CreationCollege-TOP
Now Printing..
▲ C.College TOP▲ D-Tech Top.情報局2号館

∇ 脚注


∇ 感想はこちらに
クリエイターズボード(掲示板)

- Article: 待ち関数の必要性

Update: 2000/6/16


Sleep関数は便利だけど…

 ゲームに限らず、時々動作を一定時間止めたいな、と思うことがあります。画像の切り替えとか、メッセージスピードの調整など。Delphiで通常これを行う場合は、Sleepという関数(Win32API)を使います。BASIC時代のように、

> 10 FOR I=0 TO 20000:NEXT

 こう書く事は許されません。マルチスレッドOSにおいては、一つのプロセスが異常に負荷をかけると他との協調が取れず、動作を止めてしまうからです。先のAPIを使うと、現在のプロセスを指定ms(1000で約1秒。厳密に1000msではありません)だけ止めて、その間は他のプロセスにCPU処理を渡すことができます。

> Sleep(1000);

 非常に楽ですね。ところでこれは、windowsユニットで宣言されているメソッドで、困った事にDelphiのヘルプはVCLに偏り、ユニット毎の解説がかなり不足してるんですよね(汗)。

Sleep関数の害と解決方法

 では、待ち関数はSleepで万事オーケーかと思ったらそうはいきません。確かに待っている間はマシンリソースを他に渡してくれるのですが、代わりに自分自身のプロセスは完全に停止します。そもそもイベント中は他のメッセージを受け取れない仕組みであり(イベント終了後に待ち行列の形で受け取る)、下手なSleepは考えものです。メッセージを受け取れないということはどういうことか、つまりOnClickも[システム]-[終了]も、「x」を押してアプリを切る事も、果てはバーを動かす事もできなくなります。HSPのSleep関数はそんな事なかったのにとか嘆きながら困る人が結構いると思います。AVGを作っていて、メッセージを一度に表示したくないために一文字ごとに微妙にSleepを入れたために、その表示中はウィンドウを動かせないというのは結構プレイヤーに不快感を与えてしまう事でしょう。
 この解決策として三つ考えられます。一つはタイマーイベントで制御する手法で、待ち受けモードをベースとして、TTimerのイベントで処理を起こす方法です。一見良さそうに見えますが、イベントが一瞬で終わるACTやSTGではない場合、やはりイベントが終了するまでのラグでいろんな遅延が発生します。
 二つ目は、スレッドを一つ生成し(これを裏スレッドと呼びます)、メインは何もせずに、裏スレッドでいろんな処理を行うというものです。割と有効な手法ですが、スレッド生成は若干以上の危険が伴います。
 三つ目が一番楽で有効な方法ですが、Application.ProcessMessages メソッドを使う方法です。これは、「Windows がイベントに応答できるようアプリケーションの実行を一時的に停止」する命令で、これを用いて待ち関数を作るとたいがいは上手くいきます。Delphi-MLの[35020]にある、井上さんの書かれた待ち関数のコードが一番スリムに思えたので、引用させていただきます。

//---------------- >8  ここからチョッキン  8< ----------------
var
  fWaitBreak : boolean = False;        // 強制終了用フラグ

// 待ち関数  指定カウントが経過すれば True, 中断されたならば False
function WaitTime(const t: integer): Boolean;
var
    Timeout: TDateTime;
begin
    fWaitBreak := False;              // フラグの初期化
    Timeout := Now + t/24/3600/1000;  // 終了時刻

    while (Now < Timeout)and not fWaitBreak do begin
        Application.ProcessMessages;
        Sleep(10);                //精度が 10ms 以下で良い場合
    end;

    Result := not fWaitBreak;
end;
//---------------- >8  ここまでチョッキン  8< ----------------
 ここでは、ProcessMessageとSleepを効率よく組み合わせ、指定したms分だけウェイトをかけています。その際にいい加減に時間を設定せずに、しっかりTDataTime型を使い処理しています。このソースを見たときに、「おおっ頭いい」と唸ってしまいました。
 ゲームを作る人は結構ウェイト系を多用するので、非メインループ系の処理方法としてこのテクニックは押さえておきましょう。

- 鷹月ぐみな


.
Copyright- 鷹月ぐみな(gumina)たかつきCOMPANY 1997-2000.▲ C.College TOP