📄 gamemanager.cpp
字号:
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 + -