title.cppについて
もうここまで読んだらなんとなく分かってきたかもしれませんが、やってることはびっくりするほど簡単です。正確にはやってることがとても簡単に見えるくらいまで関数を細分化しているのです。関数を分けて書かないで長文を書くと、やってることは同じなのにとても難しく見えます。
にしても驚くほど説明することがない・・・。
にしても驚くほど説明することがない・・・。
まずはヘッダーファイルから見ます。重複インクルード防止のマクロ記述は腸略します。
const int TG_NUM = 8; //TitleGraphicNumberの略 enum eTG_INDEX{ TG_BACK, }; struct STitle{ int Graphic[TG_NUM]; void Process(); // この中でループする void Init(); // 初期化 void FirstInit(); // コンストラクタ void Load(); // ロード void Draw(); // 描画系をここにまとめる };
見るべき点は、const指定による配列のサイズを決めいている点と、列挙型?を用いて配列の添え字を決めている点です。この場合、Graphic配列は要素数が8で、TG_BACKは0として扱われることになります。このような配列の添え字には意味が分かりやすいように列挙型を用いましょう。
Prosess関数について
// 全体の処理 void STitle::Process(){ Draw(); // 描画をする if( Key[KEY_INPUT_Z] == 1 ) // キー入力で画面チェンジ ChangeGameState( GS_MAIN ); }
現在は、描画する関数とZキーが押されたらゲーム画面に切り替える機能しかありません。ところで、このDraw関数は同じ構造体のDraw関数を呼び出しているわけです。慣れるまでは分かりにくいと思いますが、慣れると記述が簡単で読みやすくなると思います。
Init関数について
// タイトル画面の初期化処理 void STitle::Init(){ BgmControl.ChangePlay( BGM_TITLE ); }
これはタイトル画面が呼び出されるたびに実行される初期化関数です。下の初期化とは別物です。ChangeGameState関数から呼び出されます。ここではBGMを変更する処理のみ書かれています。このBGMを変更する関数は直前まで再生されていたBGMを止めてから新しく指定したBGMを再生する機能を持っています。ちなみに、Initは英語で初期化を意味するinitializeの略です。
FirstInit関数について
// 最初の変数の初期化 void STitle::FirstInit(){ memset(this,0,sizeof(STitle)); }
これはプログラムが起動した直後に実行される、構造体の変数の初期化をする関数です。main.cppのFirstInit関数から呼び出されます。さて、ここにあるmemset(メモリーセット)関数は、構造体や配列を初期化するときに使用されることがある関数です。とりあえず、この記述は自分自身の変数を全て0にしているということのみ覚えてください。
memset関数をアバウトに説明すると、第1引数が初期化したい構造体や配列の先頭アドレス、第2引数がどの値で変数を埋めるか、第3引数が第1引数のアドレスから、第2引数の値で変数を書き換えるバイト数という動作をします。かなり正確な動作とは違うので、詳しい使い方はググってください。
第1引数のthisは、thisポインタといい、構造体の自分自身をしめすポインタです。分かりにくいですね。そもそも、このプロトタイプ宣言は構造体の定義であって、実体を持っていません。そのため、自分自身のポインタは呼び出されるまで確定せず、定数として扱うことが出来ないのです(だいぶ嘘ついてますが、捕らえ方はこんなかんじ)。そのためthieポインタを使用する必要がるのです。
第3引数の書き換えるバイト数にはsizeof関数を用いています。sizeof関数は、引数に渡された変数や構造体の大きさを返します。単位はバイトです。
基本的に使用するのは第2引数で配列や構造体を埋めたいときに使用します。C言語の構造体?や配列?のとこを見てください。あとで書き足します。
memset関数をアバウトに説明すると、第1引数が初期化したい構造体や配列の先頭アドレス、第2引数がどの値で変数を埋めるか、第3引数が第1引数のアドレスから、第2引数の値で変数を書き換えるバイト数という動作をします。かなり正確な動作とは違うので、詳しい使い方はググってください。
第1引数のthisは、thisポインタといい、構造体の自分自身をしめすポインタです。分かりにくいですね。そもそも、このプロトタイプ宣言は構造体の定義であって、実体を持っていません。そのため、自分自身のポインタは呼び出されるまで確定せず、定数として扱うことが出来ないのです(だいぶ嘘ついてますが、捕らえ方はこんなかんじ)。そのためthieポインタを使用する必要がるのです。
第3引数の書き換えるバイト数にはsizeof関数を用いています。sizeof関数は、引数に渡された変数や構造体の大きさを返します。単位はバイトです。
基本的に使用するのは第2引数で配列や構造体を埋めたいときに使用します。C言語の構造体?や配列?のとこを見てください。あとで書き足します。
Load関数について
void STitle::Load(){ Graphic[TG_BACK] = LoadGraph("picture/title_back.bmp"); // タイトルの背景画像をロード }
タイトル画面に表示する画像を読み込んでいます。今回は読み込む画像は1つですが、拡張性を考えて配列にしてあります。読み込む画像を追加したいときはpictureフォルダに画像を追加し、Load関数で読み込ませてください。
Draw関数について
// 描画 void STitle::Draw(){ DrawGraph(0,0,Graphic[TG_BACK],FALSE); DrawString(100,100,"タイトル画面です。",White); DrawString(100,120,"Zでゲームスタート。",White); }
読み込んだ画像を表示し、さらに文字を描画しています。TG_BACKはヘッダーファイルで定義した列挙定数です。文字のカラーコードWhiteはglobal.hに定義されているグローバル変数です。描画する順番を間違えないようにしましょう。文字を描画してから背景画像を描画すると、文字の描画は画像に隠れてしまい見ることが出来ません。
また、このDraw関数は極力Process関数のはじめに呼び出しましょう。これはデバッグする際に役に立ちます。2つのサンプルProcess関数を見てみましょう。
また、このDraw関数は極力Process関数のはじめに呼び出しましょう。これはデバッグする際に役に立ちます。2つのサンプルProcess関数を見てみましょう。
先にDraw関数を呼び出した場合
void STitle::Process(){ Draw(); DrawString(...); // この関数の文字を見ることが出来る }
後にDraw関数を呼び出した場合
void STitle::Process(){ DrawString(...); // この関数の文字は次のDraw関数に上書きされてみることが出来ない Draw(); }
コメントのように、先にDraw関数を呼び出すと、デバッグのために呼び出した文字列を見ることが出来ます。デバッグのために変数を表示したりする場面は多いので、覚えておいてください。