fix long hold + boomerang artifacts: didn't draw if neither the head nor the tail were on-screen, tail bottom would be positioned above the head causing the hold to magically grow once the tail comes on screen

This commit is contained in:
Chris Danford
2005-04-07 06:41:02 +00:00
parent 77e33f21e0
commit 1e7d4001a8
4 changed files with 60 additions and 16 deletions
+21 -3
View File
@@ -25,8 +25,13 @@ static float GetNoteFieldHeight( const PlayerState* pPlayerState )
/* For visibility testing: if bAbsolute is false, random modifiers must return the
* minimum possible scroll speed. */
float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, bool bAbsolute )
float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, float &fPeakYOffsetOut, bool &bIsPastPeakOut, bool bAbsolute )
{
// Default values that are returned if boomerang is off.
fPeakYOffsetOut = FLT_MAX;
bIsPastPeakOut = true;
float fYOffset = 0;
/* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or
@@ -84,9 +89,22 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float
fYOffset += fYAdjust;
//
// Factor in boomerang
//
if( fAccels[PlayerOptions::ACCEL_BOOMERANG] > 0 )
fYOffset += fAccels[PlayerOptions::ACCEL_BOOMERANG] * (fYOffset * SCALE( fYOffset, 0.f, SCREEN_HEIGHT, 1.5f, 0.5f )- fYOffset);
{
float fOriginalYOffset = fYOffset;
fYOffset = (-1*fOriginalYOffset*fOriginalYOffset/SCREEN_HEIGHT) + 1.5*fOriginalYOffset;
float fPeakAtYOffset = SCREEN_HEIGHT * 0.75; // zero point of function above
fPeakYOffsetOut = (-1*fPeakAtYOffset*fPeakAtYOffset/SCREEN_HEIGHT) + 1.5*fPeakAtYOffset;
bIsPastPeakOut = fOriginalYOffset < fPeakAtYOffset;
}
//
// Factor in scroll speed
//
float fScrollSpeed = pPlayerState->m_CurrentPlayerOptions.m_fScrollSpeed;
if( pPlayerState->m_CurrentPlayerOptions.m_fRandomSpeed > 0 && !bAbsolute )
{
@@ -119,11 +137,11 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float
}
fYOffset *= fScrollSpeed;
fPeakYOffsetOut *= fScrollSpeed;
return fYOffset;
}
void ArrowGetReverseShiftAndScale( const PlayerState* pPlayerState, int iCol, float fYReverseOffsetPixels, float &fShiftOut, float &fScaleOut )
{
/* XXX: Hack: we need to scale the reverse shift by the zoom. */
+7 -1
View File
@@ -12,7 +12,13 @@ public:
// fYOffset is a vertical position in pixels relative to the center.
// (positive if has not yet been stepped on, negative if has already passed).
// The ArrowEffect and ScrollSpeed is applied in this stage.
static float GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, bool bAbsolute=false );
static float GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, float &fPeakYOffsetOut, bool &bIsPastPeakYOffset, bool bAbsolute=false );
static float GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, bool bAbsolute=false )
{
float fThrowAway;
bool bThrowAway;
return GetYOffset( pPlayerState, iCol, fNoteBeat, fThrowAway, bThrowAway, bAbsolute );
}
/* Actual display position, with reverse and post-reverse-effects factored in
* (fYOffset -> YPos). */
+21 -7
View File
@@ -986,20 +986,34 @@ void NoteDisplay::DrawHoldHead( const TapNote& tn, int iCol, int iRow, const boo
void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeingHeld, bool bIsActive, const HoldNoteResult &Result, float fPercentFadeToFail, bool bDrawGlowOnly, float fReverseOffsetPixels, float fYStartOffset, float fYEndOffset )
{
int iEndBeat = iRow + tn.iDuration;
int iEndRow = iRow + tn.iDuration;
// bDrawGlowOnly is a little hacky. We need to draw the diffuse part and the glow part one pass at a time to minimize state changes
bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f;
float fStartBeat = NoteRowToBeat( max(tn.HoldResult.iLastHeldRow, iRow) );
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 )
fStartYOffset = 0;
float fThrowAway = 0;
// HACK: If active, don't set YOffset to 0 so that it doesn't jiggle around the receptor.
bool bStartIsPastPeak = true;
float fStartYOffset = 0;
if( bIsActive )
; // use the default values filled in above
else
fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fStartBeat, fThrowAway, bStartIsPastPeak );
float fStartYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fStartYOffset, fReverseOffsetPixels );
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, NoteRowToBeat(iEndBeat) );
float fEndPeakYOffset = 0;
bool bEndIsPastPeak = false;
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, NoteRowToBeat(iEndRow), fEndPeakYOffset, bEndIsPastPeak );
// In boomerang, the arrows reverse direction at Y offset value fPeakAtYOffset.
// If fPeakAtYOffset lies inside of the hold we're drawing, then the we
// want to draw the tail at that max Y offset, or else the hold will appear
// to magically grow as the tail approaches the max Y offset.
if( bStartIsPastPeak && !bEndIsPastPeak )
fEndYOffset = fEndPeakYOffset; // use the calculated PeakYOffset so that long holds don't appear to grow
float fEndYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fEndYOffset, fReverseOffsetPixels );
const float fYHead = bReverse ? fEndYPos : fStartYPos; // the center of the head
+11 -5
View File
@@ -572,12 +572,18 @@ void NoteField::DrawPrimitives()
// TRICKY: If boomerang is on, then all notes in the range
// [iFirstIndexToDraw,iLastIndexToDraw] aren't necessarily visible.
// Test every note to make sure it's on screen before drawing
float fYStartOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iStartRow) );
float fYEndOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iEndRow) );
if( !( iFirstPixelToDraw <= fYEndOffset && fYEndOffset <= iLastPixelToDraw ||
iFirstPixelToDraw <= fYStartOffset && fYStartOffset <= iLastPixelToDraw ||
fYStartOffset < iFirstPixelToDraw && fYEndOffset > iLastPixelToDraw ) )
float fThrowAway;
bool bStartIsPastPeak = false;
bool bEndIsPastPeak = false;
float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iStartRow), fThrowAway, bStartIsPastPeak );
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iEndRow), fThrowAway, bEndIsPastPeak );
bool bTailIsOnVisible = iFirstPixelToDraw <= fEndYOffset && fEndYOffset <= iLastPixelToDraw;
bool bHeadIsVisible = iFirstPixelToDraw <= fStartYOffset && fStartYOffset <= iLastPixelToDraw;
bool bStraddlingVisible = bStartIsPastPeak && !bEndIsPastPeak;
if( !(bTailIsOnVisible || bHeadIsVisible || bStraddlingVisible) )
{
//LOG->Trace( "skip drawing this hold." );
continue; // skip
}