こんにちは。
最初にシューティング・ゲームを製作中です。
今まではゲームループをWinMainにPeekMessage関数で
メッセージがない時に呼ぶようにしてゲームループを
組んできました。
それで今回はゲームループをスレッドで書き直そうとしています。
今はスレッドを2つ考えています。
1つ目はゲームの進行(データ)を処理するスレッドA
2つ目はゲームの描画(60FPS)を処理するスレッドB
ここで質問。
スレッドAはデータに書き込むだけ、
スレッドBはデータから読み込むだけの場合でも排他制御が必要ですか?
1つの変数(データ)に複数のスレッドから読み書きする場合には
排他制御が必要なのはわかります。
今回の場合はどうなりますか?
教えて下さい。
[開発環境]
Windows XP Home SP2
VC++2003.NET(SDK)
[補足]
今回が初のマルチスレッド・プログラミングになります。
大よその仕組みは本、サイトから分かりましたが
まだ排他制御をすべきかどうかが不安です。
アドバイスなどをお願いします。
排他制御すべきだと思います。
経験から
物理計算やっているときに描画すると
絵が変にずれます。
あとFPSはできればPCの性能によって
可変することが好ましいです・・・
ついでに書くと、
単純な2Dのシューティング・ゲームなら
あえて描画とデータ処理をスレッドで分ける
メリットはないような気がします・・・
> 経験から
> 物理計算やっているときに描画すると
> 絵が変にずれます。
なるほどです。
> 単純な2Dのシューティング・ゲームなら
> あえて描画とデータ処理をスレッドで分ける
> メリットはないような気がします・・・
そうですか。
じゃあ。
1つのスレッドでゲームループを組めば良さそうですね。
この場合なら排他制御も必要なさそうです。
> あとFPSはできればPCの性能によって
> 可変することが好ましいです・・・
これはどう可変すればいいのでしょうか?
PCの性能を取得してどのように可変すればいいのですか?
そもそもPCの何の性能でしょうか?
そださん。
また見てくれたら何かお願いします。
他の方でもかまいません。
>PCの性能によって
色々方法はあると思うし私も専門家じゃないので
あくまで参考までに見てください。
基本的には PeekMessageを使ってメッセージが流れていない間
動かし続けます。(単発スレッドでもいいです)
データ処理の際、時間dt間での移動を求めるのに、
p = p + v * dt;
という処理を書くと思いますが、このdtをうまく決めてやります。
while(終了条件) { // ゲームのメインループ
nowtime = timeGetTime();
dt = nowtime - lasttime;
lastime = nowtime;
if( dt > 500 ) { // 安全のため
dt = 500;
}
描画関数();
データ処理関数(dt);
}
こうすることで描画関数とデータ処理関数を実行した時間に応じて
絵を移動させることができるため、
高性能なPCほど細かい時間刻みで、
低スペックなPCほど荒い時間刻みで動くゲームを作ることができます。
> 高性能なPCほど細かい時間刻みで、
> 低スペックなPCほど荒い時間刻みで動くゲームを作ることができます
これだと移動スピードが変化しませんか?
高スペックでは早く移動
低スペックでは遅い移動
今は次のようにしています。
while ( 終了条件 ){
dwGetTime = timeGetTime();
gameMain( dwGetTime );
// 描画周期
if ( (dwGetTime - dwCntTime) >= (1000 / 60) ){
gameDraw();
dwCount++;
dwCntTime = dwGetTime;
}
// FPS表示周期(テスト用に設置)
if ( (dwGetTime - dwFPSTime) >= 1000 ){
setFPS( dwCount );
dwCount = 0;
dwFPSTime = dwGetTime;
}
Sleep( 1 );
}
gameMain()関数で1フレームの処理を行いますが
自機移動は1000/60ミリ秒周期、
敵機移動は1000/60ミリ秒周期、
弾丸移動は1000/120ミリ秒周期
としています。
具体的に自機移動は
if ( (dwGetTime - dwSaveTime) >= (1000 / 60) ){
移動処理
弾の発射
当たり判定
dwSaveTime = dwGetTime;
}
としています。
敵機移動、弾丸移動も同じ感じです。
そのほか背景やアイテムも同じ考え。
> データ処理関数(dt);
この関数で移動スピードの調整とかは
どうなっているのですか?
話が物理エンジンの話にそれてるような気もしますが
この際いいでしょう。
>移動スピードが変化
1フレームあたりの変化量はPCによって変化します。
ただし、
実時間(プレーヤーが見るスピード)では速度はvで一定です。
なので、
>高スペックでは早く移動
>低スペックでは遅い移動
ということにはなりません。
>> データ処理関数(dt);
>この関数で移動スピードの調整とかは
>どうなっているのですか?
実時間でフレーム間の経過時間dtを元に
移動量を計算するため特に調整しなくても適宜な
スピードになります。
強いて言えばdtを使って移動スピードを調整しています。
例えば、
e_vx = -1.f; //敵機のx座標速度
e_vy = 0.f; //敵機のy座標速度
とあらかじめ定義して、敵機の座標をe_p=(e_x,e_y)としたとき、
処理関数(dt) {
e_x += e_vx * dt / 1000.f;
e_y += e_vy * dt / 1000.f;
}
とすれば、どんなPCでも毎秒左に1ピクセルずつ動く敵機が作れます。
> 処理関数(dt) {
> e_x += e_vx * dt / 1000.f;
> e_y += e_vy * dt / 1000.f;
> }
> とすれば、どんなPCでも毎秒左に1ピクセルずつ動く敵機が作れます。
この例えで前回の
> p = p + v * dt;
の意味が分かりました。
もう一度いろいろと考え直してみます。
スレッドに関しては1つだけにしてゲームループを組むようにします。
そださん。
最後までお付き合い。
ありがとうございました。
ツイート | ![]() |