パズルのピースハマった!

taketoshi
記事: 222
登録日時: 14年前
住所: 日本国

パズルのピースハマった!

投稿記事 by taketoshi » 11年前

オブジェクト脳。略してオブ脳を構築するべく。
今更オブジェクト指向について勉強していました。

ずーーーっと、よそのオブジェクトが持つ変数の書き換えに、
そのオブジェクトの参照を丸ごと渡すという暴挙を行っていたのです

継承と多態性まで理解していたんですが、他のクラスへのアクセス方法を理解していなかったので悩みました。
しかしここのサイトでインターフェイスクラスを学んでいてオブジェクト指向のピースが脳内でガチガチとハマりはじめました。
凄いかもオブジェクト指向。すごいぞオブ脳。

之も知らずに会社のシステムとかSRPGとか作ってたノカァ・・・。
順番まるっきり違うなぁ。と思う今日この頃。

備忘録でメモメモ。

CODE:

// インターフェイス3.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

typedef struct{
	int x,y;
}pos;

class map;
class charcter;


//例:マップに属する変数を書き換える
class IMapBelongWrite{
public:
	virtual void MapWrite(pos temp) = 0;
};


//マップ変数を書き換えるインターフェイスを継承したmapクラスを作る
class map : public IMapBelongWrite{
private:
	pos nBelong;//書き換えるターゲット
public:
	void MapWrite(pos temp) override{
		nBelong.x = temp.x;
		nBelong.y = temp.y;
	}

	void show(){
		printf("x = %d , y = %d\n",nBelong.x,nBelong.y);
	}


};

class charcter{
	//インターフェイスクラスへの参照を持つ
	IMapBelongWrite *lpMapInter;
public:
	void setchar(){
		pos temp;
		temp.x = 100;
		temp.y = 200;
		lpMapInter->MapWrite(temp);
	}

	//コンストラクタ
	charcter();
	charcter(map *lpmap){lpMapInter = lpmap;}
};

//ステージクラス
class Stage{
private:
	map *lpMap;
	charcter *lpChar;
public:

	//コンストラクタでインスタンス作る
	Stage(){
		lpMap = new map();
		lpChar = new charcter(lpMap);
	}
	~stage(){
		delete lpMap;
		delete lpChar;
	}

	void updata(){

		//mapインスタンスの変数書き換え
		lpChar->setchar();

		//確認
		lpMap->show();
		
	}
};



int _tmain(int argc, _TCHAR* argv[])
{

	Stage *lpStage = new Stage();

	lpStage->updata();

	delete lpStage;

	return 0;
}

最後に編集したユーザー taketoshi on 2014年2月07日(金) 23:46 [ 編集 1 回目 ]

ISLe
記事: 2650
登録日時: 14年前

Re: パズルのピースハマった!

投稿記事 by ISLe » 11年前

わたしは多態性を持つオブジェクトを包含はしないですね。
そのコードだとマップにキャラクタを複数表示するためにコードを変更しなければいけません。

オブジェクトが持つのはインターフェースとして機能するオブジェクト(へのポインタ)で、オブジェクト同士はインターフェースとして機能するオブジェクトを通して繋がるようにします。
ゲームの仕様を満たすシンプルなインターフェースを考えるのがゲームプログラミングの核です。

わたしならあとからキャラクタマネージャを入れてもマップクラスは一切変更しなくても良いようにします。
キャラクタ側の変化でマップが複雑になる、というのはマップとキャラクタできちんと振る舞いを区別できていないからだと思います。


インターフェースの階層というのは、例えばユーザー操作を記録するクラスはこんな感じです。

CODE:

class CInputRecorder : public CInputTask
{
private:
    CInputTask *cp; // コンストラクタ等で受け取る
public:
    // cpの指すCInputTaskの戻り値を記録しながらそのまま返す
};
わたしならもっとシンプルにするためにキーボードとパッドをもっと低レベルな部分で抽象化します。

上に書いたキャラクタとキャラクタマネージャの差し替えとかも同じようにしてサクッとできます。
最後に編集したユーザー ISLe on 2014年2月11日(火) 22:05 [ 編集 3 回目 ]

taketoshi
記事: 222
登録日時: 14年前
住所: 日本国

RE: パズルのピースハマった!

投稿記事 by taketoshi » 11年前

>>ISLeどの

>オブジェクトが持つのはインターフェースとして機能するオブジェクト(へのポインタ)で、オブジェクト同士はインターフェースとして機能するオブジェクトを通して繋がるようにします。
>ゲームの仕様を満たすシンプルなインターフェースを考えるのがゲームプログラミングの核です。

ここの言葉を読み取って、オブジェクト同士をインターフェイスへのポインタでリンクさせてみました。
キャラクタークラスからはインターフェイスに位置情報を伝え、マップクラスからは必要な時にインターフェイスクラスから引き出します。
随分と見通しが良くなってスマートになった感じがいたします。こんな感じの使い方でしょうか?
► スポイラーを表示
>>インターフェースの階層というのは、例えばユーザー操作を記録するクラスはこんな感じです
サンプルご提示ありがとうございます。
こちらは思考する時間が取れなかったので、改めて考えます。

ISLe
記事: 2650
登録日時: 14年前

RE: パズルのピースハマった!

投稿記事 by ISLe » 11年前

taketoshi さんが書きました:随分と見通しが良くなってスマートになった感じがいたします。こんな感じの使い方でしょうか?
まだオブジェクト同士の結びつきが強いように感じます。
わたしの案はマネージャ的な上位オブジェクトの存在を前提としているので最低限のコードでもけっこうな規模になります。
具体的なものを簡単に説明するのはちと無理なので、いろいろ実践する中で思い出していただければ良いかと思います。


インターフェースの階層は、デザインパターンでいうところのファサードパターンですね。
最後に編集したユーザー ISLe on 2014年2月13日(木) 01:04 [ 編集 1 回目 ]