From c321bbe196139a98d7ddfc91b4d36d61ff0cff29 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 22 Jan 2005 01:37:32 +0000 Subject: [PATCH] start merging NoteDataWithScoring and NoteField per-hold and per-tap data into TapNote and HoldNote. This reduces lookup costs significantly. It's a bit simpler, though I'm not entirely happy with the resulting encapsulation ... --- stepmania/src/NoteDataWithScoring.cpp | 59 +-------------------------- stepmania/src/NoteDataWithScoring.h | 48 ---------------------- stepmania/src/NoteDisplay.cpp | 5 ++- stepmania/src/NoteField.cpp | 9 ++-- stepmania/src/NoteField.h | 3 -- stepmania/src/NoteTypes.cpp | 5 +++ stepmania/src/NoteTypes.h | 54 +++++++++++++++++++++++- stepmania/src/Player.cpp | 45 +++++++++++--------- 8 files changed, 91 insertions(+), 137 deletions(-) diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index 6c5f64a917..89a8909ca1 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -15,8 +15,6 @@ void NoteDataWithScoring::Init() for( int t=0; t hn.iStartRow || hn.iEndRow > iEndIndex ) continue; - if( GetHoldNoteScore(hn) == hns ) + if( hn.result.hns == hns ) iNumSuccessfulHolds++; } return iNumSuccessfulHolds; @@ -158,7 +156,6 @@ int NoteDataWithScoring::GetSuccessfulHands( float fStartBeat, float fEndBeat ) for( int j=0; jhns = hns; -} - -void NoteDataWithScoring::SetHoldNoteLife( const HoldNote &hn, float f ) -{ - HoldNoteResult *hnr = CreateHoldNoteResult( hn ); - hnr->fLife = f; -} - -float NoteDataWithScoring::GetHoldNoteLife( const HoldNote &hn ) const -{ - return GetHoldNoteResult(hn).fLife; -} - -const HoldNoteResult NoteDataWithScoring::GetHoldNoteResult( const HoldNote &hn ) const -{ - map::const_iterator it = m_HoldNoteScores.find( RowTrack(hn) ); - if( it == m_HoldNoteScores.end() ) - return HoldNoteResult(hn); - - return it->second; -} - -HoldNoteResult *NoteDataWithScoring::CreateHoldNoteResult( const HoldNote &hn ) -{ - map::iterator it = m_HoldNoteScores.find( RowTrack(hn) ); - if( it == m_HoldNoteScores.end() ) - { - HoldNoteResult *ret = &m_HoldNoteScores[hn]; - ret->iLastHeldRow = hn.iStartRow; - return ret; - } - return &it->second; -} - -HoldNoteResult::HoldNoteResult( const HoldNote &hn ) -{ - hns = HNS_NONE; - fLife = 1.0f; - iLastHeldRow = hn.iStartRow; -} - /* * (c) 2001-2004 Chris Danford, Glenn Maynard * All rights reserved. diff --git a/stepmania/src/NoteDataWithScoring.h b/stepmania/src/NoteDataWithScoring.h index fb2d126255..73760c6012 100644 --- a/stepmania/src/NoteDataWithScoring.h +++ b/stepmania/src/NoteDataWithScoring.h @@ -15,51 +15,10 @@ struct RowTrack: public pair RowTrack( const HoldNote &hn ): pair( hn.iEndRow, hn.iTrack ) { } }; -struct TapNoteResult -{ - TapNoteResult() - { - tns = TNS_NONE; - fTapNoteOffset = 0; - } - TapNoteScore tns; - - /* Offset, in seconds, for a tap grade. Negative numbers mean the note - * was hit early; positive numbers mean it was hit late. These values are - * only meaningful for graded taps (tns >= TNS_BOO). */ - float fTapNoteOffset; -}; - -struct HoldNoteResult -{ - HoldNoteScore hns; - - /* 1.0 means this HoldNote has full life. - * 0.0 means this HoldNote is dead - * When this value hits 0.0 for the first time, m_HoldScore becomes HSS_NG. - * If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HSS_OK. */ - float fLife; - - /* Last index where fLife was greater than 0. If the tap was missed, this will - * be the first index of the hold. */ - int iLastHeldRow; - - HoldNoteResult() - { - hns = HNS_NONE; - fLife = 1.0f; - iLastHeldRow = 0; - } - HoldNoteResult( const HoldNote &hn ); - - float GetLastHeldBeat() const { return NoteRowToBeat(iLastHeldRow); } -}; - class NoteDataWithScoring : public NoteData { // maintain this extra data in addition to the NoteData vector m_TapNoteScores[MAX_NOTE_TRACKS]; - map m_HoldNoteScores; public: NoteDataWithScoring(); @@ -76,13 +35,6 @@ public: float GetTapNoteOffset(unsigned track, unsigned row) const; void SetTapNoteOffset(unsigned track, unsigned row, float offset); - HoldNoteScore GetHoldNoteScore( const HoldNote &hn ) const; - void SetHoldNoteScore( const HoldNote &hn, HoldNoteScore hns ); - float GetHoldNoteLife( const HoldNote &hn ) const; - void SetHoldNoteLife( const HoldNote &hn, float f ); - const HoldNoteResult GetHoldNoteResult( const HoldNote &hn ) const; - HoldNoteResult *CreateHoldNoteResult( const HoldNote &hn ); - bool IsRowCompletelyJudged(unsigned row) const; TapNoteScore MinTapNoteScore(unsigned row) const; int LastTapNoteScoreTrack(unsigned row) const; diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index 7f931590c3..cab1456857 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -928,7 +928,8 @@ void NoteDisplay::DrawHold( const HoldNote& hn, bool bIsBeingHeld, bool bIsActiv int iCol = hn.iTrack; bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5; - float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, Result.GetLastHeldBeat() ); + float fStartBeat = NoteRowToBeat( max(hn.result.iLastHeldRow, hn.iStartRow) ); + float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fStartBeat ); // HACK: If active, don't allow the top of the hold to go above the receptor if( bIsActive ) @@ -946,7 +947,7 @@ void NoteDisplay::DrawHold( const HoldNote& hn, bool bIsBeingHeld, bool bIsActiv /* Hack: Z effects need a finer grain step. */ const int fYStep = WavyPartsNeedZBuffer? 4: 16; //bWavy ? 16 : 128; // use small steps only if wavy - const float fColorScale = 1*Result.fLife + (1-Result.fLife)*cache->m_fHoldNGGrayPercent; + const float fColorScale = 1*hn.result.fLife + (1-hn.result.fLife)*cache->m_fHoldNGGrayPercent; bool bFlipHeadAndTail = bReverse && cache->m_bFlipHeadAndTailWhenReverse; diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index b6d9bdbb53..c4d6df7511 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -117,9 +117,6 @@ void NoteField::Load( NoteDataWithScoring::Init(); - m_HeldHoldNotes.clear(); - m_ActiveHoldNotes.clear(); - this->CopyAll( *pNoteData ); ASSERT( GetNumTracks() == GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer ); @@ -564,7 +561,7 @@ void NoteField::DrawPrimitives() if( hn.iTrack != c ) // this HoldNote doesn't belong to this column continue; - const HoldNoteResult Result = GetHoldNoteResult( hn ); + const HoldNoteResult &Result = hn.result; if( Result.hns == HNS_OK ) // if this HoldNote was completed continue; // don't draw anything @@ -584,8 +581,8 @@ void NoteField::DrawPrimitives() continue; // skip } - const bool bIsActive = m_ActiveHoldNotes[hn]; - const bool bIsHoldingNote = m_HeldHoldNotes[hn]; + const bool bIsActive = hn.bActive; + const bool bIsHoldingNote = hn.bHeld; if( bIsActive ) SearchForSongBeat()->m_GhostArrowRow.SetHoldIsActive( hn.iTrack ); diff --git a/stepmania/src/NoteField.h b/stepmania/src/NoteField.h index a9e9cc66fb..ff899a8bdb 100644 --- a/stepmania/src/NoteField.h +++ b/stepmania/src/NoteField.h @@ -30,9 +30,6 @@ public: float fYReverseOffsetPixels ); virtual void Unload(); - map m_HeldHoldNotes; // true if button is being held down - map m_ActiveHoldNotes; // true if hold has life > 0 - float m_fBeginMarker, m_fEndMarker; // only used with MODE_EDIT void FadeToFail(); diff --git a/stepmania/src/NoteTypes.cpp b/stepmania/src/NoteTypes.cpp index 03079e3135..8cfcb741c3 100644 --- a/stepmania/src/NoteTypes.cpp +++ b/stepmania/src/NoteTypes.cpp @@ -76,6 +76,11 @@ bool IsNoteOfType( int row, NoteType t ) return GetNoteType(row) == t; } +float HoldNoteResult::GetLastHeldBeat() const +{ + return NoteRowToBeat(iLastHeldRow); +} + /* * (c) 2001-2004 Chris Danford, Glenn Maynard * All rights reserved. diff --git a/stepmania/src/NoteTypes.h b/stepmania/src/NoteTypes.h index 1ed288836b..35d4fd0d6a 100644 --- a/stepmania/src/NoteTypes.h +++ b/stepmania/src/NoteTypes.h @@ -1,6 +1,48 @@ #ifndef NOTE_TYPES_H #define NOTE_TYPES_H +#include "GameConstantsAndTypes.h" + +struct TapNoteResult +{ + TapNoteResult() + { + tns = TNS_NONE; + fTapNoteOffset = 0; + } + TapNoteScore tns; + + /* Offset, in seconds, for a tap grade. Negative numbers mean the note + * was hit early; positive numbers mean it was hit late. These values are + * only meaningful for graded taps (tns >= TNS_BOO). */ + float fTapNoteOffset; +}; + +struct HoldNoteResult +{ + HoldNoteScore hns; + + /* 1.0 means this HoldNote has full life. + * 0.0 means this HoldNote is dead + * When this value hits 0.0 for the first time, m_HoldScore becomes HSS_NG. + * If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HSS_OK. */ + float fLife; + + /* Last index where fLife was greater than 0. If the tap was missed, this will + * be the first index of the hold. */ + int iLastHeldRow; + + HoldNoteResult() + { + hns = HNS_NONE; + fLife = 1.0f; + iLastHeldRow = 0; + } + + float GetLastHeldBeat() const; +}; + + struct TapNote { enum Type { @@ -66,6 +108,10 @@ struct TapNote #undef COMPARE return true; } + + /* This data is only used and manipulated by NoteDataWithScoring. It's only in + * here for the sake of efficiency. */ + }; const unsigned MAX_NUM_ATTACKS = 2*2*2; // 3 bits to hold the attack index currently @@ -125,7 +171,7 @@ inline float NoteRowToBeat( int row ) { return NoteRowToBeat( (float)row ); } struct HoldNote { - HoldNote( int t, int s, int e ) { iTrack=t; iStartRow=s; iEndRow=e; } + HoldNote( int t, int s, int e ) { iTrack=t; iStartRow=s; iEndRow=e; bHeld = bActive = false; } bool RowIsInRange( int row ) const { return iStartRow <= row && row <= iEndRow; } bool RangeOverlaps( int start, int end ) const { @@ -145,6 +191,12 @@ struct HoldNote int iStartRow; int iEndRow; int iTrack; + + /* This data is only used and manipulated by NoteDataWithScoring. It's only in + * here for the sake of efficiency. */ + HoldNoteResult result; + bool bHeld; + bool bActive; }; #endif diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index fae6e73c71..76f0b8b802 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -340,16 +340,25 @@ void Player::Update( float fDeltaTime ) // for( int i=0; i < m_NoteData.GetNumHoldNotes(); i++ ) // for each HoldNote { - const HoldNote &hn = m_NoteData.GetHoldNote(i); - HoldNoteScore hns = m_NoteData.GetHoldNoteScore(hn); + HoldNote &hn = m_NoteData.GetHoldNote(i); + /* Find the associated hold note in m_pNoteField. */ + /* ack: this iterates over all hold notes */ + int iHN = m_pNoteField->GetMatchingHoldNote( hn ); + HoldNote &NoteFieldHoldNote = m_pNoteField->GetHoldNote( iHN ); + + + // set hold flags so NoteField can do intelligent drawing + hn.bHeld = false; + hn.bActive = false; if( m_pNoteField ) { - m_pNoteField->m_HeldHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing - m_pNoteField->m_ActiveHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing + NoteFieldHoldNote.bHeld = false; + NoteFieldHoldNote.bActive = false; } + HoldNoteScore hns = hn.result.hns; if( hns != HNS_NONE ) // if this HoldNote already has a result continue; // we don't need to update the logic for this one if( iSongRow < hn.iStartRow ) @@ -365,38 +374,34 @@ void Player::Update( float fDeltaTime ) const TapNoteScore tns = m_NoteData.GetTapNoteScore( hn.iTrack, hn.iStartRow ); const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this hold? - float fLife = m_NoteData.GetHoldNoteLife(hn); + float fLife = hn.result.fLife; bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ); // TODO: Make the CPU miss sometimes. if( m_pPlayerState->m_PlayerController != PC_HUMAN ) bIsHoldingButton = true; - if( bSteppedOnTapNote && bIsHoldingButton ) + if( bSteppedOnTapNote && fLife != 0 ) { /* This hold note is not judged and we stepped on its head. Update iLastHeldRow. * Do this even if we're a little beyond the end of the hold note, to make sure * iLastHeldRow is clamped to iEndRow if the hold note is held all the way. */ - HoldNoteResult *hnr = NULL; - if( m_pNoteField ) - { - hnr = m_pNoteField->CreateHoldNoteResult( hn ); - hnr->iLastHeldRow = min( iSongRow, hn.iEndRow ); - } + NoteFieldHoldNote.result.iLastHeldRow = min( iSongRow, hn.iEndRow ); - hnr = m_NoteData.CreateHoldNoteResult( hn ); - hnr->iLastHeldRow = min( iSongRow, hn.iEndRow ); + hn.result.iLastHeldRow = min( iSongRow, hn.iEndRow ); } // If the song beat is in the range of this hold: if( hn.RowIsInRange(iSongRow) ) { // set hold flag so NoteField can do intelligent drawing + hn.bHeld = bIsHoldingButton && bSteppedOnTapNote; + hn.bActive = bSteppedOnTapNote; if( m_pNoteField ) { - m_pNoteField->m_HeldHoldNotes[hn] = bIsHoldingButton && bSteppedOnTapNote; - m_pNoteField->m_ActiveHoldNotes[hn] = bSteppedOnTapNote; + NoteFieldHoldNote.bHeld = bIsHoldingButton && bSteppedOnTapNote; + NoteFieldHoldNote.bActive = bSteppedOnTapNote; } if( bSteppedOnTapNote && bIsHoldingButton ) @@ -452,12 +457,12 @@ void Player::Update( float fDeltaTime ) if( m_pNoteField ) { - m_pNoteField->SetHoldNoteLife(hn, fLife); // update the NoteField display - m_pNoteField->SetHoldNoteScore(hn, hns); // update the NoteField display + NoteFieldHoldNote.result.fLife = fLife; + NoteFieldHoldNote.result.hns = hns; } - m_NoteData.SetHoldNoteLife(hn, fLife); - m_NoteData.SetHoldNoteScore(hn, hns); + hn.result.fLife = fLife; + hn.result.hns = hns; } // TODO: Remove use of PlayerNumber.