シーン管理とは

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

シーン管理とは

#1

投稿記事 by LisetteLander » 13年前

今作成中のゲームのメインループでswitchによるシーン変異をしているのですが、
管理方法を「シーン管理」に移行したいです。
しかし、調べてもswtich管理との共通点がよくわからないです。()
何かわかりやすいソースコードや説明サイト、
もしくは、我儘ですが下記のコードをシーン管理に準じた設計に変えてくれるととても助かります。

現在の↓

コード:

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),SetGraphMode(X_WINDOW,Y_WINDOW,16),DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); 

		enum{
			GAMESTART,
			MENU,
			MAINGAME,
			GAMEEND=99
		}GAME_STATUS;

		GAME_STATUS=GAMESTART;
		while(ProcessLoop(GAME_STATUS)==0){
			switch(GAME_STATUS){
					case GAMESTART:
						GAME_STATUS=MENU;
						break;

					case MENU:
						GAME_STATUS=Menu();
						break;

					case MAINGAME:
						break;

					default:
						//GAMEEND
						break;
				}
		}

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: シーン管理とは

#2

投稿記事 by softya(ソフト屋) » 13年前

シーン管理≒画面に特化した一種のタスクシステムだと私なりには理解していますが違ったらごめんなさい。
C++のクラスを使った実装が多いと思いますが、どの様な形で実装される予定ですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

naohiro19
記事: 256
登録日時: 14年前
住所: 愛知県

Re: シーン管理とは

#3

投稿記事 by naohiro19 » 13年前

シーン移行の実装には2つの方法があります。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#4

投稿記事 by LisetteLander » 13年前

関数ポインタのほうがわかりやすそうです

関数ポインタでシーン管理するとなると、関数ポインタ配列の返り値でシーン変異をするのでしょうか?
そうすると、例えばenumで定義した{MAINGAME,RESULT}などの、結果表示画面などのデータの受け渡しはグローバル変数になるのでしょうか?
またループ中、「その関数が指定されている間だけ常に保持したい変数」などもグローバル変数になるのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: シーン管理とは

#5

投稿記事 by softya(ソフト屋) » 13年前

LisetteLander さんが書きました:関数ポインタのほうがわかりやすそうです

関数ポインタでシーン管理するとなると、関数ポインタ配列の返り値でシーン変異をするのでしょうか?
そうすると、例えばenumで定義した{MAINGAME,RESULT}などの、結果表示画面などのデータの受け渡しはグローバル変数になるのでしょうか?
またループ中、「その関数が指定されている間だけ常に保持したい変数」などもグローバル変数になるのでしょうか?
話の内容からするとクラスは使わずにC言語の文法の範囲ってことで良いでしょうか?

[補足と言うかアイデア]
大雑把な例ですが、C言語で組むとしたらシーン管理モジュールで全て管理して
(1) 状態で動作するシーン関数を登録する関数。
(2) 次回の状態を変更する関数。保持はシーン管理モジュール。
(3) 状態に応じてシーン関数を呼び出す関数。
とするのはどうでしょうか?
最初の(1)はmainのループ前に行い、初期値を(2)で設定、mainからは(3)の関数を常に呼び出します。
シーンの遷移はシーン関数から(2)を呼び出して行うか戻りで制御します。
状態のenumは別途ヘッダに適宜します。

あとおまけとしてシーン関数の引数として管理構造体にシーン毎のフレームカウントやらパラメータやらを付けて呼び出してやるって機能もつけたりすると便利です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#6

投稿記事 by LisetteLander » 13年前

いえ、別にC++の機能を使ってもいいです。
色々試行錯誤していたらこのようになったのですが・・・
C++に似つかわしくない方法ということでしょうか?

自分の知識不足から来るものでもあると思います。
最後に編集したユーザー LisetteLander on 2012年5月21日(月) 00:40 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: シーン管理とは

#7

投稿記事 by softya(ソフト屋) » 13年前

LisetteLander さんが書きました:いえ、別にC++の機能を使ってもいいです。
色々試行錯誤していたらこのようになったのですが・・・
C++に似つかわしくない方法ということでしょうか?
C++なんですね。
それならシーンクラスを作って継承をした方が良いと思います。
詳しくは、申し訳ないですが明日ってことで。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#8

投稿記事 by LisetteLander » 13年前

返答ありがとうございます。
また、後日でいいのですがもうひとつ疑問があるので記入しておきます。

特定のシーンでクラスのインスタンスを保持しておき、他のシーンに変異した時に保持しておいたインスタンスを開放する
というのは現実的な手法なんでしょうか?
例えばアクションRPGなどで戦闘時以外では[バトル]クラスが持つであろうフィールド内最大人数や着地判定や当たり判定などは必要ないわけで
つまり、[バトル]クラスは戦闘画面突入時にインスタンス化されて初期化され、戦闘中のみ保持されるべきだと思うのですが・・・

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: シーン管理とは

#9

投稿記事 by h2so5 » 13年前

LisetteLander さんが書きました: 特定のシーンでクラスのインスタンスを保持しておき、他のシーンに変異した時に保持しておいたインスタンスを開放する
というのは現実的な手法なんでしょうか?
シーンが変わるごとにインスタンスを新しく作り、
それまでのシーンのインスタンスを破棄するというのは分かりやすい方法だと思います。

インスタンスの生成に時間がかかる場合や頻繁に切り替えが起こる場合は、
シーン開始時に初期化だけしてインスタンスを再利用するという方法もあります。

また、例えばアクションRPGで戦闘の途中にイベントが入り、
イベントの後で戦闘を再開するような演出を使う場合は後で使うためにシーンのインスタンスを保持する必要があるでしょう。
LisetteLander さんが書きました: 例えばアクションRPGなどで戦闘時以外では[バトル]クラスが持つであろうフィールド内最大人数や着地判定や当たり判定などは必要ないわけで
つまり、[バトル]クラスは戦闘画面突入時にインスタンス化されて初期化され、戦闘中のみ保持されるべきだと思うのですが・・・
あまり例が良くないような気がします。
アクションRPGの場合、戦闘中でなくても着地判定や当たり判定などは必要なことが多いと思います。
もっとも、移動中に必要な当たり判定と戦闘中に必要な当たり判定は違うかもしれないですが。
オフトピック
メモリ(インスタンス)は「開放」ではなく「解放」、
シーンは「変異」ではなく「遷移」するものです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: シーン管理とは

#10

投稿記事 by softya(ソフト屋) » 13年前

LisetteLander さんが書きました:例えばアクションRPGなどで戦闘時以外では[バトル]クラスが持つであろうフィールド内最大人数や着地判定や当たり判定などは必要ないわけで
つまり、[バトル]クラスは戦闘画面突入時にインスタンス化されて初期化され、戦闘中のみ保持されるべきだと思うのですが・・・
それはMMORPGなどによく有る近接するとバトルが始まるタイプですね。
シーンの初期化コスト次第ですとしか言えませんね。どう設計するかは、h2so5さんの言われるとおりです。

で、クラス化したシーン管理ですが例を上げますので考えてみてください。これ以外にも方法はあります。

1.私のNo: 5で書いた方法のC++版を作成。
全てのシーンは基本シーンクラスを継承したものを使用して、各シーンのインスタンスをシーン管理クラスに登録する形で運用する。
状態→シーン管理クラスの参照にはstd::mapなどを利用してC++の恩恵を受ける形で作成します。
シーン管理クラスはシングルトンなど単一存在で、どこからでもアクセス可能。

2.シーンクラス自体に管理・実行判定を持つ。
シーン管理クラスをは存在しません。
基本シーンクラスは存在して、基本シーンクラス継承したシーンクラスをインスタンスのチェインで接続します。
状態は状態処理関数でインスタンスチェインを伝わって行く形で受け渡されて各シーンが状態を見て自分が実行すべきかは判断します。
自分が必要なくなれば、インスタンスのチェインを書き換えて自分自身のインスタンスは消滅させます(スマートポインタなど)。

参考になりそうなサイト。
「ゲーム作者の集い[ゲームヘル2000] - kenmo」
http://www5.atwiki.jp/yaruhara/pages/39.html
「その7 ゲーム遷移の実装をあれこれ考えてみる」
http://marupeke296.com/GDEV_No7_StateImpliment2.html
「クラス内メソッド遷移からswitch~caseを消すMethodExecテンプレート」
http://marupeke296.com/DXCLS_MethodExecTemplate.html
「シーンの遷移(Stateパターン) - ゲームプログラムめも日記 - Hatena::Group::Gamehell」
http://gamehell.g.hatena.ne.jp/kenmo/20 ... 1120514678
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#11

投稿記事 by LisetteLander » 13年前

ソフト屋さん、h2so5さん
ありがとうございます。

インスタンスの再利用は初期化する時要素が多いと取りこぼしが怖いし面倒です。(←甘え
ただ、これが一番簡単かもしれません。

1.の
シーン管理クラスを作成して、それぞれのシーンのインスタンスを登録するというのはいいのですが
グローバルな領域でstatic属性というかシングルトンで保持するのはわかるのですが
std::mapを利用して参照するというのはよくわかりません。
管理クラスがシングルトンで唯一性が確保されているのなら、クラス定義をincludeするだけで
管理クラスのメンバであるそれぞれのシーンのインスタンスは参照できるのではないのですか?

2.の
>基本シーンクラスは存在して、基本シーンクラス継承したシーンクラスをインスタンスのチェインで接続します。
というのはよくわかりません・・
タスクシステム?のようなものでしょうか?
このインスタンスもグローバル領域で保持して実行すべきインスタンスに伝わるように毎回同じインスタンスにスレッドを回すのでしょうか?
シーンはそれぞれ消えたり作られたりするのでポインタ(チェーン?)の引き継ぎなど可読性が低そうです・・・

認識が間違ってたら指摘もお願いします!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: シーン管理とは

#12

投稿記事 by softya(ソフト屋) » 13年前

LisetteLander さんが書きました:ソフト屋さん、h2so5さん
ありがとうございます。

インスタンスの再利用は初期化する時要素が多いと取りこぼしが怖いし面倒です。(←甘え
ただ、これが一番簡単かもしれません。
速度と面倒さはトレードオフだと思いますので、どっかしか取れないと思います。
LisetteLander さんが書きました: 1.の
シーン管理クラスを作成して、それぞれのシーンのインスタンスを登録するというのはいいのですが
グローバルな領域でstatic属性というかシングルトンで保持するのはわかるのですが
std::mapを利用して参照するというのはよくわかりません。
管理クラスがシングルトンで唯一性が確保されているのなら、クラス定義をincludeするだけで
管理クラスのメンバであるそれぞれのシーンのインスタンスは参照できるのではないのですか?
管理クラスがシングルトンですが各シーンはシーンクラス(シーン管理クラスと別)の継承クラスのインスタンスです。
管理クラスが全部の継承クラスのヘッダをインクルードする必要もありませんしシーンクラスの基底クラスのヘッダだけに留めるべきです。
std::mapは状態からシーンのインスタンスのポインタを得るのに使っては?と言う提案ですね。
LisetteLander さんが書きました: 2.の
>基本シーンクラスは存在して、基本シーンクラス継承したシーンクラスをインスタンスのチェインで接続します。
というのはよくわかりません・・
タスクシステム?のようなものでしょうか?
このインスタンスもグローバル領域で保持して実行すべきインスタンスに伝わるように毎回同じインスタンスにスレッドを回すのでしょうか?
シーンはそれぞれ消えたり作られたりするのでポインタ(チェーン?)の引き継ぎなど可読性が低そうです・・・
単なる基底クラスのポインタチェインなので、先頭クラスのポインタだけを持っていれば十分ですね。
それもmainループで保持するローカル変数で良いでしょう。
返事を書いている時に気づきましたが、stlのlistでも問題無いです。

【補足】
2の方法でゲームを組んだことはないので何かしらの穴があるかも知れません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#13

投稿記事 by LisetteLander » 13年前

ソフト屋さんのリンクをひと通り全部見てみました。
これが相当わかりやすいですね。
「その7 ゲーム遷移の実装をあれこれ考えてみる」
http://marupeke296.com/GDEV_No7_StateImpliment2.html

↑から派生してちょっと複雑になるのですが↓のもわかり易かったです。
ただ、複雑になる反面、利点といえばテンプレートを使いまわすことができる、ぐらいでしょうか。
「クラス内メソッド遷移からswitch~caseを消すMethodExecテンプレート」
http://marupeke296.com/DXCLS_MethodExecTemplate.html

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: シーン管理とは

#14

投稿記事 by LisetteLander » 13年前

とりあえず
・インスタンスの再利用
・「その7 ゲーム遷移の実装をあれこれ考えてみる」リンク
のふたつを利用しNo.1での質問が解決したので解決とさせて頂きます。

std::の利用はC++の勉強をして、実際にテストコードを書いたあとにゲームに組み込みたいと思います。

閉鎖

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