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

📄 tankobj.cpp

📁 分布式坦克大战游戏,多机运行
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        {   // We got a forced position and direction (due to checksum mismatch)
            SetNewPos (m_iNewForcedXPos, m_iNewForcedYPos);
            m_bForceNewPos = FALSE;       // Turn it off
            m_bImageChanged = TRUE;
        } 
        else 
        {   // Normal game play
            if (ManouverSet & CManouverSet::FORWARD_MASK) 
            {   // Move forward
                m_dVelocity = fabs(m_dVelocity);
                ms.SetBit (CManouverSet::FORWARD);
                bTryToMove = TRUE;
            } else if (ManouverSet & CManouverSet::BACKWARD_MASK) 
            {   // Move backwards
                m_dVelocity = -1.0 * fabs(m_dVelocity);
                ms.SetBit (CManouverSet::BACKWARD);
                bTryToMove = TRUE;
            }
            else
                StopMovement ();    // No movement chosen
            if (bTryToMove)
            {   // Tank tried to move
                if (CalcNewPos(dwCurTime) < 0)
                {   // 
                    // Failed to move - out of map case
                    //
                    UndoMovement ();
                    if (m_uDirectionIndex != uLastDir) 
                    {   // If we moved AND rotated, cancel rotation as well.
                        m_uDirectionIndex = uLastDir;
                        m_hTankImage = himgLastImage;
                    }
                    ms.UnsetBit (CManouverSet::FORWARD);      // Cancel movements:
                    ms.UnsetBit (CManouverSet::BACKWARD);
                    ms.UnsetBit (CManouverSet::TURN_RIGHT);   // Cancel roations
                    ms.UnsetBit (CManouverSet::TURN_LEFT);
                    m_bImageChanged = FALSE;
                }
                else
                {   
                    // Tries to move and successded (so far, collision not tested yet)
                    m_bImageChanged = TRUE;
                }
            }   // end of movement attempt
        } // end of normal game play
    }   // end of if (m_bUseManouverSet)
    //
    // handle reaction:
    //
    CReaction Reaction = m_ObjList.GetGameReaction (this);
    if (m_CommManager.IsHost() && (BONUS_NONE != Reaction.GetBonusType()))
        //
        // If this the host machine and a tank just hit a bonus, tell all the other
        // players (including this player) that the bonus has just been eaten.
        // This will cause a ADD_BONUS message to arrive with the Tank ID in 
        // the LifeSpan. The game manager, upon receipt of such a message will call 
        // the EatBonus method for the correct tank object.
        //
        m_CommManager.NotifyBonusEaten (m_uTankID);
    //
    // update state (shield level, image)
    //
    UINT ExplosionReact = Reaction.GetExplosionIntensity();
    if (ExplosionReact) 
    {   // We are hit:
        m_uShieldLevel -= ExplosionReact;    
        if (LONG(m_uShieldLevel) < 0)
		{
            // We are hit badly - that's the end:
			if (m_bLocal)	// If it's a remote tank, we have to
							// wait for the judge decision...
				Kill();
			else
				m_uShieldLevel = 0;
		}
        if (m_bLocal)
            // If it's a local tank, update shield status.
            m_pDlgWnd->SetShieldLevel (m_uShieldLevel);
    }
    //
    // update position:
    //
    TerrainType TerrainReact = Reaction.GetTerrainDifficulty();
    switch (TerrainReact)
    {
        case TERR_BLOCKED:
        case HIT_TANK:
            // we are blocked - rewind the new position:
            UndoMovement ();
            if (m_uDirectionIndex != uLastDir) {
                // There was also a rotation, undo it.
                m_uDirectionIndex = uLastDir;
                m_hTankImage = himgLastImage;
            }
            m_bImageChanged = FALSE;
                // Cancel all movements and rotations:
            ms.UnsetBit (CManouverSet::TURN_RIGHT);
            ms.UnsetBit (CManouverSet::TURN_LEFT);
            ms.UnsetBit (CManouverSet::FORWARD);
            ms.UnsetBit (CManouverSet::BACKWARD);
            break;
        case TERR_EMPTY:
            m_dVelocity = TANK_MAX_VELOCITY;
            break;
        case TERR_75SPEED:
            m_dVelocity = TANK_75_VELOCITY;
            break;
        case TERR_50SPEED:
            m_dVelocity = TANK_50_VELOCITY;
            break;
        case TERR_25SPEED:
            m_dVelocity = TANK_25_VELOCITY;
            break;
        default:
            ASSERT (FALSE);
            break;
    }

    if (m_bUseManouverSet)
    {   // Can we use the manouver set to react to the user's whim
        //
        // check the fire controls, and spawn bullet/shell/mine if needed:
        //
        if ((ManouverSet & CManouverSet::FIRE_SHELL_MASK) && // Fire shell button is pressed and
            m_uShells)                                       // we have shells 
        {
            if (ShellsEnabled(dwCurTime))    // we can fire a new shell
                FireShell(dwCurTime);
            ms.SetBit (CManouverSet::FIRE_SHELL);
        }

        if ((ManouverSet & CManouverSet::FIRE_BULLET_MASK) &&   // Fire bullet button is pressed and
            m_uBullets)                                         // we have bullets and
        {
            if (BulletsEnabled(dwCurTime))  // we can fire a new bullet
                FireBullet(dwCurTime);
            ms.SetBit (CManouverSet::FIRE_BULLET);
        }

        if ((ManouverSet & CManouverSet::DROP_MINE_MASK) &&     // Drop mine button is pressed and
            m_uMines)                                           // we have mines
        {
            if (MinesEnabled(dwCurTime)) // we can fire a new mine 
                // Try to drop a mine (may fail if there's no vacant room on the map)
                DropMine(dwCurTime);
            
            ms.SetBit (CManouverSet::DROP_MINE);
        }

        if ((ManouverSet & CManouverSet::AERIAL_SUPPORT_MASK) &&    // Bomber button is pressed and
            !m_bBomberInSetup &&                                    // we don't already have a bomber in setup mode and    
            m_bBomberAvail)                                         // we have the bomber icon on
        {
            LaunchBomber();
            // Notice, we don't set the bomber bit in the ms. Only when the bomber starts to fly
            // (after its setup mode) it sends ADD_BOMBER to all other players.
        }
    }


    // Before we leave - update the last tick calculated:
    // Check the fire rate bonus expiration time:
    if (m_dwFireRateBonusLastTick && (m_dwFireRateBonusLastTick <= dwCurTime)) 
    {   // turn off the fire rate bonus (timeout):
        m_dwBulletFireDelay = BULLET_FIRE_DELAY;
        m_dwShellFireDelay = SHELL_FIRE_DELAY;
        m_dwFireRateBonusLastTick = 0;
        if (m_bLocal)
            // Turn of the icon
            m_pDlgWnd->SetFastFireRate (FALSE);
    }
    SendManouverSet (ms);   // Notify other tanks on the network of our actions.

    // Store newly calculated position in table:
    PosEntry NewPos(dwCurTime, m_Pos.x, m_Pos.y);
    m_PosTable.AddHead(NewPos);

    return STATE_ALIVE; 
}

#pragma warning (default : 4701)


inline BOOL
CTankObj::BulletsEnabled(DWORD dwCurTime)
{
    return (dwCurTime - m_dwLastBulletFiredTick >= m_dwBulletFireDelay);
}
 
inline BOOL
CTankObj::MinesEnabled(DWORD dwCurTime)
{
    return (dwCurTime - m_dwLastMineDropTick >= MINE_FIRE_DELAY);
}


inline BOOL 
CTankObj::ShellsEnabled(DWORD dwCurTime)
{
    return (dwCurTime - m_dwLastShellFiredTick >= m_dwShellFireDelay);
}

void
CTankObj::FireShell(DWORD dwCurTime)
{
    // update flags:
    m_uShells--;
    m_dwLastShellFiredTick = dwCurTime;
    // spawn shell and send message to game mananger:
    CMessage::MessageData Params;
    Params.ShellParam.wXPos = WORD(m_SpawnOffsets[m_uDirectionIndex].iShellXOffset + m_Pos.x);
    Params.ShellParam.wYPos = WORD(m_SpawnOffsets[m_uDirectionIndex].iShellYOffset + m_Pos.y);
    Params.ShellParam.bDirectionIndex = BYTE(m_uDirectionIndex);
    Params.ShellParam.bParentTankID = BYTE(m_uTankID);

    VERIFY (m_MsgQueue.Enqueue(CMessage::ADD_SHELL, Params));
    if (m_bLocal)
    {
        // Update display
        m_pDlgWnd->SetShellsCount(m_uShells);
    }
    // Play the sound
    TANKS_APP->m_gSoundManager.Play(CSoundManager::FIRE_SHELL);
}

void
CTankObj::FireBullet(DWORD dwCurTime)
{
    // update flags:
    m_uBullets--;
    m_dwLastBulletFiredTick = dwCurTime;
    // spawn bullet and send message to game mananger:
    CMessage::MessageData Params;
    Params.BulletParam.wXPos = WORD(m_SpawnOffsets[m_uDirectionIndex].iBulletXOffset + m_Pos.x);
    Params.BulletParam.wYPos = WORD(m_SpawnOffsets[m_uDirectionIndex].iBulletYOffset + m_Pos.y);
    Params.BulletParam.bDirectionIndex = BYTE(m_uDirectionIndex);
    Params.BulletParam.bParentTankID = BYTE(m_uTankID);

    VERIFY (m_MsgQueue.Enqueue(CMessage::ADD_BULLET, Params));
    if (m_bLocal)
    {
        // Update display
        m_pDlgWnd->SetBulletsCount(m_uBullets);
    }
    // Play sound
    TANKS_APP->m_gSoundManager.Play(CSoundManager::FIRE_BULLET);
}

BOOL
CTankObj::DropMine(DWORD dwCurTime)
{
    CMine tmpMine (m_SpawnOffsets[m_uDirectionIndex].iMineXOffset + m_Pos.x,
                   m_SpawnOffsets[m_uDirectionIndex].iMineYOffset + m_Pos.y);
    CReaction Reaction = m_ObjList.GetGameReaction (&tmpMine);
        // check that we can spawn:
    if ((Reaction.GetTerrainDifficulty() == TERR_EMPTY) &&                   // board is empty
        (tmpMine.GetMapPosition(tmpMine.GetPos()) == (X_FULL_IN_MAP | Y_FULL_IN_MAP))) // and fully in map
    {
        // update flags:
        m_uMines--;
        m_dwLastMineDropTick = dwCurTime;
        // spawn mine and send message to game mananger:
        CMessage::MessageData Params;

        Params.MineParam.wXPos = WORD(tmpMine.GetPos().x);
        Params.MineParam.wYPos = WORD(tmpMine.GetPos().y);

        VERIFY (m_MsgQueue.Enqueue(CMessage::ADD_MINE, Params));

        if (m_bLocal)
        {
            // Update display
            m_pDlgWnd->SetMinesCount(m_uMines);
        }

        return TRUE;    // Mine dropped
    }
    return FALSE;   // Mine cannot be dropped

⌨️ 快捷键说明

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