大部分即时战略游戏中使用的简单的碰撞判断实际上是将每一个个体看作一个球体(2D中是圆),再进行简单的球体碰撞检测,而不在意这样简单的判断是否能够满足游戏对于碰撞的要求。这样做确实有利于提升性能,即使一个游戏要进行非常复杂的碰撞判断--例如判断击出的拳头是否击中敌人,或者甚至是低精度的多边形(polygon to polygon)交叉判断,这时为可能出现的碰撞保有一个球体区域往往也能够提升程序的性能。
//Returns the ID for this group instance.
int getID( void ) const { return(mID); }
//Various get and set functions. Type designates the type of the group
//(and is thus game specific). Centroid, maxSpeed, and commander are
//obvious. FormationID is the id lookup for any formation attached to
//the group (will be some sentinel value if not set).
int getType( void ) const
{
return(mType);
}
void setType( int v )
{
mType=v;
}
BVector& getCentroid( void ) const
{
return(mCentroid);
}
float getMaxSpeed( void ) const
{
return(mMaxSpeed);
}
int getCommanderID( void ) const
{
return(mCommanderID);
}
BOOL getFormationID( void ) const
{
return(mFormationID);
}
BOOL setFormationID( int fID );
//Standard update and render functions. Update generates all of the
//decision making within the group. Render is here for graphical
//debugging.
BOOL update( void );
BOOL render( BMatrix& viewMatrix );
//Basic unit addition and removal functions.
BOOL addUnit( int unitID );
BOOL removeUnit( int unitID );
int getNumberUnits( void ) const
{
return(mNumberUnits);
}
int getUnit( int index );
protected:
int mID;
int mType;
BVector mCentroid;
float mMaxSpeed;
int mCommanderID;
int mFormationID;
int mNumberUnits;
BVector* mUnitPositions;
BVector* mDesiredPositions;
};
//*********************************************************
// BFormation Class
//*********************************************************
class BFormation
{
public:
//The three formation states.
enum
{
cStateBroken=0,
cStateForming,
cStateFormed
};
BFormation( void );
~BFormation( void );
//Accessors for the formation’s orientation and state. The expectation
//is that BFormation is really a data storage class; BGroup drives the
//state by calling the set method as needed.
BVector& getOrientation( void )
{
return(mOrientation);
}
void setOrientation( BVector& v )
{
mOrientation=v;
}
int getState( void ) const
{
return(mState);
}
void setState( int v )
{
mState=v;
}
//The unit management functions. These all return information for the
//canonical definition of the formation. It would probably be a good
//idea to package the unit information into a class itself.
BOOL setUnits( int num, BVector* pos, BVector* ori, int* types );
int getNumberUnits( void ) const
{
return(mNumberUnits);
}
BVector& getUnitPosition( int index );
BVector& getUnitOrientation( int index );
int getUnitType( int index );
protected:
BVector mOrientation;
int mState;
int mNumberUnits;
BVector* mPositions;
BVector* mOrientations;
int* mTypes;
};
缩放个体间距(Scaling unit positions).由于编队中的预定位置都是由矢量进行定义的,因此我们可以很方便的对整个编队的间距进行放缩以使它变得更小,这就使得编队能够通过城墙或树林中更小的缝隙(见图14)。这种方法对于那些排列得较为分散的编队很有效,但对于那些排列紧凑的编队就没有什么用处了。
二分和重组(Halving and rejoining).虽然简单的回避能够工作的很好,但是会降低玩家对整个编队穿越地图的感觉,相对来说二分法可以很好的保持住编队所带来的视觉冲击。当我们的编队在前方遇到一个障碍物时我们可以找出编队中的一个拆分点,从该点将编队一分为二,这两个编队分别通过障碍物之后再前进到重组位置恢复成一个编队(见图16)。这种方法只增加很少的计算量,但却能为编队移动带来良好的视觉效果。