diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index 333e8d410a..754089ba36 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -327,6 +327,7 @@ void Player::Load() m_iRowLastCrossed = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ) - 1; // why this? m_iMineRowLastCrossed = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ) - 1; // why this? m_iRowLastJudged = m_iRowLastCrossed; + m_JudgedRows.Reset(); // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; @@ -1365,7 +1366,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) //LOG->Trace( "iStartCheckingAt: %d iMissIfOlderThanThisIndex: %d", iStartCheckingAt, iMissIfOlderThanThisIndex ); - int iNumMissesFound = 0; + bool bMisses = false; FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( m_NoteData, r, iStartCheckingAt, iMissIfOlderThanThisIndex-1 ) { @@ -1407,31 +1408,32 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) } if( MissedNoteOnThisRow ) - { - iNumMissesFound++; - HandleTapRowScore( r ); - } + bMisses = true; } - if( iNumMissesFound > 0 ) - { + if( bMisses ) SetJudgment( TNS_Miss, false ); - } } void Player::UpdateJudgedRows() { - const int iRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + const int iEndRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + bool bAllJudged = true; - while( m_iRowLastJudged <= iRow ) + for( int iRow = m_iRowLastJudged+1; iRow <= iEndRow; ++iRow ) { - if( !NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, m_iRowLastJudged+1, pn) ) - break; - ++m_iRowLastJudged; - if( NoteDataWithScoring::LastTapNoteWithResult(m_NoteData, m_iRowLastJudged, pn).result.tns == TNS_None ) + if( !NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, iRow, pn) ) + { + bAllJudged = false; continue; - OnRowCompletelyJudged( m_iRowLastJudged ); + } + if( bAllJudged ) + ++m_iRowLastJudged; + TapNoteScore tns = NoteDataWithScoring::LastTapNoteWithResult( m_NoteData, iRow, pn ).result.tns; + if( m_JudgedRows[iRow] || tns == TNS_None ) + continue; + OnRowCompletelyJudged( iRow ); } } diff --git a/stepmania/src/Player.h b/stepmania/src/Player.h index 3c6603f1b4..c04b60d70a 100644 --- a/stepmania/src/Player.h +++ b/stepmania/src/Player.h @@ -36,6 +36,56 @@ AutoScreenMessage( SM_ComboStopped ); AutoScreenMessage( SM_ComboContinuing ); AutoScreenMessage( SM_MissComboAborted ); +// Helper class to ensure that each row is only judged once without taking too much memory. +class JudgedRows +{ + char *m_pRows; + int m_iStart; + int m_iOffset; + int m_iLen; + + void Resize( int iMin ) + { + char *p = m_pRows; + int newSize = max( m_iLen*2, iMin ); + m_pRows = new char[newSize]; + int i = 0; + if( p ) + { + for( ; i < m_iLen; ++i ) + m_pRows[i] = p[(i+m_iOffset)%m_iLen]; + delete[] p; + } + m_iOffset = 0; + m_iLen = newSize; + memset( m_pRows + i, 0, newSize - i ); + //LOG->Trace( "New size %d.", newSize ); + } +public: + JudgedRows() : m_pRows(NULL), m_iStart(0), m_iOffset(0), m_iLen(0) { Resize( 32 ); } + ~JudgedRows() { delete[] m_pRows; } + bool operator[]( int iRow ) + { + if( iRow < m_iStart ) return true; + if( iRow >= m_iStart+m_iLen ) Resize( iRow+1-m_iStart ); + const bool ret = m_pRows[(iRow-m_iStart+m_iOffset)%m_iLen]; + m_pRows[(iRow-m_iStart+m_iOffset)%m_iLen] = 1; + while( m_pRows[m_iOffset] ) + { + m_pRows[m_iOffset] = 0; + ++m_iStart; + if( ++m_iOffset >= m_iLen ) m_iOffset -= m_iLen; + } + return ret; + } + void Reset() + { + m_iStart = m_iOffset = 0; + memset( m_pRows, 0, m_iLen ); + } +}; + + class Player: public ActorFrame { public: @@ -123,6 +173,7 @@ protected: int m_iRowLastCrossed; int m_iMineRowLastCrossed; int m_iRowLastJudged; // Everything up to and including this row has been judged. + JudgedRows m_JudgedRows; RageSound m_soundMine; RageSound m_soundAttackLaunch;