プログラムの構造についての疑問です。
私は現在、プログラムの実行を、MainLoopと言う関数内で、TitleやGameStartと言ったゲームの中核となる関数へ(switch文でどれを実行すべきかを区別して)渡しています。
MainLoop関数は、WinMain関数内( while(ProcessMessage() == 0 && GetHitKeyStateAll(Key) == 0) のwhile文中)でのみ呼んでおり、一番上位の層で動作するものです。
void MainLoop(){
// SceneNumberの値を変えることでシーンの操作を行う
switch ( SceneNumber ){
case 0:
Title();
break;
case 1:
GameStart();
…………
と言う具合です。
ここで、TitleやGameStartと言った関数内でも、
while(ProcessMessage() == 0 && GetHitKeyStateAll(Key) == 0)
のループを用いています。
例えば、タイトル画面からメインゲーム画面へ移行したい場合、Title関数内のループを抜け、更にSceneNumber(MainLoop内で、どの関数を呼び出すかを決める変数)の値をメインゲームに対応する値に変えることで、移行を実現しています。
こういった、ループを多くの箇所で用いるやり方はまずいでしょうか?
また、どういうメリットがあり、デメリットがあるのかもお教え頂きたいと思ってます。
よろしくお願いします。
メインループ を入れ子構造に
Re:メインループ を入れ子構造に
プログラムの書き方は人によって千差万別で、プロとして他の人とやっていかない限りは、自分がわかりやすい我流でいいと思いますが、
基本的に、必ず行う
ProcessMessage() == 0
や
GetHitKeyStateAll(Key)
や、消す関数、裏画面反映関数などは「毎回必ず通る場所」に一箇所だけかくべきでしょう。
デメリットは、プログラムが長くなってくると痛感します。
いろんなところに、似たような処理がかいてあると、バグが出た時、どこがおかしいのかわからなくなったり、
します。
大きなゲームを作ろうと思ってくるとしっかりと役割分担をしないと把握が困難になってきます。
「登録部」「計算部」「描画部」が勝手にゲームの三大役割だと思っていますが、
きち~んと、この3つにモジュールをわけてやることが、大きなゲームを作る秘訣だと思っています。
一つの関数に登録も計算も描画も行うようなことがかいてあると
どこか描画がおかしかった時、どこがおかしいか検討すらつかなくなってしまいます。
後、私の場合だと、単純に似たような処理がいくつもあると気持ち悪いですし、似たようなコードはまとめないと無駄に長くなってしまいます。
例えば極端な例ですが、
printf("1");
printf("2");
printf("3");
printf("4");
printf("5");
printf("6");
のようなプログラムがあったら纏めたいと思うでしょう。
MainLoop関数は、1秒間に60回位、処理は毎回通るのでしょうか?
また、MainLoopと言うからには、ここでループさせてるのかと思いましたが、本当にループしているのはメイン関数で、MainLoopにはループ処理は無いのでしょうか?
もし毎回メイン関数を通るのならゲームプログラミングの館のサンプルのようメインにだけ
毎回呼ぶ関数を書けばいいのではないでしょうか。
基本的に、必ず行う
ProcessMessage() == 0
や
GetHitKeyStateAll(Key)
や、消す関数、裏画面反映関数などは「毎回必ず通る場所」に一箇所だけかくべきでしょう。
デメリットは、プログラムが長くなってくると痛感します。
いろんなところに、似たような処理がかいてあると、バグが出た時、どこがおかしいのかわからなくなったり、
します。
大きなゲームを作ろうと思ってくるとしっかりと役割分担をしないと把握が困難になってきます。
「登録部」「計算部」「描画部」が勝手にゲームの三大役割だと思っていますが、
きち~んと、この3つにモジュールをわけてやることが、大きなゲームを作る秘訣だと思っています。
一つの関数に登録も計算も描画も行うようなことがかいてあると
どこか描画がおかしかった時、どこがおかしいか検討すらつかなくなってしまいます。
後、私の場合だと、単純に似たような処理がいくつもあると気持ち悪いですし、似たようなコードはまとめないと無駄に長くなってしまいます。
例えば極端な例ですが、
printf("1");
printf("2");
printf("3");
printf("4");
printf("5");
printf("6");
のようなプログラムがあったら纏めたいと思うでしょう。
MainLoop関数は、1秒間に60回位、処理は毎回通るのでしょうか?
また、MainLoopと言うからには、ここでループさせてるのかと思いましたが、本当にループしているのはメイン関数で、MainLoopにはループ処理は無いのでしょうか?
もし毎回メイン関数を通るのならゲームプログラミングの館のサンプルのようメインにだけ
毎回呼ぶ関数を書けばいいのではないでしょうか。
Re:メインループ を入れ子構造に
なるほど、まとめることが大事ですね。
まとめる様にします。
ありがとうございます。
>MainLoop関数は、1秒間に60回位、処理は毎回通るのでしょうか?
いえ、通りません。
例えば、TitleからGameStartへ移動する(タイトル画面で、ゲームスタートにカーソルを合わせて決定ボタンを押す)とき等に、一度通るような仕組みです。
>また、MainLoopと言うからには、ここでループさせてるのかと思いましたが、本当にループしているのはメイン関数で、MainLoopにはループ処理は無いのでしょうか?
WinMain中のwhile文の中にMainLoop関数を入れてる形でして、MainLoop関数の中身は、switchが1つあるだけ、という形です。
まとめる様にします。
ありがとうございます。
>MainLoop関数は、1秒間に60回位、処理は毎回通るのでしょうか?
いえ、通りません。
例えば、TitleからGameStartへ移動する(タイトル画面で、ゲームスタートにカーソルを合わせて決定ボタンを押す)とき等に、一度通るような仕組みです。
>また、MainLoopと言うからには、ここでループさせてるのかと思いましたが、本当にループしているのはメイン関数で、MainLoopにはループ処理は無いのでしょうか?
WinMain中のwhile文の中にMainLoop関数を入れてる形でして、MainLoop関数の中身は、switchが1つあるだけ、という形です。
Re:メインループ を入れ子構造に
それだとあちこちに同じような処理があることが予想され、いつも通る場所がかわるような仕様になっていると思いますので、複数人での開発やバグチェックにふさわしくいと思われます。
私の勝手な書き方であり、正当性の高いものかどうかはわかりませんが、
一応私が書いているメイン関数の方法はこちらで紹介しているので、よければご覧下さい。
このように、メイン関数は毎回絶対戻ってきて、基本的な処理はメイン関数でするような仕様はどうでしょうか。
大規模なプログラムになるなら、メイン関数からどこかの関数を呼んでもいいと思いますが、一応毎回戻ってくるほうがいいと思います。
http://dixq.net/g/#34
私の勝手な書き方であり、正当性の高いものかどうかはわかりませんが、
一応私が書いているメイン関数の方法はこちらで紹介しているので、よければご覧下さい。
このように、メイン関数は毎回絶対戻ってきて、基本的な処理はメイン関数でするような仕様はどうでしょうか。
大規模なプログラムになるなら、メイン関数からどこかの関数を呼んでもいいと思いますが、一応毎回戻ってくるほうがいいと思います。
http://dixq.net/g/#34
Re:メインループ を入れ子構造に
そういう風に改造しました。
アドバイスありがとうございます。
>基本的な処理
ProcessMessageやGetHitKeyStateAllと言った関数のことでしょうか。
アドバイスありがとうございます。
>基本的な処理
ProcessMessageやGetHitKeyStateAllと言った関数のことでしょうか。
Re:メインループ を入れ子構造に
はい、毎回使うそれらの関数は別に書くと面倒なので、私は、ですけど、メインループのループ条件の中にいれてしまっています。
ソースを短く書くとすっきりするので、別に可読性が必要で無い所はトコトン短くしています。
http://dixq.net/g/#36
なんならSetDrawScreenもScreenFlip()も詰め込んで、無理やりこんなに短くもできるかもしれません。
(横に長いプログラムは嫌う人が多いですが、まぁここはお決まりのコードと言うことで)
実際数行しか書いて無いですが、
ウィンドウ変更();
DxLib初期化();
裏画面設定();
裏画面反映();
プロセスメッセージ処理();
裏画面削除();
キー入力状態保存();
Escapeキーが押されたら終了;
DxLib終了();
これらのいつも必ず書く関数や処理をしてくれています。
ソースを短く書くとすっきりするので、別に可読性が必要で無い所はトコトン短くしています。
http://dixq.net/g/#36
なんならSetDrawScreenもScreenFlip()も詰め込んで、無理やりこんなに短くもできるかもしれません。
(横に長いプログラムは嫌う人が多いですが、まぁここはお決まりのコードと言うことで)
#include "DxLib.h" char Key[256]; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() || SetDrawScreen( DX_SCREEN_BACK )) return -1; while(!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){ //ここに処理を書く } DxLib_End(); return 0; }
実際数行しか書いて無いですが、
ウィンドウ変更();
DxLib初期化();
裏画面設定();
裏画面反映();
プロセスメッセージ処理();
裏画面削除();
キー入力状態保存();
Escapeキーが押されたら終了;
DxLib終了();
これらのいつも必ず書く関数や処理をしてくれています。