【C++服务端技术】移动广播

/*
基于9宫格的移动广播,进入视野离开视野
1.根据玩家的xy坐标计算玩家移动之前和移动之后的格子id
2.根据格子id计算附近的格子,附近格子里面的玩家成为附近玩家
3.向新减少的格子的玩家发送离开视野,向新增的格子的玩家发送进入视野
*/


bool Room::HandleOnMove( IRole * pRole )
{
    if(NULL == pRole)
        return false;
    Room *pRoom = pRole->GetRoom();
    if(NULL == pRoom || pRoom->GetSceneId() == enNewPlayer_SceneId)
    {
        return false;
    }
    if(pOwnerScene->sceneInfo.canCrossRole == IS_CAN_CROSS_ROLE)
    {
        //设置Grid某一个点为1
        int pos = GetRoleGridPosByRowCol(pRole->GetRolePos().coord.getX(),pRole->GetRolePos().coord.getY());
        if(pos >=0 && pos < m_nRoleGridsSize)
        {
            if(pRole->GetLastGridPos() >= 0)
            {
                m_pRoleGrids[pRole->GetLastGridPos()] = 0;
            }
            pRole->SetLastGridPos(pos);
            m_pRoleGrids[pos] = 1;
            //Log::Instance()->WriteLog(enLogType_Error, "HandleOnMove m_pRoleGrids[pos]:%d 1", pos);
        }
    }

    Tint32 nOldSceneCellId = pRole->GetSceneCellId();

    //计算玩家在哪个单元格
    Tint32 TileId = CalcCellId(pRole->GetSceneCoord().getX(),pRole->GetSceneCoord().getY());
    if(TileId < m_nCellSize && TileId >= 0)
    {
        if(nOldSceneCellId < m_nCellSize && nOldSceneCellId >= 0)
        {
            if(nOldSceneCellId != TileId)
            {
                tagCellList CellList = GetDiffCell(&m_cells[nOldSceneCellId], &m_cells[TileId]);

                for (Tint32 i=CellList.nCount-1; i >=0 ; i--)
                {
                    CellList.m_Cells[i]->BroadcastCellLeaveMsg(pRole,false,true);
                }

                m_cells[nOldSceneCellId].OnLeave(pRole);
                m_cells[TileId].OnEnter(pRole);

                tagCellList EnterCellList = GetDiffCell(&m_cells[TileId], &m_cells[nOldSceneCellId]);
                for (Tint32 i=EnterCellList.nCount-1; i >=0 ; i--)
                {
                    EnterCellList.m_Cells[i]->SendCellEnterMsg(pRole,false);
                }
                pRole->SetSceneCellId(TileId);
            }
        }

        if(pRole->getIsMove())
        {
            if(cellSend[TileId] == 0)    //防止一个格子重复广播
            {
                m_cells[TileId].SyncCoord();        
                cellSend[TileId] = 1;
            }
        }
    }
    return true;
}

void CSceneCell::SyncCoord()
{
    Tint32 tmpSelfRoleCount;
    IRole* tmpSelfRoles[MAX_PLAYER_POS_CHANGE_COUNT + 1];

    tmpSelfRoleCount = GetSelfRoleListToArray(tmpSelfRoles, MAX_PLAYER_POS_CHANGE_COUNT);
    if(tmpSelfRoleCount == 0)
        return;

    if(tmpSelfRoleCount > MAX_PLAYER_POS_CHANGE_COUNT)
    tmpSelfRoleCount = MAX_PLAYER_POS_CHANGE_COUNT;
    
    MsgPushRoleMove RoleMove;
    for (Tint32 i=0; i < tmpSelfRoleCount; i++)
    {
        IRole* pRole = tmpSelfRoles[i];
        if(pRole->getIsMove())
        {
            pRole->setIsMove(false);
            MsgStructMove* Move = RoleMove.add_move_list();
            Move->set_role_type(pRole->GetRoleType());
            Move->set_tile_x(pRole->GetSceneCoord().getX());
            Move->set_tile_y(pRole->GetSceneCoord().getY());
            char buf[64] = ""; 
            if(pRole->GetRoleType() == GAME_PLAYER)
                sprintf(buf, "%lld", ((GamePlayer*)pRole)->GetGUID());
            else
                sprintf(buf, "%d", pRole->GetRoleId());
            Move->set_role_id(buf);
            Move->set_move_speed(pRole->GetMoveSpeed());
        }
    }
    
    if(RoleMove.move_list_size() == 0)
    {
        return;
    }
    vector<GamePlayer*> NearPlayers = GetNearPlayerList();
    //每个Cell只发数据给相邻的Cell,这样就确保每个对象只接收到一次数据
    tagNetMsg sendMsg;
    sendMsg.BuffLen = RoleMove.ByteSize();
    RoleMove.SerializePartialToArray(sendMsg.buff,RoleMove.ByteSize());
    for(vector<GamePlayer*>::iterator itPlayer = NearPlayers.begin();itPlayer != NearPlayers.end();++ itPlayer)
    {
        GamePlayer* TmpRole = *itPlayer;
        TmpRole->Send
        Msg(GAME_PLAYER_LOCATION_NOTIFY,sendMsg.BuffLen,sendMsg);
    }
}

https://github.com/jiangguilong2000/gamioo

原文地址:https://www.cnblogs.com/byfei/p/14104073.html