游戏中地图中需要设置不同的区域,尤其对于大型网络游戏,到达不同的区域通常需要提示本区域名称。
本节主要讨论一种游戏区域信息的管理方法:
实现步骤
1.首先对区域进行边界的描边,获取区域的顶点描边信息
2. 对存储有区域以及区域描边信息的地图,进行信息归纳,形成稀疏矩阵存储, 其中X再加入区域ID信息
区域信息:
struct SMapAreaInfo
{
typedef vector<POINT> Polygon;
size_t nAreaID; // area map ID
size_t nFatherMapID; // father ID, a nearest area which contain it
// tchar szAreaName[32]; // Area name
tstring szAreaName;
RECT areaMapRect; //area Rect
Polygon points; //edge points
};
地图信息: MapQueryInfo 即是 稀疏矩阵,每行表示Y这行的边界点以及该边界点的区域ID; 包含有本地图中所有的区域,用List 存储起来
struct SMapStateInfo
{
struct QueryItem{
short tile;
size_t areaid ;
};
typedef vector<QueryItem> MapLine;
typedef vector<MapLine> MapQueryInfo;
typedef std::vector<size_t> StateAreaList;
size_t nStateID; //state ID, key to a map that should be showed independent
StateAreaList nStateAreaInfo;
MapQueryInfo QueryVertex; // query map information
};
typedef std::map<size_t,SMapAreaInfo> TMAP_AREAINFO; //map of SMapAreaInfo list
typedef map<size_t, SMapStateInfo> TMAP_MAPSTATE; //map of SMapStateInfo list map
3.判断区域所属哪个区域
主要思想即: 查询每张地图的稀疏矩阵(即含有区域ID的边界顶点信息),如果X大于最近的边界,则在这个区域之中。
/**get Title's area ID
* @ param x,y: is title
* @ param nStateId: the title in map ID
* @ return : title's area ID
*/
size_t CTerrainMapArea::GetTerrainAreaID(size_t nStateID, int x, int y)const
{
//case 1 title or stateID is error return 0
if(x<0 || y<0 || nStateID <=0)
return 0;
//case 2: title is not in map of nStateID return 0
RECT rc;
if(GetBoundingBox(nStateID,rc))
{
// for safety consideration, y = limitation should be deleted,
// as it may be a vertex point that not in linenum
if(x<rc.left || x > rc.right || y<=rc.top || y >= rc.bottom)
return 0;
}
TMAP_MAPSTATE::const_iterator it = m_mapTerrainMapState.find(nStateID);
if (it == m_mapTerrainMapState.end())
return 0;
// put in case 2
SMapStateInfo::MapLine const & line = it->second.QueryVertex[y];
size_t index = 0;
//case x <min( line[].titles) or x > max(line.titles) is out of consideration
while(x > line[index].tile ){
index++;
}
if(/*stackArearId.size() >0*/ index >0){
//return stackArearId.top();
return line[index - 1].areaid;
}
else{
return 0;
}
}