⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamemanager.cpp

📁 分布式坦克游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        msg.CheckSumParam.MinesSectorsChkSum[bSector] = 
            BYTE(msg.CheckSumParam.MinesSectorsChkSum[bSector] + pGameObj->GetPosCheckSum());
    }
    m_MinesCS.Unlock();
    // Finally, do the bonus flag:
    m_BonusCS.Lock();
    if (m_pBonus != NULL)
        msg.CheckSumParam.ActiveBonusType = m_pBonus->GetBonusType();
    else 
        msg.CheckSumParam.ActiveBonusType = BONUS_NONE;
    m_BonusCS.Unlock();

    // Send it all through the comm. manager
    m_CommManager.NotifyCheckSum (msg);
}

void
CGameManager::GetBonusState(CMessage::MessageData& MsgData)
{
    m_BonusCS.Lock();
    if (m_pBonus) 
    {   // Bonus exists
        MsgData.BonusParam.Type = m_pBonus->GetBonusType();
        CPoint pos(m_pBonus->GetPos());
        MsgData.BonusParam.XPos = pos.x;
        MsgData.BonusParam.YPos = pos.y;
        MsgData.BonusParam.LifeSpan = BONUS_MIN_LIFESPAN + BONUS_LIFESPAN_RANGE;   // Max life span
    }
    else
    {   // Bonus doesn't exist
        MsgData.BonusParam.Type = BONUS_NONE;
        MsgData.BonusParam.LifeSpan = MAX_TANKS;    // No tank has eaten the last bonus
    }
    m_BonusCS.Unlock();
}

BOOL 
CGameManager::GetTankStatus(int iTankID, CMessage::MessageData& MsgData)
{
    BOOL bRes = FALSE;
    m_BonusCS.Lock();
    ASSERT(iTankID < MAX_TANKS);
    if (m_pTanks[iTankID]) {
        bRes = TRUE;
        m_pTanks[iTankID]->GetStatus(MsgData);
    }
    m_BonusCS.Unlock();
    return bRes;
}

BOOL 
CGameManager::GetTankStatusAndPos(int iTankID, CMessage::MessageData& MsgData)
{
    BOOL bRes = FALSE;
    m_BonusCS.Lock();
    ASSERT(iTankID < MAX_TANKS);
    if (m_pTanks[iTankID]) {
        bRes = TRUE;
        m_pTanks[iTankID]->GetStatusAndPos(MsgData);
    }
    m_BonusCS.Unlock();
    return bRes;
}

DWORD
CGameManager::GetMinesInSector (UINT uSector, DWORD *pAllMinesInSector)
{
    DWORD dwCount = 0;
    m_MinesCS.Lock();
    LIST_POS lp = m_GameObjsList.GetHeadPosition();
    CGameObject* pGameObj = m_GameObjsList.GetNext(lp);  // GameBoard
    ASSERT(BOARD == pGameObj->GetType());

        // Continue (after the board) and scan for mines (only lower level):
    for ( pGameObj = m_GameObjsList.GetNext(lp);
          pGameObj && (HIGHER_LEVEL > pGameObj->GetHeight());
          pGameObj = m_GameObjsList.GetNext(lp) ) 
    {
        // This is a lower level object
        if (pGameObj->GetType() != MINE)
            continue;
        // This is a mine - check for sector
        if (pGameObj->GetSector() != uSector)
            continue;   // Mine is not of requested sector
        // This is a mine of requested sector - add it
        
        pAllMinesInSector[dwCount++] = MAKELONG (pGameObj->GetPos().x, pGameObj->GetPos().y);

    }
    m_MinesCS.Unlock();
    return dwCount;
}

void
CGameManager::SetMinesInSector (UINT uSector, DWORD dwNumMines, DWORD *pAllMinesInSector)
{
    m_MinesCS.Lock();
    LIST_POS lp = m_GameObjsList.GetHeadPosition();
    CGameObject* pGameObj = m_GameObjsList.GetNext(lp);  // GameBoard
    ASSERT(BOARD == pGameObj->GetType());

    DWORD dwNewMines = dwNumMines;

        // Continue (after the board) and scan for mines (only lower level):
    for ( pGameObj = m_GameObjsList.GetNext(lp);
          pGameObj && (HIGHER_LEVEL > pGameObj->GetHeight());
          pGameObj = m_GameObjsList.GetNext(lp) ) 
    {
        // This is a lower level object
        if (pGameObj->GetType() != MINE)
            continue;
        // This is a mine - check for sector
        if (pGameObj->GetSector() != uSector)
            continue;   // Mine is not of requested sector
        // This is a mine of requested sector - find it in the list
        BOOL bMineFound = FALSE;
        for (DWORD i=0; i < dwNumMines; i++)
            if ((pGameObj->GetPos().x == LOWORD (pAllMinesInSector[i])) &&
                (pGameObj->GetPos().y == HIWORD (pAllMinesInSector[i])))
            {
                // The mine is found in the list:
                pAllMinesInSector[i] = MAX_DWORD;   // Mark it out
                dwNewMines--;                       // This is not a new mine
                bMineFound = TRUE;
                break;                              // Stop searching the list
            }
        if (!bMineFound)
        {
            // Mine is not in the list but is in the game - Kill it
            pGameObj->Kill();
        }
    }
    m_MinesCS.Unlock();
    // Now the list contains exactly dwNewMines new mines to be added.
    if (0 == dwNewMines)
        return; // Quit now if there are no new mines to add

    for (DWORD i=0; i < dwNumMines; i++)
        if (pAllMinesInSector[i] != MAX_DWORD)
        {   // Mine is in the list and not marked => Add it using a message to the incoming queue
            CMessage::MessageData Params;
            Params.MineParam.wXPos = LOWORD (pAllMinesInSector[i]);
            Params.MineParam.wYPos = HIWORD (pAllMinesInSector[i]);
            VERIFY (m_MsgQueue.Enqueue(CMessage::ADD_MINE, Params));
            if (--dwNewMines == 0)
                // No more new mines, stop scanning the list and exit
                break;
        }
}

// Message handlers:

void 
CGameManager::AddBonus (CMessage &Msg, DWORD dwLoopStartTime)
{
    if (BONUS_NONE == Msg.m_UnionData.BonusParam.Type)
    { // Bonus is being removed - Tank ID is in LifeSpan (MAX_TANKS for no tank)
        if (Msg.m_UnionData.BonusParam.LifeSpan < MAX_TANKS)
        {   // Some tank ate the bonus, tell him about that
            m_TanksCS.Lock();
            if (m_pTanks[Msg.m_UnionData.BonusParam.LifeSpan] != NULL)
                // This tank is alive on this machine - feed the bonus to the tank
                m_pTanks[Msg.m_UnionData.BonusParam.LifeSpan]->EatBonus (m_LastBonusType, 
                                                                                Msg.GetTime());
            m_TanksCS.Unlock();
        }
        m_BonusCS.Lock();
        if (NULL != m_pBonus)
        {   // Bonus didn't timeout yet
            m_pBonus->Kill();   // Remove this bonus object
            m_pBonus = NULL;    // Deref (make room for new bonus right away)    
        }
        m_BonusCS.Unlock();
    }
    else
    { // Bonus is being added
        m_BonusCS.Lock();
        if (NULL != m_pBonus)
            // Make sure there's only one bonus
            m_pBonus->Kill();   // Remove this bonus object
        m_pBonus = new CBonus (
            BonusType(Msg.m_UnionData.BonusParam.Type),
            CPoint (Msg.m_UnionData.BonusParam.XPos, 
                    Msg.m_UnionData.BonusParam.YPos),
            1000L * Msg.m_UnionData.BonusParam.LifeSpan, // Convert from secs to msecs.
            dwLoopStartTime);
        AddObject (m_pBonus);
        m_LastBonusType = BonusType(Msg.m_UnionData.BonusParam.Type);
        m_BonusCS.Unlock();
    }
}

void
CGameManager::AddTank (CMessage &Msg)
{
    m_TanksCS.Lock();
    // The following assertion was removed:
    // Reason:  If this is a client (non-judge) and it connects to a server,
    //          the server sends ADD_TANK after the client first check sum report.
    //          The ADD_TANK may not be fully digested until it's time to send
    //          another checksum report, which will report the tank as still missing
    //          and will cause another ADD_TANK with the same tank ID.
//            ASSERT (NULL == m_pTanks[Msg.m_UnionData.TankParam.ID]);   // Can't add same tank twice
    if (NULL == m_pTanks[Msg.m_UnionData.TankParam.ID])
    {   // First time this tank is seen
        m_pTanks[Msg.m_UnionData.TankParam.ID] = new CTankObj (
            Msg.m_UnionData.TankParam.ID,
            Msg.m_UnionData.TankParam.XPos,
            Msg.m_UnionData.TankParam.YPos,
            Msg.m_UnionData.TankParam.Direction,
            Msg.m_UnionData.TankParam.Local,
            Msg.m_UnionData.TankParam.ShieldLevel,
            Msg.m_UnionData.TankParam.Shells,
            Msg.m_UnionData.TankParam.Bullets,
            Msg.m_UnionData.TankParam.Mines,
            Msg.m_UnionData.TankParam.FireRateBonusSecsLeft);  // @@ fix last parameter @@@
        AddObject (m_pTanks[Msg.m_UnionData.TankParam.ID]);
        m_iNumTanks++;
        ASSERT (m_iNumTanks <= MAX_TANKS);
    }
    else
    {   
        //
        // An already existing tank was added. Ignore, next checksum will fix tank properties
        //
    }

    // If this our local tank - attach the keyboard to the manouver set:
    if (Msg.m_UnionData.TankParam.Local)
    {   // Local tank
        TANKS_APP->m_gKbdManager.SetManouverSet 
            (&(TANKS_APP->m_gManouverSets[Msg.m_UnionData.TankParam.ID]));
        m_iLocalTankID = Msg.m_UnionData.TankParam.ID;
    }
    else
    {   // Adding a remote tank, make sure the manouver set is clear
        TANKS_APP->m_gManouverSets[Msg.m_UnionData.TankParam.ID].Clear();
    }
    m_TanksCS.Unlock();
}

void
CGameManager::RemoveTank (CMessage &Msg)
{
    m_TanksCS.Lock();
    CTankObj *pTank = m_pTanks[Msg.m_UnionData.TankRemoveParam.ID];
    if (pTank &&                    // If tank exists and
        !pTank->IsExploding())      // it is not already exploding
    {
        pTank->Kill();
    }
    m_TanksCS.Unlock();
}

void
CGameManager::AddBoard (CMessage &Msg)
{
    CGameBoard *pGameBoard = new CGameBoard ();
    pGameBoard->GenerateBoard (
        Msg.m_UnionData.BoardParam.Seed,
        Msg.m_UnionData.BoardParam.Complexity);
    AddObject (pGameBoard);
}

void
CGameManager::AddShell (CMessage &Msg)
{
    AddObject(new CShell (
        Msg.m_UnionData.ShellParam.wXPos,
        Msg.m_UnionData.ShellParam.wYPos,
        Msg.m_UnionData.ShellParam.bDirectionIndex,
        Msg.m_UnionData.ShellParam.bParentTankID));
}

void
CGameManager::AddBullet (CMessage &Msg)
{
    AddObject (new CBullet (
        Msg.m_UnionData.BulletParam.wXPos,
        Msg.m_UnionData.BulletParam.wYPos,
        Msg.m_UnionData.BulletParam.bDirectionIndex,
        Msg.m_UnionData.BulletParam.bParentTankID));
}

void
CGameManager::AddBomber (CMessage &Msg, DWORD dwLoopStartTime)
{
    // Create and add a new flying bomber
    AddObject (new CBomber (Msg.m_UnionData.BomberParam.Direction,
                            Msg.m_UnionData.BomberParam.Xpos,
                            Msg.m_UnionData.BomberParam.Ypos,
                            dwLoopStartTime));
}

void
CGameManager::AddMine (CMessage &Msg)
{
    m_MinesCS.Lock();
    AddObject (new CMine (Msg.m_UnionData.MineParam.wXPos,
                          Msg.m_UnionData.MineParam.wYPos));
    m_MinesCS.Unlock();
}


void
CGameManager::SetTankStatus (CMessage &Msg)
{
    ASSERT(Msg.m_UnionData.TankStatusParam.bID < MAX_TANKS);
    if (m_pTanks[Msg.m_UnionData.TankStatusParam.bID])
    {   // Tank exists:
        // Set its status:
        m_pTanks[Msg.m_UnionData.TankStatusParam.bID]->SetStatus(Msg.m_UnionData);
    }
}

void
CGameManager::SetTankPos (CMessage &Msg)
{
    ASSERT(Msg.m_UnionData.TankPosParam.ID < MAX_TANKS);
    if (m_pTanks[Msg.m_UnionData.TankPosParam.ID])
    {   // Tank exists:
        // TODO: The following assert fails, that the reason it's marked out:
        //ASSERT (Msg.m_UnionData.TankPosParam.ID != UINT(m_iLocalTankID)); 
        // This msg shouldn't be send back to sender
        if (Msg.m_UnionData.TankPosParam.ID == UINT(m_iLocalTankID))
            return;
        m_pTanks[Msg.m_UnionData.TankPosParam.ID]->
            SetPos (Msg.GetTime(),
                    Msg.m_UnionData.TankPosParam.XPos,  // Set its position
                    Msg.m_UnionData.TankPosParam.YPos); // according the time stamp
    }
}

void
CGameManager::SetTankZombie (CMessage &Msg)
{
    ASSERT(Msg.m_UnionData.TankZombieParam.ID < MAX_TANKS);
    if (m_pTanks[Msg.m_UnionData.TankZombieParam.ID])  // Tank exists:
        m_pTanks[Msg.m_UnionData.TankZombieParam.ID]->
            SetZombie (Msg.m_UnionData.TankZombieParam.Zombie);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -