シーン分け 継承について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
c++勉強中

シーン分け 継承について

#1

投稿記事 by c++勉強中 » 9年前

シーン分けについてですが
継承を学んだので継承でシーン分けを考えていたのですが、
プレイ画面で引数が変わる場合継承ができなくて困っています。
その場合は共通に
しなければなりませんか?
なにかいい方法があれば教えてくださいお願いします。
int no = 0;//シーンの番号
int main(){
[tab=30]Windows windows;
[tab=30]HWND hwnd = windows.CreateSimPleWindow();//ウインドウの作成
[tab=30]Graphics g;
[tab=30]g.Init( hwnd );//グラフィックの初期化
[tab=30]Input input;
[tab=30]Field field( g );
[tab=30]Scene *scene = new Title;
[tab=30]scene->Init( g );
[tab=30]while( DoEvents() ){
[tab=30][tab=30]g.Clear();
[tab=30][tab=30]input.Update(); //キーの更新[/color]
[tab=30][tab=30]KeyboardState key = input.GetKeyboard(); //キーの情報を取得
[tab=30][tab=30][color=#00FF000]//キー入力でプレイ画面に行く[/color]
[tab=30][tab=30]if( no == 0 ){ //タイトル画面
[tab=30][tab=30]if( key.Just( Key::A ) ){
[tab=30][tab=30][tab=30][tab=30]delete scene;
[tab=30][tab=30][tab=30][tab=30]no = 1;//プレイ画面に移動
[tab=30][tab=30][tab=30][tab=30]scene = new Field( g );
[tab=30][tab=30][tab=30][tab=30]scene->Init( g );
[tab=30][tab=30]}
[tab=30][tab=30]scene->KeyUpdate();
[tab=30][tab=30]scene->Update( );
[tab=30][tab=30]scene->Draw( g );

[tab=30][tab=30]}
[tab=30][tab=30] //プレイ画面
[tab=30][tab=30] if( no == 1 ){
[tab=30][tab=30]field.KeyUpdate( &field, key );//問題の部分です
[tab=30][tab=30] field.Update( );
[tab=30][tab=30]field.Draw( g );
[tab=30][tab=30] }
[tab=30][tab=30] g.Update();

[tab=30] }
[tab=30] scene->Release();
[tab=30] g.Release();
}

おっく

Re: シーン分け 継承について

#2

投稿記事 by おっく » 9年前

main()関数の実装内容を見せられても、何とも言えない気がします。

問題の箇所だと指摘されている、
・fieldクラスについて
・どうして引数が変わるのか、ご自身が考える設計内容について
の情報が無いとコメント難しいと思います。

c++勉強中

Re: シーン分け 継承について

#3

投稿記事 by c++勉強中 » 9年前

失礼しました

ポインタで渡すのは
先行宣言をするためにポインタにしています。
Field.cpp
KeyUpdateではキー入力の処理をしています
block.Turn関数でfieldのポインタを渡したいので引数で渡しています
void Field::KeyUpdate( Field *field,KeyboardState &key){
[tab=30]//キーの入力にやる操作
省略
[tab=30] if( key.Just( Key::A ) ){
[tab=30][tab=30] block.Turn( *field );
[tab=30] }
[tab=30] if( key.Just( Key::S ) ){
[tab=30][tab=30] block.Turn( *field );
[tab=30] }

}

Block.cpp
TurnではfieldのGet()関数を使いたいので、参照で渡し
Getが真なら処理を実行させる形です
void Block::Turn(Field &field){
省略

[tab=30] //回転できるかどうか調べる
[tab=30] //ブロックがすでに合ったらフラグを立てる
[tab=30] //もしくはフィールド外なら回転しない
[tab=30] for(int i = 0;i < 4; i ++ ){
[tab=30][tab=30] for(int j = 0;j < 4; j ++ ){
[tab=30][tab=30][tab=30] if( field.Get( pos.x + j, pos.y + i ) ){
[tab=30][tab=30][tab=30][tab=30] 省略
[tab=30][tab=30][tab=30] }
[tab=30][tab=30][tab=30] if( pos.x + j < 0 || pos.x + j >= Field_X ){
[tab=30][tab=30][tab=30][tab=30] 省略
[tab=30][tab=30][tab=30] }
[tab=30][tab=30] }
[tab=30] }


}

このような説明で理解いただけましたか?
お願いします。

アバター
MNS
記事: 35
登録日時: 9年前

Re: シーン分け 継承について

#4

投稿記事 by MNS » 9年前

引数が変わるので継承ができないというのは、Fieldクラスが継承されるクラスですか?
それと、KeyUpdate関数について、どのように引数を変更したいのですか?
その説明ではイマイチ伝わらないと思います。

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

Re: シーン分け 継承について

#5

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

codeタグを利用していただくと手間もかからず読みやすくなります。
詳しくはフォーラムルールをお読みください。

コード:

int no = 0;//シーンの番号
int main(){
	Windows windows;
	HWND hwnd = windows.CreateSimPleWindow();//ウインドウの作成
	Graphics g;
	g.Init( hwnd );//グラフィックの初期化
	Input input;
	Field field( g );
	Scene *scene = new Title;
	scene->Init( g );
	while( DoEvents() ){
		g.Clear();
		input.Update(); //キーの更新
		KeyboardState key = input.GetKeyboard(); //キーの情報を取得
		//キー入力でプレイ画面に行く
		if( no == 0 ){ //タイトル画面
			if( key.Just( Key::A ) ){
				delete scene;
				no = 1;//プレイ画面に移動
				scene = new Field( g );
				scene->Init( g );
			}
			scene->KeyUpdate();
			scene->Update( );
			scene->Draw( g );

		}
		//プレイ画面
		if( no == 1 ){
			field.KeyUpdate( &field, key );//問題の部分です
			field.Update( );
			field.Draw( g );
		}
		g.Update();

	}
	scene->Release();
	g.Release();
}

//Field.cpp
//KeyUpdateではキー入力の処理をしています
//block.Turn関数でfieldのポインタを渡したいので引数で渡しています
void Field::KeyUpdate( Field *field,KeyboardState &key){
	//キーの入力にやる操作
	//省略
	if( key.Just( Key::A ) ){
		block.Turn( *field );
	}
	if( key.Just( Key::S ) ){
		block.Turn( *field );
	}

}

//Block.cpp
//TurnではfieldのGet()関数を使いたいので、参照で渡し
//Getが真なら処理を実行させる形です
void Block::Turn(Field &field){
	//省略

	//回転できるかどうか調べる
	//ブロックがすでに合ったらフラグを立てる
	//もしくはフィールド外なら回転しない
	for(int i = 0;i < 4; i ++ ){
		for(int j = 0;j < 4; j ++ ){
			if( field.Get( pos.x + j, pos.y + i ) ){
				//省略
			}
			if( pos.x + j < 0 || pos.x + j >= Field_X ){
				//省略
			}
		}
	}
}
シーン分けについてですが
継承を学んだので継承でシーン分けを考えていたのですが、
プレイ画面で引数が変わる場合継承ができなくて困っています。
その場合は共通に
しなければなりませんか?
なにかいい方法があれば教えてくださいお願いします。
今まで見せていただいたコードでは、どういう所で継承を使いたいのかイマイチ掴めておりません。
シーン分け継承がどの様な形でつなげるつもりなのか、こちらに伝わらないって感じです。
意図している継承とは、どんな事でしょうか?
現状のfieldクラス自体の定義も見せてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: シーン分け 継承について

#6

投稿記事 by dic » 9年前

ここはあえてつられて

コード:

    Windows windows;
    HWND hwnd = windows.CreateSimPleWindow();//ウインドウの作成
    Graphics g;
とありますが
Windows型? オリジナルですか?
Graphics型? Javaですか?
色々不思議さん状態です

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

Re: シーン分け 継承について

#7

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

dic さんが書きました:ここはあえてつられて

コード:

    Windows windows;
    HWND hwnd = windows.CreateSimPleWindow();//ウインドウの作成
    Graphics g;
とありますが
Windows型? オリジナルですか?
Graphics型? Javaですか?
色々不思議さん状態です
それらは、オリジナルかどこかのサイトが提供しているライブラリのクラスの名前ではないでしょうか?
どこらへんが釣られているのか説明をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: シーン分け 継承について

#8

投稿記事 by dic » 9年前

くいつきますね^^;
書き込んでもいいんでしょうかね
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。

c++勉強中

Re: シーン分け 継承について

#9

投稿記事 by c++勉強中 » 9年前

度々申し訳ありません
GraphicsとWindowsの型はオリジナルで自分で作りました。
GraphicsはDirect3Dの初期化と解放をクラスにしました。
Windowsも同様でWindowsの初期化を行っています。
Textureもオリジナルで、ddsの読み込みと解放をしています。
Inputはキーボードの状態を初期化と更新を行っています。
Main関数で行われているのはDoEventも自作関数でメッセージが呼ばれたら終了させる処理を作っています。
できる限りKeyUpdateは引数を変えない方向でお願いしたいのですが無理でしょうか?
できないなら、別の方法を考えいたします。何度も申し訳ありません。
お願いします。

コード:

Scene.h

class	Scene{
public:
	virtual		void	Init(Graphics &g){}
	virtual		void	KeyUpdate(){}
	virtual		void	Update(){}
	virtual		void	Draw(Graphics &g){ }
	virtual		void	Release( ){}
public:
	int scene;
};

Field.h

class Field:public	Scene{
public:
	//初期化の処理
	Field(Graphics &g):
	  block( g ),
	  field( Field_X * Field_Y, 0 )
	{
		next.texture = next.CreateTexture( g, "Next.bmp" );
		texture.texture = texture.CreateTexture( g, "bg.bmp");

	}
	 void	Init( Graphics &g ){ }
	void	KeyUpdate( Field *field,KeyboardState &key); 
	void	Update();
	//フィールド外に出ないように制御させる
	//一番左から一番右までの制御させる
	//座標 + 移動量がフィールド外なら移動量を0にする
	void	Chaeck(Block *block );
	//一番したまで来たらそこにブロックを設定する
	//移動量がフィールド外に出たら当たっている事を調べる
	//当たっていたらTrue を返し当たっていなかったらfalse
	bool	FirstLower(Block *block);
	//座標Y
	bool	CheckHitY(Block *block );
	void	CheckHitX(Block *block);
	//ブロックを設定する
	//もしブロックもしくはフィールドの一番したなら現在の座標に設定させ、初期値に戻す
	void	BlockSet(Block *block );
	//ブロックを消す処理
	//一列がうまっているかどうかを数えて、すべて埋まっていたらその列を消去する
	//消去したら消したブロックの上からすべておろす
	void	Delete();
	void	FieldDown(int y );
	int	Get( int x,int y ){
		return field[ x + y * Field_X ];
	}
	void	Set(int x, int y){
		field[ x + y * Field_X ] = 1;
	}
	void	Draw(Graphics &g);
	void	Release(){
		next.Release();
		texture.Release();
	}
public:
	Texture		next;
	Texture		texture;
	Block		block;
	std::vector< int >field; 
};


main.cpp

class	Title:public Scene {
public:
	void	Init(Graphics &g){
		D3DXCreateTextureFromFile( g.device, "title.bmp", &texture.texture );
	}
	void	Update(){
	}
	void	Draw( Graphics &g ){
		if( g.Begin() ){
			g.DrawSprite( texture, Point( 0, 0), Rect( 0, 0, 720, 480 ), Color( 0xff, 0xff, 0xff ) );
			g.End();
		}
	}
	void	Release(){
		texture.Release();
	}
public:
	Texture	texture;
};
int no = 0;
int main(){
	Windows windows;
	HWND hwnd = windows.CreateSimPleWindow();
	Graphics g;
	g.Init( hwnd );
	Input input;	
	Field field( g );
	Scene *scene = new Title;
	scene->Init( g );
	while( DoEvents() ){
		g.Clear();
		input.Update();			//キーの更新
		KeyboardState key = input.GetKeyboard();		//キーの情報を取得
		//キー入力でプレイ画面に行く
		if( no == 0 ){				//タイトル画面
			if( key.Just( Key::A ) ){		
				delete scene;
				no = 1;
				scene = new Field( g );
				scene->Init( g );
			}
			scene->Update( );
			scene->Draw( g );

		}
		//プレイ画面
		if( no == 1 ){
			field.KeyUpdate( &field, key );
			field.Update(  );
			field.Draw( g );	
		}
		g.Update();

	}
	scene->Release();
	g.Release();
}


bool DoEvents()
{
    MSG msg;
    for(;;)
    {
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            if( msg.message == WM_QUIT )return false;

            TranslateMessage( &msg );
            DispatchMessage( &msg );        //ウィンドウプロシージャの呼び出し
        }
        else
        {
            return true;
        }
    }
	return false;
}


dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: シーン分け 継承について

#10

投稿記事 by dic » 9年前

何もしない処理を追加して共通化するのはどうでしょうか?
下のようなコードになります

コード:

#include <stdio.h>

class	Title	:	public	Scene {
public:
	...
		...

	void	KeyUpdate( Field *field,KeyboardState &key);
	...
		...
};

void	Title::KeyUpdate( Field *field,KeyboardState &key)
{
	//	何もしない
}


...
	...
	if( no == 0 ){
		if( key.Just( Key::A ){
			delete scene;
			no = 1;
			scene = new Field( g );
			scene->Init( g );
		}
		scene->KeyUpdate( &field, key ); // 上の何もしない関数を追加
		scene->Update();
		scene->Draw( g );

	}
	//	プレイ画面
	if( no == 1 ){
		field.KeyUpdate( &field, key );
		field.Update( );
		field.Draw( g );
	}
	g.Update();

しひ

Re: シーン分け 継承について

#11

投稿記事 by しひ » 9年前

不思議さんは側溝にでも捨てておいて。
一口にシーン遷移といってもその実装の仕方は大量にあります。
一例として、自分の考えた実装を書いておきます。

コード:

// 全てシーンの基底クラス
class Scene
{
public:
	Scene(){}
	virtual ~Scene()
	{
		/*ゲーム全体の終了処理*/
	}
	virtual Scene* Update() = 0;
	virtual void Draw() = 0;

private:
	// 全てのシーンで使うリソース
	static Window window;
	static Graphic g;
	static Input input;
};

// ゲームを初期化するシーン
class Init : public Scene
{
public:
	Init()
	{
		/*ゲーム全体の初期化処理*/
	}
	Scene* Update()
	{
		return new Title(); // 初期化が終わったらタイトルへ
	}
}

// タイトルのシーン
class Title : public Scene
{
public:
	Title(){}
	~Title(){}
	Scene* Update()
	{
		input.update();
		if( /*何か押した*/ ) return new Game(); // 何か押したらゲームへ
		return this;
	}
	void Draw(){}
};

// ゲーム?のシーン
class Field : public Scene
{
public:
	Field(){}
	~Field(){}
	void get(){}
	Scene* Update()
	{
		input.update();
		if( /*何か押した*/ ) block.turn( this );
		return this;
	}
	void Draw(){}
private:
	// ここでしか使わないリソース
	Block block;
};

int main()
{
	std::unique_ptr<Scene> scene( new Scene() );
	
	while( /*ゲームが終わるまで*/ )
	{
		Scene* next( scene.update() );
		scene.draw();
		
		// ポインタが異なっていたら(違うシーンに移っていたら)シーンを更新する
		if( next != scene.get() ) scene.reset( next );
	}
}
せっかく継承を使うんですから変数noなんて使わないで下さいな。
それと、上のコードはコンパイルしてないのでかなり怪しいです。あくまでも参考程度にして下さい。
シーン遷移の実装に正解はないので自分の良いと思う実装を模索してみて下さい。

c++勉強中

Re: シーン分け 継承について

#12

投稿記事 by c++勉強中 » 9年前

回答してくださった方々ありがとうございます。
とても参考になりました。本当にありがとうございます。

閉鎖

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