■ 新・ゲーム開発講座 |
■ へっぽこプログラミング入門♪ |
■第51夜:システムメニュー:LOAD 前回までで、SAVEはできるようになりました。今回はLOAD処理についてインプリメントしましょう。ソースはこちらです。 言うまでもなくLOAD処理とは、SAVEしたときのプログラム的な状況を再現する操作です。基本的にはSAVEと逆の方法でデータを取り出し、値をメモリ内の変数に格納します。気をつけなければならないのはポインタ処理で、ポインタの値を直接保存することは無意味なのでオフセットで保存する…というのは前回までにお話したとおりです。まあ、SAVEについて一通りわかっていれば内容的には似たようなものです(・ω・)ノ。 ■窓をひらく(撃つ) メニュー窓を開く部分はSAVEとほとんど同じです(とゆーかそっくりコピーですし
^^;)。
もちろんBMPも同じサイズです。 |
//===================================================== _Menu_Win SysMenu_load; //LOADメニューの窓情報用 //名前が長いと面倒なので短縮表記を定義(SAVE窓用) int System_load() //LOADメニュー窓を開く
|
■回す マウス入力のスキャン部分は毎度毎度々々々々同じなので解説を省きます(^^;)。重要なのは、LOADすべきファイルが選択されたときの動作です。まずはさらりとソースを読んでみてください。 |
int System_load_task() //システムメニューのタスク部分 {
|
メッセージBOXを用いて確認メッセージ「LOADしますか?」を表示し、プレイヤーが「いいえ」=IDNO を選択したらふたたびスキャンループに戻り、そうでなければLOADの準備として現在鳴っているBGMを停止します。ここでは第33、34、37夜で作成した演奏停止関数を読んで済ませています。 次に、システムメニューのウィンドウを閉じる関数 _System_load_task_end() を呼んでいます。この段階でメニュー窓を閉じるのは、窓の背景の書き戻しを早い段階で済ませてしまうためです。窓BGMの背景退避領域には、システムメニューを開いたときのバックサーフェイスの一部が退避しています。窓を閉じるのがLOADデータの読み込み後になってしまうと、メニュー窓を閉じた後にLOAD前の画面の一部が書き戻されてみっともないことになります(どうせLOAD画面で上書きされるので書き戻さずに放っておくという漢の選択もありますが、気分的に正式に閉じておきたいです… ^^;)。 窓を閉じたら、いよいよSAVE構造体にファイルを読み込み、環境復元のための関数 restore_save_info() を呼びます(内容は後述します)。そして、BGM起動タスクにバトンタッチします。 このBGM起動タスクって何だ?と思われる方もいると思いますが、これはBGMの再生を安定させるための苦肉の策だったりしまして、あまりカッコイイものではありません…(大汗
^^;) MCIでBGMを演奏する場合、演奏停止 → ファイル読み込み → 演奏開始 を一度に行おうとすると動作が不安定になる場合があるのです。そこで、演奏を再開する前に
Mainloop() を一度カラ回りさせてやろうというのがここで行っている操作の意味です。具体的には Mode_stat.flag_system_menu
に SYSMENU_LOAD_BGM という値(SystemMenu_01.h で定義しています)をセットして、次にループが回ってきたらBGMタスクのほうに処理を振り向けます。BGMタスクでは演奏再開したのちフラグをOFFにしてLOAD処理の終了するという次第です。(とゆーかもっといい方法があったら教えて欲しいです、はい
^0^;) LOADタスク終了部分を以下に示します。 |
void _System_load_task_end() //タスクの終了処理部分を分離したもの {
|
■SAVE内容の復帰部分 いよいよ、肝心のSAVE内容の復帰部分です。とはいえ、別に難しいことをしている訳ではありません。まずはスクリプトファイルを読み込み、テキストポインタをリセットします。SAVE構造体に格納してあるのはテキストバッファ先頭からのオフセット量ですから、テキストポインタにはバッファの先頭アドレス+オフセットを設定してやります。 その後、念のためにデフォルト背景画像を各サーフェイス (バックサーフェイス、背景画面、パーツ画面) に読み込んで初期化したのち、BMPファイル名のキャッシュ内容に従ってそれぞれのBMPを読み込みます(ここでは、ファイル名の長さが0の場合は何もしない=デフォルト背景のままとします)。 画面の復帰が終わったら、コンフィグ項目、SAVEポイントモードを復帰し、フラグ構造体 Mode_stat も復帰(単純なコピー)します。 |
void restore_save_info()
|
こうしてみると実際のLOAD処理は恐ろしく簡単そうに見えますが、それは保存/復帰する内容を整理したからで、特に画面状況の復帰を大胆にばっさり切ってのけたことが大きいと思います。このあたりはコーディング以前の段階(仕様とか設計とか)で難易度が大きく左右されます。
さきほど述べました「Mainloop1回分カラ回り」の処理です。main.cpp の Mainloop() に、フラグに応じてBGMタスクを呼ぶ部分を追加します。それにしても、システムメニューのフラグを Mode_stat.flag_system_menu 1個に絞ったのは正解だったなぁ…(互いに排他処理になるので動作が重ならない)。 |
void Mainloop(void) {
|
演奏再開部分は、以下のとおりです。SAVEデータをパッケージしたときに、演奏中でない場合はファイル名をNULL文字列にておいたので、それを手がかりに演奏する/しないを判定しています。念のために mciSendString("seek _MIDI_ to start",NULL,0,0); で強制的に先頭からの演奏を指定している以外は 第33、34、37夜 の内容を踏襲しています。そして、最後にループフラグを OFF にしてLOAD処理を終えています。 |
void System_load_begin_BGM() //セーブデータの内容に従ってBGMを再生する {
} |
さて、それでは実際にコンパイルして実行してみましょう。サンプルスクリプトを書いてみて思ったのですが、SAVEポイントは AUTO 設定で改ページ毎に自動処理にしておくのが一番無難でラクなようです。サンプルでは画面が切り替わりながらテキストが流れるループを繰り返しますので、いろいろなタイミングでSAVE/LOADして動作内容を確認してみてください。 |
|