//场景上的物体
struct SceneEntry
{
friend class SceneEntryIndex;
public:
//物体类型
enum SceneEntryType
{
SceneEntry_Player, /**< 玩家*/
SceneEntry_NPC, /**< NPC*/
SceneEntry_Build, /**< 建筑*/
SceneEntry_Object, /**< 地上物品*/
SceneEntry_MAX
};
//物体状态
enum SceneEntryState
{
SceneEntry_Normal, /**< 普通状态 */
SceneEntry_Death, /**< 死亡状态 */
SceneEntry_Hide /**< 隐藏状态 */
};
...
};
class Scene : public SceneEntryIndex
{
public:
enum SceneType
{
STATIC, //静态地图
GANG //副本
};
bool init(DWORD mapid); //初始化地图场景
bool Scene::sendCmdToNine(const zPosI posi, const void *pstrCmd, const int nCmdLen);
...
};
bool Scene::sendCmdToNine(const zPosI posi, const void *pstrCmd, const int nCmdLen)
{
SceneSendToEveryOne sendeveryone(pstrCmd, nCmdLen); //示例,对于每个九屏玩家发送了一个pstrCmd指令
const zPosIVector &pv = getNineScreen(posi);
for(zPosIVector::const_iterator it = pv.begin(); it != pv.end(); it++)
{
execAllOfScreen(zSceneEntry::SceneEntry_Player,*it,sendeveryone);
}
return true;
}
class SceneManager
{
public:
bool init();
Scene * loadScene(Scene::SceneType type, DWORD mapid);
struct MapInfo {
DWORD mapid;
char name[100];
...
}
typedef std::map<DWORD , MapInfo> MapMap;
MapMap map_info; //所有地图信息
};
//场景战斗类,包括场景玩家和npc的战斗
class SceneEntryPk : public SceneEntry
{
public:
Scene *scene; //所在的场景指针
...
};
//场景玩家
class SceneUser : public SceneEntryPk
{
public:
bool changeMap(Scene *newscene,const Pos &pos); //切换地图
bool intoScene(Scene *newscene,bool needInitInfo,const Pos &initPos); //进入地图场景
bool LeaveScene(); //离开场景
void sendMeToNine(); //把自己通知九屏
void sendNineToMe(); //把九屏通知自己
...
};
void SceneUser::sendNineToMe()
{
GetEnvryOneAndSend one(this); //里面实现了一个打包数据的exec
const zPosIVector &pv = scene->getNineScreen(getPosI());
for(zPosIVector::const_iterator it = pv.begin(); it != pv.end(); it++)
{
scene->execAllOfScreen(*it,one);
}
}
typedef DWORD zPosI;
typedef std::vector<zPosI> zPosIVector;
//场景物体屏索引
class SceneEntryIndex
{
protected:
Pos sceneWH; //场景宽和高
DWORD screenMax; //最大屏索引编号
DWORD screenx; //横向多少屏
DWORD screeny; //纵向多少屏
private:
typedef std::set<SceneEntry *> SceneEntry_SET;
typedef std::map<zPosI, SceneEntry_SET> PosIMapIndex;
PosIMapIndex index[SceneEntry::SceneEntry_MAX]; //场景所有物体 SceneEntryType PosI SceneEntry
SceneEntry_SET all[SceneEntry::SceneEntry_MAX]; //场景所有物体 SceneEntryType SceneEntry
//在初始化的时候计算九屏关系
typedef map<DWORD, zPosIVector> NineScreen_map;
typedef NineScreen_map::iterator NineScreen_map_iter;
typedef NineScreen_map::const_iterator NineScreen_map_const_iter;
typedef NineScreen_map::value_type NineScreen_map_value_type;
NineScreen_map ninescreen;
void freshEffectPosi(const zPosI oldposi, const zPosI newposi);
public:
SceneEntryIndex() {}
void init(const Pos sceneWH, const DWORD screenx, const DWORD screeny, const DWORD screenMax);
virtual ~SceneEntryIndex() {}
const zPosIVector &getNineScreen(const zPosI &posi)
{
NineScreen_map_const_iter iter = ninescreen.find((DWORD)posi);
if( iter != ninescreen.end())
{
return iter->second;
}
return ninescreen[(DWORD)-1];
}
...
};
void SceneEntryIndex::init(const Pos sceneWH, const DWORD screenx, const DWORD screeny, const DWORD screenMax)
{
this->sceneWH=sceneWH;
this->screenx=screenx;
this->screeny=screeny;
for(int i = 0; i < SceneEntry::SceneEntry_MAX; i++)
{
for(DWORD j=0; j < screenMax; j ++)
{
index[i][j];
}
}
//预先建立地图九屏索引
const int adjust[9][2] = { {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, 0} };
for(DWORD j=0; j < screenMax ; j ++)
{
int nScreenX = j % screenx;
int nScreenY = j / screenx;
//计算周围九屏
{
zPosIVector pv;
for(int i = 0; i < 9; i++) {
int x = nScreenX + adjust[i][0];
int y = nScreenY + adjust[i][1];
if (x >= 0 && y >= 0 && x < (int)screenx && y < (int)screeny) {
pv.push_back(y * screenx + x);
}
}
ninescreen.insert(NineScreen_map_value_type(j,pv));
}
}
}
//刷新屏索引
bool SceneEntryIndex::refresh(SceneEntry *e,const Pos & newPos)
{
if(e==NULL) return false;
SceneEntry::SceneEntryType type = e->getType();
if(e->inserted)
{
//已经加入地图,只是在屏之间来回切换
bool ret=false;
zPosI orgscreen=e->getPosI();
SceneEntry_SET &pimi = index[type][orgscreen];
SceneEntry_SET::const_iterator it = pimi.find(e);
if (it != pimi.end() && e->setPos(sceneWH, newPos))
{
ret=true;
if(orgscreen!=e->getPosI())
{
pimi.erase(it);
index[type][e->getPosI()].insert(e);
}
}
return ret;
}
else
{
//新加入地图
if(e->setPos(sceneWH,newPos))
{
index[type][e->getPosI()].insert(e);
//在全局索引中添加
all[type].insert(e);
e->inserted=true;
}
return e->inserted;
}
}
//移除场景物体
bool SceneEntryIndex::removeSceneEntry(SceneEntry *e)
{
if(e==NULL || !e->inserted) return false;
SceneEntry::SceneEntryType type = e->getType();
SceneEntry_SET &pimi = index[type][e->getPosI()];
SceneEntry_SET::iterator it = pimi.find(e);
if (it != pimi.end())
{
//在屏索引中删除
pimi.erase(it);
//在全局索引中删除
all[type].erase(e);
e->inserted=false;
return true;
}
return false;
}
//遍历一屏物体,并对其进行callback操作
void SceneEntryIndex::execAllOfScreen(const zPosI screen,zSceneEntryCallBack &callback)
{
for(int i = 0; i < SceneEntry::SceneEntry_MAX; i++)
{
SceneEntry_SET &pimi = index[i][screen];
for(SceneEntry_SET::iterator it=pimi.begin();it!=pimi.end();)
{
//预先保存迭代器,防止回调中使迭代器失效
SceneEntry_SET::iterator tmp = it;
it++;
zSceneEntry *eee = *tmp;
if (!callback.exec(eee)) return;
}
}
}