遊戲中地圖中需要設置不同的區域,尤其對於大型網絡遊戲,到達不同的區域通常需要提示本區域名稱。
本節主要討論一種遊戲區域信息的管理方法:
實現步驟
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;
}
}