Dxライブラリ 書いてはいけない処理

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ユーマ
記事: 29
登録日時: 3年前

Dxライブラリ 書いてはいけない処理

#1

投稿記事 by ユーマ » 3年前

プログラムを始めたばかりの初心者です。よろしくお願いします。

先日、Dxライブラリについて勉強していると次のサイトでこのようなことが書かれていました。(ちなみにそのサイトはhttp://dixq.net/g/h_11.htmlです)

ここには ProcessMessage(),ClearDrawScreen(),ScreenFlip() が複数の場所に書かれているといけない。

私は、なぜこれがダメなのかを知りたいです。

また、この三つを複数書かないでゲームプログラミングする方法が私には思いつきません。(今まではこれをwhile分の条件の中などに、たくさん書いてしまっていました)

もし、ダメな理由がわかる方やこの三つを複数書かないで正しくプログラミングする方法をご存知の方かいらっしゃいましたらご教授ください>_<

よもやま
記事: 68
登録日時: 5年前
連絡を取る:

Re: Dxライブラリ 書いてはいけない処理

#2

投稿記事 by よもやま » 3年前

ユーマ さんが書きました:プログラムを始めたばかりの初心者です。
どの程度まで理解されておられるのか具体的に記載いただけないですか。
まずC言語でWindowsプログラムを作成されたことがあるのでしょうか。

猫でもわかるプログラミング(WindowsSDK編 第1部)
少なくともWindowsにてCreateWindowとWinProcの関係について理解を深めることをお勧めします。
ユーマ さんが書きました: ここには ProcessMessage(),ClearDrawScreen(),ScreenFlip() が複数の場所に書かれているといけない。

私は、なぜこれがダメなのかを知りたいです。
まず、題材としているゲームは、1フレームウィンドウを持ち複数のシーンを構成するアプリといえます。
タイトル、ゲーム、ランキング、オプション設定を1フレームウィンドウでシーンを切り替えるような形となろうとおもいます。
その際、シーンごとで各メッセージ(選択、コントローラーからの入力など)を処理したいとしても通知されてくるのは最初につくったフレームウィンドウです。

そもそもメッセージ取得は1フレームウィンドウにつき1つが原則です。
CreateWindow、CreateWindowEx、CreateDialogのAPI関数リファレンスを参照ください。
CreateWindow
CreateWindowEx
CreateDialog

そして、メッセージと再描画までの一連の流れとしては、
1.メッセージ取得
2.メッセージに対応した処理
(以下は必要に応じて、または安全策として必ず背景を消去し再描画させるという考えもあり)
3.背景消去
4.再描画

シーンに合わせた処理という点で参考になりえるのは
LED、液晶が搭載されている炊飯器や電気ポット、電子レンジといったものでしょうか。
炊飯器でいくと炊飯メニューボタンを押すと玄米やらが選べて
炊飯量にあわせ炊飯に必要な時間まで表示されたりします。
表示内容が押されたボタンなどに切り替わる様子は、ゲームタイトルからゲームを選択したりゲームタイトルからオプション設定へ、ゲームタイトルからランキングへといった遷移に似ています。

また基本無料のスマホゲームでも似た構造が多いですね。

コードの一例です。このままではコンパイルは通りません。参考までに。。

コード:

//関数引数として通知メッセージ、実際ゲームアプリでは足りないと思われる。
void dispatchMessage(int message) {
	swtich(ScreenMode) {
	case SC_TITLE;
		dispatchMsgTitle(message);
		break;
	case SC_GAME:
		dispatchMsgGame(message);
		break;
	case SC_SETTING:
		dispatchMsgSetting(message);
		break;
	case SC_RANKING:
		dispatchMsgRanking(message);
		break;
	}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode( TRUE ); // ウィンドウモードに設定
	DxLib_Init();   // DXライブラリ初期化処理
	SetDrawScreen( DX_SCREEN_BACK ); //描画先を裏画面に設定
	//他色々必要に応じて初期処理
	ScreenMode = SC_TITLE;

	int notifyMessage = 0;
	while( 1 ){
		if( ProcessMessage() != 0 ){ // メッセージ処理
			break;//ウィンドウの×ボタンが押されたらループを抜ける
		}
		//notifyMessageにはキー入力、コントローラーからの通知内容を格納する
		//関数パラメータは1つだけでは足りないと思われる。
		dispatchMessage(notifyMessage);
		ClearDrawScreen();// 画面を消す
		/* ====== 描画処理 START  ====== */
		/* ====== 描画処理 END    ====== */
		ScreenFlip();  //裏画面を表画面に反映
	}

	DxLib_End();    // DXライブラリ終了処理
	return 0;
}

アバター
Dixq (管理人)
管理人
記事: 1661
登録日時: 10年前
住所: 北海道札幌市
連絡を取る:

Re: Dxライブラリ 書いてはいけない処理

#3

投稿記事 by Dixq (管理人) » 3年前

まさにこの記事を書いた者です。
http://dixq.net/g/h_11.html

ゲームプログラムというものは、一般的に1秒間に60回画面を書き換えるように作ります(可変フレームレートは今回省略)。
ですので、処理を特定の場所で止めてはいけません。
あらゆるところで処理を止めてしまっては全体的な管理ができなくなってしまいます。
従って、常にメインループに処理を返しましょう。
特定の関数やモジュールの中に閉じて新しいループ(ProcessMessage(),ClearDrawScreen(),ScreenFlip()を行う物)を作ってはいけません。

仕様変更・管理が難しくなる一例として、「どんな時もF12を押したら強制終了するようにしよう」と思ったら、
今のプログラムコードにどういう修正をしますか?
ゲームプログラミングの館で紹介している設計なら、一行、コードを追加するだけで済みますが、
ユーマさんのコードだと、おそらくあらゆる箇所に処理を追加する必要が出てくると思います。
このようなことが、何か仕様を追加するたびに出てくるのです。

> この三つを複数書かないでゲームプログラミングする方法が私には思いつきません

ゲームプログラミングの館で紹介しているような設計方法を用いれば特別難しいことはありません。
http://dixq.net/g/
こちらの「ゲームプログラミング設計」や「メニューの作り方」が参考になると思いますので読んでいただければと思います。

ユーマ
記事: 29
登録日時: 3年前

Re: Dxライブラリ 書いてはいけない処理

#4

投稿記事 by ユーマ » 3年前

よもやまさん、Dixq管理人さんご回答ありがとうございます。

まず、よもやまさん。具体的なプログラムまで載せてくださりありがとうございます。
また、私自身のプログラムの理解度の記述が少なかったことについては次から気を付けていきたいと思います。
あなたの回答のおかげで少し、この三つの関数の使い方の理解が深まったように感じました。
このプログラムを参考にしていきたいと思いますorz

そしてDixq管理人さん。確かに、「どんな時もF12を押したら強制終了するようにしよう」 などとしたときに私の方法だと一々そのためのコードを書かないといけないと思いました。
紹介されたページを読んでみると、僕の知りたかったことがわかりました。常にメインループに処理を返す、そこを意識してプログラムを組んでいきたいと思います。


今回は回答してくださったお二人のおかげで理解することができました。
これからも質問させていただく時に教えてくださると幸いです。
ありがとうございました!

ユーマ
記事: 29
登録日時: 3年前

Re: Dxライブラリ 書いてはいけない処理

#5

投稿記事 by ユーマ » 3年前

すみません、解決にするのを忘れていました。

返信

“C言語何でも質問掲示板” へ戻る