RTS製作日記。その9

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

RTS製作日記。その9

投稿記事 by MNS » 14年前

*経路探索 - ”経路”と”経路をたどる動き”

ターゲットへ障害物へ移動するには、ターゲットを避けた経路を計算し、
その経路に辿って動く必要があります。
前回作ったグラフが、その経路の指標となるものですが、
経路は別のものとして作ります。
加えて、経路を辿る行動を実装します。
実際に障害物を避けてターゲットへ移動する動きを実装するのは、
おそらく次くらいになると思います。

・経路クラス

CODE:

class	Path
{
	std::list			m_Path;
	
	//たどるのに便利
	std::list::iterator	m_PathItr;

public:

	Path(){}


	//次のターゲットに移る
	void	SetNext(){ ++m_PathItr; }
	//経路が終了していないか
	bool	ifFinish(){ return (m_PathItr == m_Path.end()); }

	//ターゲットの座標を取得
	Vec2D	GetCurrentTarget(){ return *m_PathItr; }


	//アクセサ
	void	SetPath(std::list& path)
	{
		m_Path = path;
		m_PathItr = m_Path.begin();
	}
};
まあ単純ですね。

つぎに、”経路を計算する”クラスを簡単に作ります。
あくまで試験的なもので、実際にターゲットへの経路を計算する機能はつけません。

CODE:

class	PathFinder
{


	//各ユニットが独自のものをもつ
	Unit*	m_pUnit;

	//グラフへのポインタ
	Graph*	m_pGraph;


public:

	PathFinder(Unit* unit, Graph* graph)
		:m_pUnit(unit), m_pGraph(graph)
	{}



	//成功=true、失敗=false
	bool	GetShortestPath(Vec2D target,
							std::list& path/*これに経路を記録*/);

};

CODE:

bool	PathFinder::GetShortestPath(Vec2D target,
									std::list& path)
{
	path.push_back( Vec2D(100,400) );
	path.push_back( Vec2D(200,300) );
	path.push_back( Vec2D(300,400) );
	path.push_back( target );
	return true;
}
デタラメな経路(ただし最終的にはターゲットへ行く)を計算し、返します。


次に、経路を辿る行動を実装します。
行動ですから、MotionManagerの関数です。

CODE:

//経路探索において、中継点と十分近づいたと判断する数値
const double FOLLOW_PATH_MIN_DIST = 4.0;
Vec2D	MotionManager::FollowPath()
{
	if(m_Path->ifFinish()) return Vec2D();

	Vec2D dist = m_Path->GetCurrentTarget() - m_pUnit->Pos();
	if(dist.LengthSQ() SetNext();
	}

	if(!m_Path->ifFinish())
		//中継点へ向かう
		return Go(m_Path->GetCurrentTarget());
	else
		return Vec2D();
}
これも割と単純ですね。


あとは、クリックした際に、直接そこへ向かっていたのを、
経路を計算して、その経路を辿るようにします。
これは、ステートマシーンを弄る必要があります。

CODE:

bool	STATE_Global::HandleMesssage(Unit* owner, Message& message)
{
	switch(message.m_Order)
	{
	case	GO_AHEAD:
		//座標を得る
		Vec2D*	target = (Vec2D*)message.m_Info;
		//ターゲットを設定
		owner->getMotionManager()->SetTarget(*target);

		//ターゲットまでの経路を求める
		std::list path;
		owner->getPathFinder()->GetShortestPath(*target, path);
		owner->getMotionManager()->SetPath(path);

		//ステートを変更
		owner->ChangeState(new STATE_GoAhead);
		return true;
	}
	return false;
}
移動命令を受けた際に、移動先へ経路を計算するようにします。

次に、移動する関数を、経路を辿って移動するようにします。
これは簡単で、さっきの”FollowPath”の行動をOnにするだけです。

CODE:

void	STATE_GoAhead::Enter(Unit* owner)
{
//	owner->getMotionManager()->flag_Go.ON();
	owner->getMotionManager()->flag_FollowPath.ON();
	//ユニットの行動を止める。
	owner->Stop();
}
これで、経路を辿って移動する行動ができました。

ゲーム画面:
[youtube][/youtube]
最後に編集したユーザー MNS on 2011年2月04日(金) 15:35 [ 編集 1 回目 ]

コメントはまだありません。