やっとオリジナリティのあるコードがでてきそうです…。
陣形、すなわちユニットの整列です。
これは思うほど単純なものではありませんでした。
なぜなら、並べるユニットの数によって、つくる陣形を変形する必要があるからです。
つまり、妙なほど横に長かったり、縦に長かったりしないよう、
適度な長方形になるよう、縦列(行)と横列の個数を決める必要があります。
今回のきめかたは次のようにします。
縦列の個数を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]
これで、適当な形の長方形になると思います。
コード:
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; }
};
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);
}
}
どんどん左右上下へと成長させていく感じです。
今は実装しませんが、障害物に重なることを考慮して、
陣形の形を変える処理も実装予定です。
(そのため、このような計算方法になっています)
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でも、
人間間の戦争ではなかったり、柔らかい表現のゲームにするか…。
後者のほうが求められている気がしなくもないのですが。