ページ 11

終了処理について

Posted: 2012年3月31日(土) 01:16
by とっち
今、DXライブラリで簡単なRPGを作成しています。
そこで少し疑問に思ったことがあったので質問させていただきます。
環境はWindows7,c++,DXライブラリです。

以下仮想コードで申し訳ないです・・・

コード:

#include "Dxlib.h"

title(){
	switch(state){
	case "New Gameが選択された時":
		// ゲーム処理へ
		break;
	case "Load Gameが選択された時":
		// ゲーム処理へ
		break;
	case "Exitが選択された時":
		// 終了処理
		break;
	}
}

int WinMain(略){
	// 初期化
	while(メインループ){
		title();
	}
	
	DxLib_End();
	return 0;
}
このようなコードがあったとします。
質問したいのはtitle関数のcase "Exitが選択された時":についてです。
Exitが押された時プログラムを終了したいのですが、その方法として次のようなものが思い浮かびました。

方法1:
    Exitが押された時return 1;など、適当な値を返しWinMain関数のメインループを抜けるようにする。
方法2:
    c言語のexit関数を使用して強制的に終了させる。


方法1の場合、たとえばtitle関数の中のcalc関数の中の・・・のようにWinMain関数から遠い場合、
その都度returnで値を返さなければならないので、コードが汚くならないかなと危惧しています。
方法2の場合、DxLib_End関数は呼ばれないので、DXライブラリを使用しているのにいいのかなって思ってしまいます。

何か良い方法などありますでしょうか?
ご教授よろしくお願いします。

Re: 終了処理について

Posted: 2012年3月31日(土) 01:35
by パコネコ
私の場合は、メインループのループ条件の中にフラグをめり込んでます。
終了処理を行なったあとにフラグをそこで立ててあげます。
フラグが立っていればループ条件に当てはまらないためループ終了。
そうすれば、コードは汚くならないんじゃないかな~っと思っています。

方法2ですが、
それでしたら、exitを呼び出す前にDxLib_Endを呼んでみたらどうかと思います。
( 自分で行なっている方法ではないのでそれで正しいとは言い切りませんが・・・ )

あとはgotoでDxLib_Endの前に飛ぶ方法もあるにはあるかと・・・gotoは好きではないですし私的にはおすすめではありませんが。

Re: 終了処理について

Posted: 2012年3月31日(土) 01:46
by zxc
  exitでなくDxLib_Endで終了させた方が望ましいと思います。
DXライブラリを使用するなら呼ぶ必要があるみたいですから。
  
  もしくはstateを変更した上でもう一度title関数を呼ぶような処理も
一応は終了に繋がる処理といえるのではないでしょうか。
実用的な場面は思いつきませんけども。

Re: 終了処理について

Posted: 2012年3月31日(土) 01:54
by UN
方法1だろうが方法2だろうが
結果的に変数stateをExitに変更しなくてはいけないという意味では
意味は同じになるような気がします。
ちなみにPCのみの思考でいくなら方法2でもいいですが、
IPhoneなど他のプラットフォームでは基本的に終了処理は正式な手順を踏んで終了させないと
いけないため、方法1の正式な終了処理を通すことをお勧めします。
汎用制も高まりますし。

PCではウインドウズの右上の×印が押された際の処理もあるしで
(WindowMessageのCloseWindowみたいなメッセージが飛んでくるみたいな仕様でしたが)
Stateだけでは限界があるため、

1:Exitフラグみたいなものをtitleやlogoなどどこからも参照できるようにして、
それぞれの内部でそのフラグがたったときに、各titleやlogoで
使用したメモリを解放後にメインループを抜ける

2:titleやlogoの更新関数の返り値で、それぞれexitに値するものが返ってきたら
メインループを抜ける

など、いずれにしても
各シーンで終了を確実に行わせて、全て解放してからメインループを抜けるという方法をお勧めします。
スレッドなんかを使いはじめると、どこのシーンでどのスレッドを使用してなんかを管理して
ちゃんと終わらせてから終了するというのを実現するには、一番上の階層で管理よりは
使用した本人に終わらせてもらうというのが一番ですから。

Re: 終了処理について

Posted: 2012年3月31日(土) 09:18
by beatle
C言語標準ライブラリにatexitという関数があります。この関数を使うと、プログラム終了時に自動で呼び出して欲しい関数を登録することができます。
atexitでDxLib_Endを実行するような関数を登録しておけば、exit関数で、またはmain関数からreturnでプログラムが終了したときにDxLib_Endを実行させることができます。

Re: 終了処理について

Posted: 2012年3月31日(土) 11:03
by とっち
みなさま解答ありがとうございます。

>パコネコさん
フラグというのは便利ですね。
それにわかりやすくてよさそうです。

>zxcさん
確かにDXライブラリを使用するならexit関数よりDxLib_End関数を直接呼んだほうがいいですね。

>UNさん
なるほど・・・
今後のためにも今回の場合は方法1:のようにメインループを抜けるような
仕様にしたほうがよさそうですね。

>beatleさん
こんな関数があるのですか!
便利な関数を教えていただいてありがとうございます。


今回の場合はパコネコさんのフラグで管理するという方法をとらせていただくことにします。
様々な解答をいただき本当にありがとうございました。

Re: 終了処理について

Posted: 2012年3月31日(土) 11:27
by たかぎ
初期化と終了の処理を確実に呼び出す方法として、私がよく使っているのは...

コード:

int WINAPI WinMain(...)
{
    struct _
    {
        _() { if (DxLib_Init() == -1) std::exit(-1); }
        ~_() { DxLib_End(); }
    } z;
    ...
    return 0;
}
といった方法です。
これなら、WinMainの途中からreturn文で終わろうが、例外が捕捉されずに終わろうが、確実にDxLib_Endが呼ばれます。

Re: 終了処理について

Posted: 2012年3月31日(土) 18:01
by ISLe
メニューで終了を選んだら、
PostMessage(GetMainWindowHandle(), WM_CLOSE, 0, 0);
というふうにウィンドウを閉じるメッセージを投げる方法もあります。

Re: 終了処理について

Posted: 2012年3月31日(土) 22:29
by とっち
>たかぎさん
コンストラクタとデストラクタという考えでよろしいのでしょうか?
それなら確実に呼び出されますし、簡単ですね

>ISLeさん
こんな関数もあるのですか・・・
まだまだ勉強不足ですね

いろいろな解答本当にありがとうございます。