Bomber.cpp
上传用户:royluo
上传日期:2007-01-05
资源大小:1584k
文件大小:13k
源码类别:

游戏

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *                                                                             
  3. *   Bomber.cpp                                                            
  4. *                                                                             
  5. *   Electrical Engineering Faculty - Software Lab                             
  6. *   Spring semester 1998                                                      
  7. *                                                                             
  8. *   Tanks game                                                                
  9. *                                                                             
  10. *   Module description: Implements the bomber object. That's a unique game 
  11. *                       object - when in use it catches the keyboard input,
  12. *                       enabling the player to position and direct it on board,
  13. *                       and afterward when launched it acts like the other 
  14. *                       moving game objects.
  15. *                       
  16. *                                                                             
  17. *   Authors: Eran Yariv - 28484475                                           
  18. *            Moshe Zur  - 24070856                                           
  19. *                                                                            
  20. *                                                                            
  21. *   Date: 23/09/98                                                           
  22. *                                                                            
  23. ******************************************************************************/
  24. #include <stdafx.h>
  25. #include <bomber.h>
  26. #include <Bomb.h>
  27. /*------------------------------------------------------------------------------
  28.   Function: Constructor
  29.   Purpose:  Contructs the bomber on a local machine (enabling player to control
  30.             the start position and direction).
  31.   Input:    pParent - pointer to the tank that owns (launches) the bomber.
  32.   Output:   None.
  33.   Remarks:  
  34. ------------------------------------------------------------------------------*/
  35. CBomber::CBomber (CTankObj *pParent) :
  36.     CMovingGameObject (MAP_WIDTH - BOMBER_WIDTH / 2,        // XPos
  37.                        MAP_HEIGHT / 2 - BOMBER_HEIGHT / 2,  // YPos
  38.                        BOMBER_WIDTH,                        // XSize
  39.                        BOMBER_HEIGHT,                       // YSize
  40.                        0,                                   // Direction index
  41.                        BOMBER_SPEED),                       // Velocity 
  42.     m_pFather (pParent),
  43.     m_bLocal (TRUE),
  44.     m_MsgQueue(TANKS_APP->m_gIncomingMsgQueue),
  45.     m_Timer(TANKS_APP->m_gTimer),
  46.     m_dwLastMoveTick (0),
  47.     m_State (BOMBER_STATE_SETUP),
  48.     m_uEdgePos (UINT(1.5 * float (EDGE_TICKS)))
  49. {
  50.     m_hImage = m_GlobalImageManager.GetImage (CImageManager::IMG_BOMBER);
  51.     if (!m_GlobalObjsList.IsObjectValid(m_pFather))
  52.     {
  53.         // Father tank is dead now
  54.         m_pFather = NULL;
  55.         m_State = BOMBER_STATE_DEAD;
  56.         m_pManouverSet = NULL;
  57.     }
  58.     else
  59.     {   // Wa have a legal father tank
  60.         m_pManouverSet = &m_pFather->GetManouverSet();
  61.         m_pFather->RelinquishInput();
  62.     }
  63. }            
  64. /*------------------------------------------------------------------------------
  65.   Function: Constructor
  66.   Purpose:  Contructs the bomber on a remote machine (a player on another 
  67.             machine was launching the bomber, we are only displaying it).
  68.   Input:    uDirInd - the bombers direction
  69.             uXPos,uYPos - the bombers position
  70.             dwInitFlightTime - the game time the bomber was launched
  71.   Output:   None.
  72.   Remarks:  
  73. ------------------------------------------------------------------------------*/
  74. CBomber::CBomber (  UINT uDirInd,
  75.                     UINT uXPos,
  76.                     UINT uYPos,
  77.                     DWORD dwInitFlightTime) :
  78.     CMovingGameObject (uXPos,           // XPos
  79.                        uYPos,           // YPos
  80.                        BOMBER_WIDTH,    // XSize
  81.                        BOMBER_HEIGHT,   // YSize
  82.                        uDirInd,         // Direction index
  83.                        BOMBER_SPEED),   // Velocity 
  84.     m_pFather (NULL),
  85.     m_bLocal (FALSE),
  86.     m_MsgQueue(TANKS_APP->m_gIncomingMsgQueue),
  87.     m_Timer(TANKS_APP->m_gTimer),
  88.     m_dwLastMoveTick (dwInitFlightTime),
  89.     m_State (BOMBER_STATE_FLYING),
  90.     m_pManouverSet (NULL),
  91.     m_dwInitialTime (dwInitFlightTime),
  92.     m_InitialPos (CPoint (uXPos, uYPos))
  93. {
  94.     m_hImage = m_GlobalImageManager.GetImage (CImageManager::IMG_BOMBER);
  95.     m_GlobalImageManager.RotateImage (m_hImage, m_uDirectionIndex);
  96. }
  97. CPoint 
  98. CBomber::CalcEdgePos ()
  99. {
  100.     CPoint res;
  101.     ASSERT (m_uEdgePos < (4 * EDGE_TICKS));
  102.     if (((m_uEdgePos >= (3 * EDGE_TICKS)) && 
  103.         (m_uEdgePos <= (4 * EDGE_TICKS - 1))) || 
  104.         (0 == m_uEdgePos))
  105.         // Left pane
  106.         res.x = - BOMBER_WIDTH / 2;
  107.     else if ((m_uEdgePos >= EDGE_TICKS) && (m_uEdgePos <= (2 * EDGE_TICKS)))
  108.         // Right pane
  109.         res.x = MAP_WIDTH - BOMBER_WIDTH / 2;
  110.     else if ((m_uEdgePos >= 1) && (m_uEdgePos <= (EDGE_TICKS - 1)))
  111.         // Top pane
  112.         res.x = ((MAP_WIDTH / EDGE_TICKS) * m_uEdgePos) - BOMBER_WIDTH / 2;
  113.     else if ((m_uEdgePos >= (2 * EDGE_TICKS + 1)) && 
  114.         (m_uEdgePos <= (3 * EDGE_TICKS - 1)))
  115.         // Bottom pane
  116.         res.x = ((MAP_WIDTH / EDGE_TICKS) * ((3 * EDGE_TICKS) - m_uEdgePos)) - 
  117.             BOMBER_WIDTH / 2;
  118.     if ((m_uEdgePos >= (3 * EDGE_TICKS + 1)) && 
  119.         (m_uEdgePos <= (4 * EDGE_TICKS - 1)))
  120.         // Left pane
  121.         res.y = ((MAP_HEIGHT / EDGE_TICKS) * 
  122.             (m_uEdgePos - (3 * EDGE_TICKS))) - BOMBER_HEIGHT / 2;
  123.     else if ((m_uEdgePos >= (EDGE_TICKS + 1)) && 
  124.         (m_uEdgePos <= (2 * EDGE_TICKS - 1)))
  125.         // Right pane
  126.         res.y = ((MAP_HEIGHT / EDGE_TICKS) * ((2 * EDGE_TICKS) - m_uEdgePos)) -
  127.             BOMBER_HEIGHT / 2;
  128.     else if ((m_uEdgePos >= 0) && (m_uEdgePos <= EDGE_TICKS))
  129.         // Top pane
  130.         res.y = MAP_HEIGHT - BOMBER_HEIGHT / 2;
  131.     else if ((m_uEdgePos >= (2 * EDGE_TICKS)) && 
  132.         (m_uEdgePos <= (3 * EDGE_TICKS)))
  133.         // Bottom pane
  134.         res.y = - BOMBER_HEIGHT / 2;
  135.     return res;
  136. }
  137. void
  138. CBomber::FixEdgeDirection ()
  139. {
  140.     BOOL bTop    = (m_uEdgePos >= 0) && (m_uEdgePos <= EDGE_TICKS),
  141.          bLeft   = ((m_uEdgePos >= (3 * EDGE_TICKS)) && (m_uEdgePos <= (4 * EDGE_TICKS - 1))) || (0 == m_uEdgePos),
  142.          bRight  = (m_uEdgePos >= EDGE_TICKS) && (m_uEdgePos <= (2 * EDGE_TICKS)), 
  143.          BBottom = (m_uEdgePos >= (2 * EDGE_TICKS)) && (m_uEdgePos <= (3 * EDGE_TICKS));
  144.     ASSERT (m_uEdgePos < (4 * EDGE_TICKS));
  145.     ASSERT (m_uDirectionIndex < MAX_DIRECTIONS);
  146.     UINT u90Deg = MAX_DIRECTIONS / 4;
  147.     if (bTop && (m_uDirectionIndex < (2 * u90Deg + 1)))
  148.     {   // fix dir
  149.         if (m_uDirectionIndex < u90Deg)
  150.             m_uDirectionIndex = (MAX_DIRECTIONS - 1);
  151.         else
  152.             m_uDirectionIndex = 2 * u90Deg + 1;
  153.     }
  154.     if (bLeft && ((m_uDirectionIndex < (u90Deg + 1)) || (m_uDirectionIndex > (3 * u90Deg - 1))))
  155.     {   // fix dir
  156.         if (m_uDirectionIndex < (u90Deg + 1))
  157.             m_uDirectionIndex = u90Deg + 1;
  158.         else
  159.             m_uDirectionIndex = (3 * u90Deg - 1);
  160.     }
  161.     if (bRight && (m_uDirectionIndex < (3 * u90Deg + 1)) && (m_uDirectionIndex > (u90Deg - 1)))
  162.     {   // fix dir
  163.         if (m_uDirectionIndex < (2 * u90Deg))
  164.             m_uDirectionIndex = u90Deg - 1;
  165.         else
  166.             m_uDirectionIndex = (3 * u90Deg + 1);
  167.     }
  168.     if (BBottom && ((m_uDirectionIndex > (2 * u90Deg - 1)) || (m_uDirectionIndex < 1)))
  169.     {   // fix dir
  170.         if (0 == m_uDirectionIndex)
  171.             m_uDirectionIndex = 1;
  172.         else if (m_uDirectionIndex < (3 * u90Deg))
  173.             m_uDirectionIndex = 2 * u90Deg - 1;
  174.         else
  175.             m_uDirectionIndex = 1;
  176.     }
  177. }
  178. StateType           
  179. CBomber::CalcState (DWORD dwCurTime)
  180. {
  181.     m_bImageChanged = FALSE;    // Assume no change since last CalcState
  182.     if (BOMBER_STATE_DEAD == m_State)
  183.         return STATE_DEAD;
  184.     if (BOMBER_STATE_FLYING == m_State)
  185.     {   // Flying now
  186.         int iDistSqr = CalcNewPos (dwCurTime, FALSE);
  187.         if (iDistSqr < 0) 
  188.         {   // Out of map situation
  189.             m_State = BOMBER_STATE_DEAD;
  190.             return STATE_DEAD;
  191.         }
  192.         int iNumBombs = (dwCurTime - m_dwLastMoveTick) / BOMBS_TIME_GAP;
  193.         while (iNumBombs--)
  194.         {   // More bombs to drop
  195.             m_dwLastMoveTick += BOMBS_TIME_GAP;
  196.             CPoint BombPos;
  197.             // Find out position of bomb at new time
  198.             if (!FindBombPos (BombPos, m_dwLastMoveTick - m_dwInitialTime))
  199.             { // Out of map
  200.                 m_State = BOMBER_STATE_DEAD;
  201.                 return STATE_DEAD;
  202.             }
  203.             // Drop the bomb
  204.             CBomb *pBomb = new CBomb (BombPos, m_uDirectionIndex);
  205.             // spawn bomb and send message to game mananger:
  206.             CMessage::MessageData Params;
  207.             Params.pGameObj = pBomb;
  208.             VERIFY (m_MsgQueue.Enqueue(CMessage::ADD_OBJECT, Params));
  209.             // Play sound
  210.             TANKS_APP->m_gSoundManager.Play(CSoundManager::DROP_BOMB);
  211.         }
  212.         m_bImageChanged = TRUE;
  213.         return STATE_ALIVE;
  214.     }
  215.     // Setup mode:
  216.     if (!AfxIsValidAddress(m_pFather, sizeof (CTankObj)))
  217.     {
  218.         // Father tank is dead
  219.         m_State = BOMBER_STATE_DEAD;
  220.         return STATE_DEAD;
  221.     }
  222.     if (0 == m_dwLastMoveTick) {
  223.         // First time
  224.         m_dwLastMoveTick = dwCurTime;
  225.         m_bImageChanged = TRUE;
  226.         m_pManouverSet->UnsetBit (CManouverSet::AERIAL_SUPPORT);
  227.     }
  228.     UINT ManouverSet = m_pManouverSet->GetAll();
  229.         // Each time we call GetAll on the MS we need to reset its values:
  230.     TANKS_APP->m_gKbdManager.RefreshManouverSet();
  231.     if (dwCurTime - m_dwLastMoveTick >= BOMBER_ROTATION_DELAY)
  232.     {   // Can we move / rotate ?
  233.         BOOL bMoveMade = FALSE;
  234.         if (ManouverSet & CManouverSet::TURN_RIGHT_MASK) 
  235.         {   // Rotate right
  236.             m_uDirectionIndex = (m_uDirectionIndex + 1) % MAX_DIRECTIONS;
  237.             bMoveMade = TRUE;
  238.         }
  239.         else if (ManouverSet & CManouverSet::TURN_LEFT_MASK) 
  240.         {   // Rotate left
  241.             m_uDirectionIndex = (m_uDirectionIndex == 0) ? (MAX_DIRECTIONS - 1) : (m_uDirectionIndex - 1);
  242.             bMoveMade = TRUE;
  243.         }
  244.         if (ManouverSet & CManouverSet::FORWARD_MASK) 
  245.         {   // Move forward
  246.             m_uEdgePos = (m_uEdgePos + 1) % (4 * EDGE_TICKS);
  247.             bMoveMade = TRUE;
  248.         } else if (ManouverSet & CManouverSet::BACKWARD_MASK) 
  249.         {   // Move backwards
  250.             m_uEdgePos = (0 == m_uEdgePos) ? (4 * EDGE_TICKS - 1) : m_uEdgePos - 1;
  251.             bMoveMade = TRUE;
  252.         }
  253.         if (bMoveMade)
  254.         {
  255.             m_dwLastMoveTick = dwCurTime;
  256.             SetNewPos (CalcEdgePos());
  257.             FixEdgeDirection ();
  258.             m_GlobalImageManager.RotateImage (m_hImage, m_uDirectionIndex);
  259.             m_bImageChanged = TRUE;
  260.         }
  261.     }
  262.     if (ManouverSet & (CManouverSet::FIRE_SHELL_MASK | CManouverSet::FIRE_BULLET_MASK)) 
  263.     {   // Launch bomber-> Send ADD_BOMBER to the server, and kill current bobmer.
  264.         // The server will send ADD_BOMBER to all players (and us too) an we'll create a new
  265.         // bomber object as a response.    
  266.         m_pFather->RegainInput (TRUE);
  267. //        m_State = BOMBER_STATE_FLYING;
  268. //        m_InitialPos = m_Pos;
  269. //        m_dwLastMoveTick = m_dwInitialTime = dwCurTime;
  270.         m_pManouverSet->UnsetBit (CManouverSet::FIRE_SHELL);
  271.         m_pManouverSet->UnsetBit (CManouverSet::FIRE_BULLET);
  272.         SendBomberMsg ();
  273.         return STATE_DEAD;  // Kill this object, a new bomber (flying) will be created soon
  274.                             // when the game manager receives ADD_BOMBER from the server.
  275.     }
  276.     if (ManouverSet & (CManouverSet::DROP_MINE_MASK | CManouverSet::AERIAL_SUPPORT_MASK)) 
  277.     {   // Cancel bomber
  278.         m_pFather->RegainInput (FALSE);
  279.         m_State = BOMBER_STATE_DEAD;
  280.         m_pManouverSet->UnsetBit (CManouverSet::AERIAL_SUPPORT);
  281.         m_pManouverSet->UnsetBit (CManouverSet::DROP_MINE);
  282.         return STATE_DEAD;
  283.     }
  284.     return STATE_ALIVE;
  285. }
  286. BOOL
  287. CBomber::FindBombPos (CPoint &ResPos, DWORD dwTimeGap)
  288. {
  289.     CalcPosAtTime (m_InitialPos, dwTimeGap, ResPos, FALSE);
  290.     // Fix position to look as if the bomb is dropped from behind the bomber
  291.     double radius = BOMBER_WIDTH / 2;
  292.     ResPos.x += (int(radius) - int (radius * m_dDirectionsArr[m_uDirectionIndex].dXDir) - 9);
  293.     ResPos.y += (int(radius) - int (radius * m_dDirectionsArr[m_uDirectionIndex].dYDir) - 9);
  294.     WORD fl = GetMapPosition(ResPos);
  295.     if ((X_NOT_IN_MAP & fl) || (Y_NOT_IN_MAP & fl)) 
  296.     {   // Out of map situation
  297.         return FALSE;
  298.     }
  299.     return TRUE;
  300. }
  301. void
  302. CBomber::SendBomberMsg ()
  303. {
  304.     CMessage::MessageData Params;
  305.         // Create bomber notification message:
  306.     Params.BomberParam.Xpos = m_Pos.x;
  307.     Params.BomberParam.Ypos = m_Pos.y;
  308.     Params.BomberParam.Direction = m_uDirectionIndex;
  309.         // Send it
  310.     TANKS_APP->m_gOutgoingMsgQueue.Enqueue (CMessage::ADD_BOMBER, Params);
  311. }