static void PushUp(const T_choice *aChoice) { T_timeDateWorkspace *G_ws = (T_timeDateWorkspace *)aChoice->iData; if (G_ws->iMode) DateUp(aChoice); else TimeUp(aChoice); }
/** This methods executes one round of gameplay. The game progresses through phases Ph_START, Ph_NORMAL, and Ph_KO. If a KO happened, it will invoke InstantReplay. At the end of the round m_aiRoundsWonByPlayer[x] will be incremented depending on the outcome. m_iNumberOfRounds will also increase by 1. */ void CGame::DoOneRound() { m_enGamePhase = Ph_START; m_poBackground->DeleteExtraLayers(); int iTeamSize = (SState::Team_ONE_VS_ONE==g_oState.m_enTeamMode) ? 1 : g_oPlayerSelect.GetPlayerInfo(0).m_aenTeam.size(); int aiTeamNumber[MAXPLAYERS]; for ( int i=0; i<g_oState.m_iNumPlayers; ++i ) { aiTeamNumber[i] = 0; } if ( IsTeamMode() ) { for ( int i=0; i<g_oState.m_iNumPlayers; ++i ) { g_oPlayerSelect.SetPlayer( i, g_oPlayerSelect.GetPlayerInfo(i).m_aenTeam[aiTeamNumber[i]] ); } } g_oBackend.PerlEvalF( "GameStart(%d,%d,%d,%d,%d);", IsMaster() ? g_oState.m_iHitPoints : g_poNetwork->GetGameParams().iHitPoints, g_oState.m_iNumPlayers, iTeamSize, m_bWide, m_bDebug ); g_oBackend.ReadFromPerl(); if ( IsNetworkGame() ) { g_poNetwork->SynchStartRound(); g_poNetwork->SendGameTick( g_oBackend.m_iGameTick-1 ); } int iKoFrame = -1; double dGameTime = 2 * 1000; // Only for the "greeting phase", the real gametime will be set after. int iThisTick, iLastTick, iGameSpeed; bool bHurryUp = false; bool bReplayAfter = true; iGameSpeed = IsMaster() ? g_oState.m_iGameSpeed : g_poNetwork->GetGameParams().iGameSpeed; iThisTick = SDL_GetTicks() / iGameSpeed; iLastTick = iThisTick - 1; m_oKeyQueue.Reset(); oFpsCounter.Reset(); // 1. DO THE NORMAL GAME ROUND (START, NORMAL, KO, TIMEUP) while ( dGameTime >= 0 ) { if ( m_enInitialGameMode != g_oState.m_enGameMode ) { return; } // 1. Wait for the next tick (on extremely fast machines..) while (iThisTick == iLastTick) { iThisTick = SDL_GetTicks() / iGameSpeed; if ( iThisTick==iLastTick ) SDL_Delay(1); } // 2. Advance as many ticks as necessary.. int iNumTicks = iThisTick - iLastTick; if ( iNumTicks > MAXFRAMESKIP ) iNumTicks = MAXFRAMESKIP; Advance( iNumTicks ); dGameTime -= iNumTicks * iGameSpeed; // 3. Check for state transitions and game time. // START -> NORMAL // NORMAL -> KO // NORMAL -> TIMEUP // bHurryUp flag can be set during NORMAL phase if ( Ph_START == m_enGamePhase ) // Check for the end of the START phase { if ( dGameTime <= 0 ) { m_enGamePhase = Ph_NORMAL; dGameTime = (IsMaster() ? g_oState.m_iRoundLength : g_poNetwork->GetGameParams().iRoundLength) * 1000; } } else if ( Ph_NORMAL == m_enGamePhase ) // Check for the end of the NORMAL phase { if ( dGameTime < 10 * 1000 && !bHurryUp ) { bHurryUp = true; g_poNetwork->SendHurryup( 1 ); HurryUp(); iGameSpeed = iGameSpeed * 3 / 4; } if ( g_oBackend.m_bKO ) { m_enGamePhase = Ph_KO; dGameTime = 10 * 1000; iKoFrame = m_aReplayOffsets.size(); } else if ( dGameTime <= 0 ) { m_enGamePhase = Ph_TIMEUP; g_poNetwork->SendHurryup( 2 ); TimeUp(); break; } } m_iGameTime = (int) ((dGameTime + 500.0) / 1000.0); iLastTick = iThisTick; // ProcessEvents will read keyboard/gamepad input // It will also transmit them to the remote side in a network game. if ( ProcessEvents() || g_oState.m_bQuitFlag ) { bReplayAfter = false; break; } oFpsCounter.Tick(); // 3. Draw the next game screen.. Draw(); // 4. Check 'end of round' condition. for ( int i=0; i<g_oState.m_iNumPlayers; ++i ) { if ( g_oBackend.m_aoPlayers[i].m_iRealHitPoints <= -10000 ) { // We have a dead player here. if ( aiTeamNumber[i] < iTeamSize-1 ) { ++aiTeamNumber[i]; AddBodyToBackground( i ); FighterEnum enFighter = g_oPlayerSelect.GetPlayerInfo(i).m_aenTeam[ aiTeamNumber[i] ]; g_oPlayerSelect.SetPlayer( i, enFighter ); g_oBackend.PerlEvalF( "NextTeamMember(%d,%d);", i, enFighter ); } } } if ( g_oBackend.m_iGameOver ) { break; } if ( !IsMaster() ) { if ( g_poNetwork->IsRoundOver() ) { break; } } } int p1h = g_oBackend.m_aoPlayers[0].m_iRealHitPoints; int p2h = g_oBackend.m_aoPlayers[1].m_iRealHitPoints; // 3. DO THE REPLAY (IF THERE WAS A KO) if ( iKoFrame>0 && bReplayAfter && !IsNetworkGame() ) { InstantReplay( iKoFrame ); } // 4. END OF ROUND debug( "Game over; p1h = %d; p2h = %d\n", p1h, p2h ); if ( IsMaster() ) { int iWhoWon = -1; if ( p1h > p2h ) { ++m_aiRoundsWonByPlayer[0]; iWhoWon = 0; } if ( p2h > p1h ) { ++m_aiRoundsWonByPlayer[1]; iWhoWon = 1; } if ( IsNetworkGame() ) { g_poNetwork->SendGameTick( g_oBackend.m_iGameTick + m_iEnqueueDelay * 100 ); g_poNetwork->SendRoundOver( iWhoWon, m_iNumberOfRounds > 0 ); } } else { int iWhoWon = g_poNetwork->GetWhoWon(); if ( iWhoWon>=0 ) { ++m_aiRoundsWonByPlayer[iWhoWon]; } } ++m_iNumberOfRounds; }