ページ 11

再帰呼び出しについて

Posted: 2011年12月29日(木) 16:27
by ぱにしん
こんにちは。
私は今Dixqさんの龍神録の書き方を真似してSRPGを作成しています。
キャラクターの移動範囲を求める関数を作っているのですが、再起でマップチップのリストをそのまま呼び出しているせいなのか、非常に処理が重くなりました。
このままではゲームにならないので何とかしたいのですが、リストを呼ばないことには移動コストなどが取得出来ないのでどうにも出来ず困っています。

基本的に同じものなので一回呼べばそれで済むと思うのですが、一回呼んでそれを使い回すことは出来ないのでしょうか。
解答をよろしくお願いします。

コード:

bool CPlayer::CanMoveOrNot(int x,int y,int MoveP,int di,char MovingPath){	
	//マップチップのリスト取得
	list<CMapTip*> ListOfMapTip;
	CFacade::Inst()->GetListOfMapTip(ListOfMapTip);
	//マップチップのリスト分ループ
	for(list<CMapTip*>::iterator it=ListOfMapTip.begin();it!=ListOfMapTip.end();it++){
		if((*it)->Position.x==x && (*it)->Position.y==y){
			if(MoveP<(*it)->MoveCost){return false;}//移動できなかったら終了
			
			(*it)->CanMove=true;
			mvrec[x][y] = MovingPath;
			if(di!=3){CanMoveOrNot(x,y-1,MoveP-(*it)->MoveCost,1,MovingPath+'1');}
			if(di!=4){CanMoveOrNot(x+1,y,MoveP-(*it)->MoveCost,2,MovingPath+'2');}
			if(di!=1){CanMoveOrNot(x,y+1,MoveP-(*it)->MoveCost,3,MovingPath+'3');}
			if(di!=2){CanMoveOrNot(x-1,y,MoveP-(*it)->MoveCost,4,MovingPath+'4');}
			return true;

		}
	}
}

void CPlayer::MoveAreaSearch(){
	int X = Position.x, Y = Position.y;
	int MoveP = JobData.MoveP;

	CanMoveOrNot(X,Y,MoveP,1,'1');
	CanMoveOrNot(X,Y,MoveP,2,'2');
	CanMoveOrNot(X,Y,MoveP,3,'3');
	CanMoveOrNot(X,Y,MoveP,4,'4');
}

開発環境
Windows7
Mictrosoft VisualC++2010 HomeEdition
DXライブラリ
今の知識はゲームプログラミングの館を読んだ程度です。
参考にしたサイトhttp://gumina.sakura.ne.jp/CREATION/OLD ... SESS03.htm

Re: 再帰呼び出しについて

Posted: 2011年12月29日(木) 18:01
by softya(ソフト屋)
リストが必須なのかまでは解析してませんが、参照で引渡していけば毎回リストのインスタンスを作る必要はないと思いますが。

Re: 再帰呼び出しについて

Posted: 2011年12月29日(木) 18:42
by a5ua
関数呼び出し毎に、リストを線形探索して対応する座標のマップチップを取得していますが、
マップチップのリストを

コード:

vector<vector<CMapTip *> > ListOfMapTip; // TipじゃなくてChip?
のように2次元配列で保持すれば、マップチップ自身が座標を保持しなくても、
ListOfMapTip[y][x]->XXXのように、添字で対応する座標のマップチップを取得できると思いますが、どうでしょうか。

Re: 再帰呼び出しについて

Posted: 2011年12月29日(木) 18:58
by ぱにしん
参照を使って早くなりました。ありがとうございます!

まだ場数積んでないというか、あまり使いこなせてるとは言えない状態なのでこれからも初心者っぽい質問するかもしれませんが、その時はまたよろしくお願いします。
まだ1、2秒ぐらい計算に時間かかるんですよね・・・そもそも設計がおかしいのか、無駄な処理しているのか・・・。

とにかくありがとうございました。

Re: 再帰呼び出しについて

Posted: 2011年12月29日(木) 19:05
by ぱにしん
a5ua さんが書きました:関数呼び出し毎に、リストを線形探索して対応する座標のマップチップを取得していますが、
マップチップのリストを

コード:

vector<vector<CMapTip *> > ListOfMapTip; // TipじゃなくてChip?
のように2次元配列で保持すれば、マップチップ自身が座標を保持しなくても、
ListOfMapTip[y][x]->XXXのように、添字で対応する座標のマップチップを取得できると思いますが、どうでしょうか。
そうですね・・・vectorではなくlistで作ってたので添字で要素にアクセス出来なかったのです。
そこも無駄だと思うのでそのように改変してみます。
スペルミス、恥ずかしい限りですorz

Re: 再帰呼び出しについて

Posted: 2011年12月31日(土) 07:53
by beatle
a5ua さんが書きました:関数呼び出し毎に、リストを線形探索して対応する座標のマップチップを取得していますが、
マップチップのリストを

コード:

vector<vector<CMapTip *> > ListOfMapTip; // TipじゃなくてChip?
のように2次元配列で保持すれば、マップチップ自身が座標を保持しなくても、
ListOfMapTip[y][x]->XXXのように、添字で対応する座標のマップチップを取得できると思いますが、どうでしょうか。
std::mapを使うのも手ですね.

コード:

std::map<Point, CMapTip*> map_chips;
map_chips[Point(x, y)]->XXX;

Re: 再帰呼び出しについて

Posted: 2011年12月31日(土) 14:38
by ぱにしん
beatle さんが書きました:
a5ua さんが書きました:関数呼び出し毎に、リストを線形探索して対応する座標のマップチップを取得していますが、
マップチップのリストを

コード:

vector<vector<CMapTip *> > ListOfMapTip; // TipじゃなくてChip?
のように2次元配列で保持すれば、マップチップ自身が座標を保持しなくても、
ListOfMapTip[y][x]->XXXのように、添字で対応する座標のマップチップを取得できると思いますが、どうでしょうか。
std::mapを使うのも手ですね.

コード:

std::map<Point, CMapTip*> map_chips;
map_chips[Point(x, y)]->XXX;
こんなのもあるんですか・・・
まだまだ標準ライブラリとかは勉強不足です。
やはりその辺をしっかり勉強してから組んだ方がいいですね。
とりあえず今組んでるの物を形にしてから勉強しようと思います。ありがとうございました。

Re: 再帰呼び出しについて

Posted: 2011年12月31日(土) 14:59
by softya(ソフト屋)
STLは便利ですが速度を犠牲にする部分もあるので速度を確かめた上に使われると良いと思います。
とくにmapは内部で検索するので遅くなると思います。

Re: 再帰呼び出しについて

Posted: 2012年1月01日(日) 20:39
by ぱにしん
softya(ソフト屋) さんが書きました:STLは便利ですが速度を犠牲にする部分もあるので速度を確かめた上に使われると良いと思います。
とくにmapは内部で検索するので遅くなると思います。
なるほど・・・
先ほどlistをvectorに変えたところvectorの方が若干早いように感じました(気のせいかもしれませんが^^;
種類によっての功罪(?)をよく考えて使えるようにしたいです。