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という列挙体で宣言された定数で、
この命令を元に、処理を決めます。 現在は前進(GoAhead)のみ宣言されています。
付属情報はvoid*型で、あらゆる型のポインタを記録できます。
必要に応じて型変換をし、使用します。
次に、受信する側の構造を作ります。
今のところ、受信はステートで行い、
あらゆるステートで行えるようにします。
よって、Stateクラスに純粋仮想関数として実装します。 中身を実装する前に、送信する構造を作ります。
クラスにしようと思いもしたのですが、
今のところは単体の関数で実装します。
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が返ってきた場合)
グローバルステートに送信します。
すべてユニットは、あらゆる状況下においても、
プレイヤーの指示を最優先にする必要があります。
よって、それらの処理はすべてグローバルステートに実装します。
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;
}
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);
}
}
}
これはあとで陣形という概念を導入したときに再び改良しようと思っています。
これで、ユニットの選択およびその移動が実装できました。
ここまでほぼ殴り書きなので、次はまとめようと思います。