Chinaunix首页 | 论坛 | 博客
  • 博客访问: 375200
  • 博文数量: 37
  • 博客积分: 6000
  • 博客等级: 准将
  • 技术积分: 1266
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-16 19:52
文章分类

全部博文(37)

文章存档

2011年(1)

2010年(7)

2009年(12)

2008年(17)

我的朋友

分类: C/C++

2009-09-13 00:54:43

 
Wow世界中的地图有两种:场景地图和副本地图.
              场景地图只有一个实体,一般比较大。如东部王国、卡里姆多和外域分别是一个整张的地图(各个地图间传送的港口也是单独的地图)。
              副本地图是同样的地图场景,但却有多个不同的实体。比如各种副本和战场,都属于副本地图。
InstanceMgr:将负责整个世界的地图创建和保持。每个地图(以及每个副本)将以MapMgr的形式创建,MapMgr主要负责地图中玩家和npc怪物的逻辑管理和运算。世界地图的MapMgr放在m_singleMaps中,副本的MapMgr则在每个Instance:: m_mapMgr中(也就是说每个副本都会有一个MapMgr,但是当没有副本存在时也不会有副本的MapMgr。而世界地图则固定有一个MapMgr)。 Map中的_terrain则加载了地图文件中的地形信息,包括水体深度和地面高度信息等。而Map也将主要负责地图信息和地形信息的管理。下面分别描述:
注:如上图,MapMgr派生自CThread,也就是说每个地图和副本都会有一个线程。这样使不同的地图的运算分离,也能充分利用多cpu的性能,但是当用户量大的时候可能会产生大量的线程,不太确定这种方法的优劣。不过如果线程在可以承受的范围内的话,这样也可以避免一个玩家操作卡时导致整个服务器都卡的情况,至多也就是当前地图副本的玩家卡。
    MapMgr:
              MapMgr派生自CThread和CellHandler,在创建时会加入到线程池中运行,当终止线程时,MapMgr会删除自己释放内存。父类CellHandler是个模板类,把地图分为多个单元格MapCell,将地图上的npc和玩家划分为多个小子集分别处理.当当前单元格和相邻的单元个都没有玩家的时候,会将单元格设置一个
延迟unload事件:
sEventMgr.AddEvent(_mapmgr, &MapMgr::UnloadCell,(uint32)_x,(uint32)_y,MAKE_CELL_EVENT(_x,_y),sWorld.map_unload_time * 1000,1,0);
在一定时间后如果还没有玩家进入就unload该单元格以及其中的npc,以节省资源。
              MapMgr则在Do函数(实际上是运行在run()函数执行线程中)中循环调用_PerformObjectDuties()函数,以间隔时间刷新该地图中所有对象(npc,宠物,玩家,gameObject,session等)的状态和逻辑运算。
      Map:
              成员TerrainMgr同样将地图的地形分为单元格(成员CellInformation),实现了地形的动态加载和卸载(这个与MapCell的加载和卸载是一起的,但是没有设置延时,是立即释放的。当玩家在两个格子间频繁切换时会影响性能。)
         Map本身则负责了怪物刷新点(spawns)的载入和维护管理。
      InstanceMgr:
         InstanceMgr初始化时将为每一个地图创建一个Map,为每一个非副本地图创建一个MapMgr:
void InstanceMgr::_CreateMap(uint32 mapid)
{
     if( mapid >= NUM_MAPS )
         return;
     MapInfo * inf;
     inf = WorldMapInfoStorage.LookupEntry(mapid);
     if(inf==NULL)
         return;
     if(m_maps[mapid]!=NULL)
         return;
     //初始化一个map,并将指针放入数组
     m_maps[mapid] = new Map(mapid, inf);
     if(inf->type == INSTANCE_NULL)
     {
         //如果不是副本地图则创建世界地图副本(实际的实现是为其创建一个MapMgr并放入线程池执行)
         _CreateInstance(mapid, GenerateInstanceID());
     }
}
副本的MapMgr将在创建副本对象时动态创建,
//跟创建世界地图副本的函数是不同的两个重载函数
MapMgr * InstanceMgr::_CreateInstance(Instance * in)
{
     in->m_mapMgr = new MapMgr(m_maps[in->m_mapId], in->m_mapId, in->m_instanceId);
     in->m_mapMgr->pInstance = in;
     in->m_mapMgr->iInstanceMode = in->m_difficulty;
     in->m_mapMgr->InactiveMoveTime = 60+UNIXTIME;
     ThreadPool.ExecuteTask(in->m_mapMgr);
     return in->m_mapMgr;
}
         Instance的创建在InstanceMgr::GetInstance(Object* obj)时动态创建,当instance绑定到一个MapMgr以后,就以MapMgr的形式单独运行,直到_DeleteInstance时,将设置MapMgr终止线程。
阅读(818) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~