RTS製作日記。その5

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

RTS製作日記。その5

投稿記事 by MNS » 14年前

まず、メッセージのクラスを作ります。

CODE:

class	Message
{
public:

	//送信者のID
	int		m_Sender;

	//受信者のID
	int		m_Receiver;

	//メッセージの種類
	ORDERS	m_Order;

	//付属情報(なんでも)
	void*	m_Info;

	Message(int sender,
			int receiver,
			ORDERS order,
			void* info)

			:m_Sender(sender),
			 m_Receiver(receiver),
			 m_Order(order),
			 m_Info(info)
	{}
};
メッセージに、命令と付属の情報を持たせて送信します。
命令はORDERSという列挙体で宣言された定数で、
この命令を元に、処理を決めます。

CODE:

enum	ORDERS
{
	GO_AHEAD
};
現在は前進(GoAhead)のみ宣言されています。

付属情報はvoid*型で、あらゆる型のポインタを記録できます。
必要に応じて型変換をし、使用します。


次に、受信する側の構造を作ります。
今のところ、受信はステートで行い、
あらゆるステートで行えるようにします。
よって、Stateクラスに純粋仮想関数として実装します。

CODE:

class	State
{
public:

	…略…

	virtual bool	HandleMesssage(Unit* owner, Message& message) = 0;
};
中身を実装する前に、送信する構造を作ります。
クラスにしようと思いもしたのですが、
今のところは単体の関数で実装します。

CODE:

void	SendMsg(Message msg)
{
	//受信者のポインタを得る
	Unit*	receiver = UnitManager::Instance().GetUnit(msg.m_Receiver);

	
	//--送信の処理--

	//まず、現在のステートに送信する
	if(receiver->CurrentState()
		&& receiver->CurrentState()->HandleMesssage(receiver, msg))
	return;

	//送信出来なかった場合は、グローバルステートに送信する
	if(receiver->GlobalState()
		&& receiver->GlobalState()->HandleMesssage(receiver, msg))
	return;
}
メッセージの送信は現在のステートの方が優先され、
送れなかった場合(戻り値としてfalseが返ってきた場合)
グローバルステートに送信します。


すべてユニットは、あらゆる状況下においても、
プレイヤーの指示を最優先にする必要があります。
よって、それらの処理はすべてグローバルステートに実装します。

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);
		//ステートを変更
		owner->ChangeState(new STATE_GoAhead);
		return true;
	}
	return false;
}
最後に、MyPlayer::Updateに、右クリックされた時の処理を実装します。

CODE:

void	MyPlayer::Update()
{
	
	…省略…
	
	//右クリックが行われたら
	if(m_bRightClick)
	{
		//全選択ユニットの平均位置を得る
		Vec2D	APos;
		int		count = 0;
		std::list::iterator it;
		for(it = m_SelectedUnitList.begin();
			it != m_SelectedUnitList.end(); ++it)
		{
			APos += (*it)->Pos();
			++count;
		}

		APos /= count;

		//選択ユニット全員に移動命令を送る
		for(it = m_SelectedUnitList.begin();
			it != m_SelectedUnitList.end(); ++it)
		{
			//座標はマウスでクリックした位置と、
			//自身の位置と全選択ユニットの平均位置との差分を考える
			Vec2D TPos = m_MousePos - (APos - (*it)->Pos());
			Message msg(-1,//送信者なし
						(*it)->ID(),
						GO_AHEAD,
						&TPos);

			SendMsg(msg);
		}
	}
}
ユニットは、ユニット同士の距離を維持したまま移動します。
これはあとで陣形という概念を導入したときに再び改良しようと思っています。

これで、ユニットの選択およびその移動が実装できました。
ここまでほぼ殴り書きなので、次はまとめようと思います。

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