diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index a70652bcd4..30eba612d7 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -1653,6 +1653,8 @@ AAFF41A40F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = AAFF41A20F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h */; }; AAFF41A50F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAFF41A10F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.cpp */; }; AAFF41A60F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = AAFF41A20F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h */; }; + B75CE3B5137963350076A82D /* SongPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = B75CE3B3137963350076A82D /* SongPosition.h */; }; + B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B75CE3B4137963350076A82D /* SongPosition.cpp */; }; EE2153A910A75BEE0074B01B /* NotesLoaderPMS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */; }; EE2153AA10A75BEE0074B01B /* NotesLoaderPMS.h in Headers */ = {isa = PBXBuildFile; fileRef = EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */; }; EE879B60132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE879B5C132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp */; }; @@ -3017,6 +3019,8 @@ AAFF55220549F43A00D02EE9 /* ComboGraph.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ComboGraph.h; path = ../src/ComboGraph.h; sourceTree = ""; }; AAFF5541054E736D00D02EE9 /* Attack.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; name = Attack.cpp; path = ../src/Attack.cpp; sourceTree = ""; }; AAFF5542054E736D00D02EE9 /* Attack.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = Attack.h; path = ../src/Attack.h; sourceTree = ""; }; + B75CE3B3137963350076A82D /* SongPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SongPosition.h; path = ../src/SongPosition.h; sourceTree = SOURCE_ROOT; }; + B75CE3B4137963350076A82D /* SongPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SongPosition.cpp; path = ../src/SongPosition.cpp; sourceTree = SOURCE_ROOT; }; EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderPMS.cpp; path = ../src/NotesLoaderPMS.cpp; sourceTree = SOURCE_ROOT; }; EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderPMS.h; path = ../src/NotesLoaderPMS.h; sourceTree = SOURCE_ROOT; }; EE879B5C132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RageDisplay_Legacy_Helpers.cpp; path = ../src/RageDisplay_Legacy_Helpers.cpp; sourceTree = SOURCE_ROOT; }; @@ -3925,6 +3929,8 @@ AA7CDD930D8395F90001DAFC /* Song.h */, AA6EFE0704770C79005F316C /* SongOptions.cpp */, AA6EFE0804770C79005F316C /* SongOptions.h */, + B75CE3B4137963350076A82D /* SongPosition.cpp */, + B75CE3B3137963350076A82D /* SongPosition.h */, AA5C73F90637A5F000AFB891 /* SongUtil.cpp */, AA5C73FA0637A5F000AFB891 /* SongUtil.h */, AAEBF57C0B5C83F4005F3C7C /* SoundEffectControl.cpp */, @@ -5042,6 +5048,7 @@ 2BC6132D13773C8E00CC8BBD /* pngpriv.h in Headers */, 2BC6133313773C8E00CC8BBD /* pngstruct.h in Headers */, 2BC6133E13773D2C00CC8BBD /* pnglibconf.h in Headers */, + B75CE3B5137963350076A82D /* SongPosition.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6301,6 +6308,7 @@ 2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */, 2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */, 2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */, + B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/GameState.cpp b/src/GameState.cpp index 90792cad8c..6f3dc9f6a0 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -951,53 +951,13 @@ static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) { - if( !timestamp.IsZero() ) - m_LastBeatUpdate = timestamp; - else - m_LastBeatUpdate.Touch(); + + m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); - // xxx testing: only do this on monotune survivor - /* - if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) - LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); - */ - - timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); - // "Crash reason : -243478.890625 -48695.773438" - ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); - - m_fMusicSeconds = fPositionSeconds; - - m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds ); - - m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); - - m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); - float fThrowAway, fThrowAway2; - bool bThrowAway; - int iThrowAway; - timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); - - /* - // xxx testing: only do this on monotune survivor - if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) - { - // and only do it in the known negative bpm region. HACKITY HACK - if(m_fSongBeat >= 445.490f && m_fSongBeat <= 453.72f) - { - LOG->Trace( ssprintf("fPositionSeconds = %f",fPositionSeconds) ); - LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); - //LOG->Trace( ssprintf("Music seconds visible %f = fPositionSeconds %f - g_fVisualDelaySeconds %f", m_fMusicSecondsVisible,fPositionSeconds,g_fVisualDelaySeconds.Get()) ); - } - else if(m_fSongBeat == 445.500f) - { - LOG->Trace( ssprintf("[beat 445.500] fPositionSeconds = %f",fPositionSeconds) ); - LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); - } - } - */ - - Actor::SetBGMTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fPositionSeconds, m_fSongBeatNoOffset ); + FOREACH_EnabledPlayer( pn ) + m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); + + Actor::SetBGMTime( m_Position.m_fMusicSecondsVisible, m_Position.m_fSongBeatVisible, m_Position.fPositionSeconds, m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } diff --git a/src/GameState.h b/src/GameState.h index 406e4784b1..9b192156c3 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -10,6 +10,7 @@ #include "RageTimer.h" #include "PlayerOptions.h" #include "SongOptions.h" +#include "SongPosition.h" #include "Preference.h" #include @@ -194,29 +195,9 @@ public: bool m_bBackedOutOfFinalStage; // Music statistics: - // Arcade - the current stage (one song). - // Oni/Endless - a single song in a course. - // Let a lot of classes access this info here so they don't have to keep their own copies. - // todo: [NUM_PLAYERS] this for split bpm lolol -aj - float m_fMusicSeconds; // time into the current song, not scaled by music rate - float m_fSongBeat; - float m_fSongBeatNoOffset; - float m_fCurBPS; - float m_fLightSongBeat; // g_fLightsFalloffSeconds ahead - //bool m_bStop; // in the middle of a stop (freeze or delay) - /** @brief A flag to determine if we're in the middle of a freeze/stop. */ - bool m_bFreeze; - /** @brief A flag to determine if we're in the middle of a delay (Pump style stop). */ - bool m_bDelay; - /** @brief The row used to start a warp. */ - int m_iWarpBeginRow; - /** @brief The beat to warp to afterwards. */ - float m_fWarpDestination; - RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update - BroadcastOnChange m_bGameplayLeadIn; + SongPosition m_Position; - float m_fMusicSecondsVisible; - float m_fSongBeatVisible; + BroadcastOnChange m_bGameplayLeadIn; // if re-adding noteskin changes in courses, add functions and such here -aj void GetAllUsedNoteSkins( vector &out ) const; diff --git a/src/Player.cpp b/src/Player.cpp index 95353c1669..1843553ade 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -506,7 +506,7 @@ void Player::Load() m_LastTapNoteScore = TNS_None; // The editor can start playing in the middle of the song. - const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ); + const int iNoteRow = BeatToNoteRowNotRounded( m_pPlayerState->m_Position.m_fSongBeat ); m_iFirstUncrossedRow = iNoteRow - 1; m_pJudgedRows->Reset( iNoteRow ); @@ -695,7 +695,7 @@ void Player::Update( float fDeltaTime ) return; } - const float fSongBeat = GAMESTATE->m_fSongBeat; + const float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); // Optimization: Don't spend time processing the things below that won't show @@ -797,7 +797,7 @@ void Player::Update( float fDeltaTime ) // Check for a strum miss if( m_pPlayerState->m_fLastStrumMusicSeconds != -1 && - m_pPlayerState->m_fLastStrumMusicSeconds + g_fTimingWindowStrum < GAMESTATE->m_fMusicSeconds ) + m_pPlayerState->m_fLastStrumMusicSeconds + g_fTimingWindowStrum < m_pPlayerState->m_Position.m_fMusicSeconds ) { DoStrumMiss(); } diff --git a/src/PlayerState.h b/src/PlayerState.h index 6df9dc662d..59239ca915 100644 --- a/src/PlayerState.h +++ b/src/PlayerState.h @@ -3,6 +3,7 @@ #ifndef PlayerState_H #define PlayerState_H +#include "SongPosition.h" #include "Attack.h" #include "ModsGroup.h" #include "PlayerNumber.h" @@ -38,6 +39,9 @@ public: */ MultiPlayer m_mp; + // Music statistics: + SongPosition m_Position; + /** * @brief Change the PlayerOptions to their default. * @param l the level of mods to reset. diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp new file mode 100644 index 0000000000..c3e6c30ffc --- /dev/null +++ b/src/SongPosition.cpp @@ -0,0 +1,63 @@ +/* + * SongPosition.cpp + * stepmania + * + * Created by [Full Username] on 5/10/11. + * Copyright 2011 [Organization Name]. All rights reserved. + * + */ + +#include "SongPosition.h" + +void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) +{ + + if( !timestamp.IsZero() ) + m_LastBeatUpdate = timestamp; + else + m_LastBeatUpdate.Touch(); + + // xxx testing: only do this on monotune survivor + /* + if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) + LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); + */ + + timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); + + // "Crash reason : -243478.890625 -48695.773438" + ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); + + m_fMusicSeconds = fPositionSeconds; + + m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds ); + + m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); + + m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); + float fThrowAway, fThrowAway2; + bool bThrowAway; + int iThrowAway; + timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); + + /* + // xxx testing: only do this on monotune survivor + if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) + { + // and only do it in the known negative bpm region. HACKITY HACK + if(m_fSongBeat >= 445.490f && m_fSongBeat <= 453.72f) + { + LOG->Trace( ssprintf("fPositionSeconds = %f",fPositionSeconds) ); + LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); + //LOG->Trace( ssprintf("Music seconds visible %f = fPositionSeconds %f - g_fVisualDelaySeconds %f", m_fMusicSecondsVisible,fPositionSeconds,g_fVisualDelaySeconds.Get()) ); + } + else if(m_fSongBeat == 445.500f) + { + LOG->Trace( ssprintf("[beat 445.500] fPositionSeconds = %f",fPositionSeconds) ); + LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); + } + } + */ + + +} diff --git a/src/SongPosition.h b/src/SongPosition.h new file mode 100644 index 0000000000..8890e3a87d --- /dev/null +++ b/src/SongPosition.h @@ -0,0 +1,69 @@ +#ifndef SONGPOSITION_H +#define SONGPOSITION_H + +#include "GameConstantsAndTypes.h" +#include "RageTimer.h" +#include "LightsManager.h" +#include "MessageManager.h" +#include "TimingData.h" + +class SongPosition +{ + + public: + + // Arcade - the current stage (one song). + // Oni/Endless - a single song in a course. + // Let a lot of classes access this info here so they don't have to keep their own copies. + // todo: [NUM_PLAYERS] this for split bpm lolol -aj + float m_fMusicSeconds; // time into the current song, not scaled by music rate + float m_fSongBeat; + float m_fSongBeatNoOffset; + float m_fCurBPS; + float m_fLightSongBeat; // g_fLightsFalloffSeconds ahead + //bool m_bStop; // in the middle of a stop (freeze or delay) + /** @brief A flag to determine if we're in the middle of a freeze/stop. */ + bool m_bFreeze; + /** @brief A flag to determine if we're in the middle of a delay (Pump style stop). */ + bool m_bDelay; + /** @brief The row used to start a warp. */ + int m_iWarpBeginRow; + /** @brief The beat to warp to afterwards. */ + float m_fWarpDestination; + RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update + + float m_fMusicSecondsVisible; + float m_fSongBeatVisible; + + void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); + +}; + +#endif + +/** + * @file + * @author Chris Danford, Glenn Maynard (c) 2001-2004 + * @section LICENSE + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */