RTS製作日記。その14

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

RTS製作日記。その14

投稿記事 by MNS » 14年前

*陣形をつくる

やっとオリジナリティのあるコードがでてきそうです…。

陣形、すなわちユニットの整列です。
これは思うほど単純なものではありませんでした。
なぜなら、並べるユニットの数によって、つくる陣形を変形する必要があるからです。

つまり、妙なほど横に長かったり、縦に長かったりしないよう、
適度な長方形になるよう、縦列(行)と横列の個数を決める必要があります。

今回のきめかたは次のようにします。
縦列の個数をYとすると、横列の(最大)個数Xは、
X = 4×2Y-1
ということにします。(等比数列かな?)

[table=border:1px solid #cccccc;][tr=text-align:center;]
[td=border:2px solid #cccccc;]縦[/td]
[td=border:1px solid #cccccc; width:20px;]1[/td]
[td=border:1px solid #cccccc; width:20px;]2[/td]
[td=border:1px solid #cccccc; width:20px;]3[/td]
[td=border:1px solid #cccccc; width:20px;]4[/td]
[td=border:1px solid #cccccc; width:20px;]5[/td]
[/tr]
[tr=text-align:center;]
[td=border:2px solid #cccccc;]横[/td]
[td=border:1px solid #cccccc; width:20px;]4 [/td]
[td=border:1px solid #cccccc; width:20px;]8 [/td]
[td=border:1px solid #cccccc; width:20px;]16[/td]
[td=border:1px solid #cccccc; width:20px;]32[/td]
[td=border:1px solid #cccccc; width:20px;]64[/td]
[/tr]
[tr=text-align:center;]
[td=border:1px solid #cccccc;]総数[/td]
[td=border:1px solid #cccccc; width:20px;]4[/td]
[td=border:1px solid #cccccc; width:20px;]16[/td]
[td=border:1px solid #cccccc; width:20px;]48[/td]
[td=border:1px solid #cccccc; width:20px;]124[/td]
[td=border:1px solid #cccccc; width:20px;]320[/td]
[/tr][/table]

これで、適当な形の長方形になると思います。

コード:

CODE:

class	FormationMaker
{

	//この陣形を構成するユニットの人数
	int		m_Numbers;

	//陣形の起点となる座標
	Vec2D	m_Center;

	//陣形―座標のリスト
	std::vector	m_Formation;

	
	//横列の基本ユニット数
	const	int	  BasicRank;
	//縦、横の間隔
	int		SpaceX;
	int		SpaceY;


public:

	FormationMaker(int numbers,
				   Vec2D center)
		:m_Numbers(numbers),
		 m_Center(center),
		 BasicRank(4),
		 SpaceX(20),
		 SpaceY(20)
	{
		Make();
	}


	//陣形の座標を計算する
	void	Make();


	//縦の列に並べる
	void	ArrayFile(double X,
					  int num);


	std::vector	GetFormation(){ return m_Formation; }
};

CODE:

void	FormationMaker::Make()
{
	//横列単位のキュー(X座標)
	std::queue rank;

	//縦の列の個数を計算
	int FNum = 1;
	int count = BasicRank;
	while(count = m_Numbers)
		{
			break;
		}
		ArrayFile(L, FNum);
		//キューに積む
		rank.push(R);
		rank.push(L);
	}
}


void	FormationMaker::ArrayFile(double X, int num)
{
	//縦列単位のキュー
	std::queue file;

	//真ん中に配置(便宜上二つ)
	file.push(Vec2D(X, m_Center.y));
	file.push(Vec2D(X, m_Center.y));
	//ひとつだけ追加
	m_Formation.push_back(Vec2D(X, m_Center.y));
	for(int i = 1+2; i  m_Numbers)
		{
			return;
		}
		//列を取り出す、一方は上方向に伸び、
		//もう一方は下方向に伸びる。
		Vec2D A = file.front(); file.pop();
		Vec2D B = file.front(); file.pop();
		//加える方向を決める
		Vec2D newA, newB;
		//-上、下に伸ばす
		newA = A + Vec2D(0,SpaceY);
		newB = B + Vec2D(0,-SpaceY);
		//陣形の加える
		m_Formation.push_back(newA);
		//要素は+2追加していくため、
		//途中で個数を超える場合があるのを考慮
		if(i>=num) return;
		m_Formation.push_back(newB);
		//キューに積む
		file.push(newA);
		file.push(newB);
	}
}
イメージとしては、クリックした地点から、
どんどん左右上下へと成長させていく感じです。
今は実装しませんが、障害物に重なることを考慮して、
陣形の形を変える処理も実装予定です。
(そのため、このような計算方法になっています)

CODE:

void	MyPlayer::Update()
{

	…略…

	//右クリックが行われたら&選択ユニットがいれば
	if(m_bRightClick && LClickCounter == 0
		&& !m_SelectedUnitList.empty())
	{
		//カウンターを起動。
		LClickCounter = 20;

		//陣形を作る
		FormationMaker fm(m_SelectedUnitList.size(),
						  m_MousePos);
		
		//座標を取得
		std::vector formation = fm.GetFormation();
		int count = 0;

		std::list::iterator it;
		//選択ユニット全員に移動命令を送る
		for(it = m_SelectedUnitList.begin();
			it != m_SelectedUnitList.end(); ++it)
		{
			//前から順に割り当てていく
			Vec2D TPos = formation.at(count++);
			Message msg(-1,//送信者なし
						(*it)->ID(),
						GO_AHEAD,
						&TPos);

			SendMsg(msg);
		}
	}				
}
クリックしたときの処理です。
選択ユニットを前から順に割り当てていきます。


ゲーム映像:
[youtube][/youtube]


さて、陣形の実装が終わって、
次は経路探索の高速化か時分割、もしくは”戦い”の実装をするか…

それよりも、ゲームのコンセプトを固めなければいけませんね。
なんというか、みるからに”戦争”を模すのか、
それとも「ピクミン」のように、システムはRTSでも、
人間間の戦争ではなかったり、柔らかい表現のゲームにするか…。
後者のほうが求められている気がしなくもないのですが。

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