まずはmain.hから。
const int MG_NUM = 8 ; //MAIN_GRAPHIC_NUMの略 enum eMG_INDEX{ MG_BACK, }; struct SGameMain{ int Graphic[MG_NUM]; // グラフィック bool PoseFlag; // ポーズかどうかのフラグ void Process(); // この中でループする void Init(); // 初期化 void FirstInit(); // コンストラクタ void Load(); // ロード void Draw(); // 描画系をここにまとめる bool Pose(); // ポーズ };
タイトルとほとんど一緒です。よってほとんど省きます。さて、異なる点としてbool型のPoseFlag変数がありますね。bool型とは、C++でサポートされている型で、真か偽かを扱う型です。つまり、0かそれ以外かを格納する変数です。もっと極端な言い方をすると、0(false)か1(true)かを記憶する変数です。これはゲームプログラミングにおいて価値のある型です。真か偽かしか扱えないため、あいまいさがないのです。この変数の場合、ポーズ状態ではない(false)かポーズ状態である(true)の2つを記憶します。
Process関数について
// メインゲームの処理 void SGameMain::Process(){ Draw(); if( Pose() == true ) return; if( Key[KEY_INPUT_Z] == 1 ) ChangeGameState( GS_CLEAR ); if( Key[KEY_INPUT_X] == 1 ) ChangeGameState( GS_OVER ); }
他の関数を呼び出す関数ですね。描画、ポーズ処理、キー入力で次の画面に進む処理を持っています。ゲームの内部の主要な処理はreturn文と次のif文の間に書き足します。
ポーズ処理はこのように実現しました。ポーズ関数が真を返す場合ならProcess関数を終了するというものです。そうすると、Pose関数以降に書かれたゲーム内部の主要な処理は一切行われないまま関数が終了します。そのため、プレイヤーが勝手に動いたり、敵が動いたり、時間が進んだりしないわけです。Draw関数はプレイヤーの座標や敵の座標の位置に画像を描画します。プレイヤーや敵が動かないわけですから、画像の描画位置が変わることもありません。もしDraw関数をPose関数より後に書くと、Draw関数が実行されないままProcess関数が終了してしまうことになるので注意しましょう。
ポーズ処理はこのように実現しました。ポーズ関数が真を返す場合ならProcess関数を終了するというものです。そうすると、Pose関数以降に書かれたゲーム内部の主要な処理は一切行われないまま関数が終了します。そのため、プレイヤーが勝手に動いたり、敵が動いたり、時間が進んだりしないわけです。Draw関数はプレイヤーの座標や敵の座標の位置に画像を描画します。プレイヤーや敵が動かないわけですから、画像の描画位置が変わることもありません。もしDraw関数をPose関数より後に書くと、Draw関数が実行されないままProcess関数が終了してしまうことになるので注意しましょう。
Init関数について
// メインゲームの初期化処理 void SGameMain::Init(){ BgmControl.ChangePlay( BGM_GAMEMAIN ); }
タイトルと一緒です。ゲームメインに画面が切り替わるときに行う初期化処理を実行する関数です。ここではBGMをゲームメインのものに変更します。
FirstInit関数について
// 最初の変数の初期化 void SGameMain::FirstInit(){ memset(this,0,sizeof(SGameMain)); }
タイトルと一緒です。プログラムが起動したときに1度だけ実行する初期化です。自分の構造体の変数を全て0にしています。
Load関数について
// ロード void SGameMain::Load(){ Graphic[MG_BACK] = LoadGraph("picture/main_back.bmp"); } タイトルと一緒です。画像をロードしています。添え字は列挙定数です。
描画関数
// 描画 void SGameMain::Draw(){ DrawGraph(0,0,Graphic[MG_BACK],FALSE); DrawString(100,100,"メインゲーム画面です",Black); DrawString(100,120,"Zでゲームクリア",Black); DrawString(100,140,"Xでゲームオーバー",Black); }
タイトルと一緒です。グラフィックハンドルの添え字は列挙定数です。カラーコードのBlackはglobal.hに定義されています。
Pose関数について
// ポーズ bool SGameMain::Pose(){ if( Key[KEY_INPUT_A] == 1 ){ // ポーズボタンが押されたとき if( PoseFlag == false ){ // ポーズ状態でなかったら PoseFlag = true; // ポーズ状態に変更 } else if( PoseFlag == true ){ // ポーズ状態だったら PoseFlag = false; } } if( PoseFlag == true ){ // もしポーズ状態なら DrawString(100,200,"ポーズ中です",Black); // 文字を表示する } return PoseFlag; // ポーズフラグを返す }
戻り値がbool型です。真(true)か偽(false)を返します。この場合、ポーズ状態なら真を、ポーズ状態でないなら偽を返します。
まず、この関数はAが押されたときに反応します。上から、Aが押されたとき、いままでポーズ状態でなかったらポーズ状態にする、いままでポーズ状態だったのならポーズ状態を解除するという条件分岐をしています。
そして、次のif文でポーズ状態ならそのことを知らせる文字列を表示するというものです。
最後に、PoseFlagnの値を返しています。真を返した場合、Process関数の多くの処理を実行しないで関数を終了します。
まず、この関数はAが押されたときに反応します。上から、Aが押されたとき、いままでポーズ状態でなかったらポーズ状態にする、いままでポーズ状態だったのならポーズ状態を解除するという条件分岐をしています。
そして、次のif文でポーズ状態ならそのことを知らせる文字列を表示するというものです。
最後に、PoseFlagnの値を返しています。真を返した場合、Process関数の多くの処理を実行しないで関数を終了します。
Pose構造体をつくり、制御するほうがいいかもしれません。ポーズ状態なら文字を表示するという部分はPoseProcess関数などを作成し、処理させるべきでしょう。ぜひ挑戦してみてください。
また、SGameMainのDraw関数にPoseFlagの値によって描画するかどうかの分岐を持たせることでポーズ状態のときは背景とプレイヤーは描画するけど、敵は描画しないといったテクニックを実現することが出来ます。
また、SGameMainのDraw関数にPoseFlagの値によって描画するかどうかの分岐を持たせることでポーズ状態のときは背景とプレイヤーは描画するけど、敵は描画しないといったテクニックを実現することが出来ます。