summaryrefslogtreecommitdiffstats
path: root/game/code/gameflow
diff options
context:
space:
mode:
authorSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
committerSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
commiteb4b3404aa00220d659e532151dab13d642c17a3 (patch)
tree7e1107c4995489a26c4007e41b53ea8d00ab2134 /game/code/gameflow
downloadThe-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.gz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.bz2
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.lz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.xz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.zst
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.zip
Diffstat (limited to 'game/code/gameflow')
-rw-r--r--game/code/gameflow/allgameflow.cpp1
-rw-r--r--game/code/gameflow/gameflow.cpp377
-rw-r--r--game/code/gameflow/gameflow.h106
3 files changed, 484 insertions, 0 deletions
diff --git a/game/code/gameflow/allgameflow.cpp b/game/code/gameflow/allgameflow.cpp
new file mode 100644
index 0000000..870b94b
--- /dev/null
+++ b/game/code/gameflow/allgameflow.cpp
@@ -0,0 +1 @@
+#include <gameflow/gameflow.cpp>
diff --git a/game/code/gameflow/gameflow.cpp b/game/code/gameflow/gameflow.cpp
new file mode 100644
index 0000000..deb4bb1
--- /dev/null
+++ b/game/code/gameflow/gameflow.cpp
@@ -0,0 +1,377 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: gameflow.cpp
+//
+// Description: Implementation for GameFlow class.
+//
+// History: + Stolen and cleaned up from Penthouse -- Darwin Chau
+//
+//=============================================================================
+
+#define DONTCHECKVECTORRESIZING
+//========================================
+// System Includes
+//========================================
+#include <raddebug.hpp>
+#include <radtime.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include <gameflow/gameflow.h>
+
+#include <contexts/entrycontext.h>
+#include <contexts/bootupcontext.h>
+#include <contexts/frontendcontext.h>
+#include <contexts/pausecontext.h>
+#include <contexts/exitcontext.h>
+#include <contexts/gameplay/loadinggameplaycontext.h>
+#include <contexts/gameplay/gameplaycontext.h>
+#include <contexts/demo/loadingdemocontext.h>
+#include <contexts/demo/democontext.h>
+#include <contexts/supersprint/loadingsupersprintcontext.h>
+#include <contexts/supersprint/supersprintcontext.h>
+#include <contexts/supersprint/supersprintfecontext.h>
+
+#include <sound/soundmanager.h>
+#include <main/commandlineoptions.h>
+#include <main/game.h>
+#include <memory/memoryutilities.h>
+#include <memory/srrmemory.h>
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+//
+// Static pointer to instance of this singleton.
+//
+GameFlow* GameFlow::spInstance = NULL;
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// GameFlow::CreateInstance
+//==============================================================================
+//
+// Description: Create the gameflow controller.
+//
+// Parameters: None.
+//
+// Return: Pointer to the created gameflow controller.
+//
+// Constraints: This is a singleton so only one instance is allowed.
+//
+//==============================================================================
+GameFlow* GameFlow::CreateInstance()
+{
+MEMTRACK_PUSH_GROUP( "GameFlow" );
+ rAssert( spInstance == NULL );
+
+ spInstance = new(GMA_PERSISTENT) GameFlow;
+ rAssert( spInstance );
+MEMTRACK_POP_GROUP( "GameFlow" );
+
+ return spInstance;
+}
+
+
+//==============================================================================
+// GameFlow::GetInstance
+//==============================================================================
+//
+// Description: Return the gameflow controller.
+//
+// Parameters: None.
+//
+// Return: Pointer to the created gameflow controller.
+//
+//==============================================================================
+GameFlow* GameFlow::GetInstance()
+{
+ //rAssert( spInstance != NULL );
+
+ return spInstance;
+}
+
+
+//==============================================================================
+// GameFlow::DestroyInstance
+//==============================================================================
+//
+// Description: Destroy the gameflow controller.
+//
+// Parameters: None.
+//
+// Return: None.
+//
+//==============================================================================
+void GameFlow::DestroyInstance()
+{
+ rAssert( spInstance != NULL );
+
+ delete( GMA_PERSISTENT, spInstance );
+ spInstance = NULL;
+}
+
+
+//==============================================================================
+// GameFlow::PushContext
+//==============================================================================
+//
+// Description: Change the context. Pushes the new context onto the stack.
+// The previous context(s) are preserved on the stack.
+// Note: the new context will not take effect until the next
+// timer tick (game loop update).
+//
+// Parameters: context - the new context
+//
+// Return: None.
+//
+//==============================================================================
+void GameFlow::PushContext( ContextEnum context )
+{
+ //
+ // Really bad news if this assert triggers. There's already a context
+ // change in the queue when this one was requested.
+ //
+ // This assert cannot be ignored, you must fix the problem.
+ //
+ rAssert( mCurrentContext == mNextContext );
+
+MEMTRACK_PUSH_GROUP( "GameFlow" );
+ mNextContext = context;
+ mContextStack.push( context );
+MEMTRACK_POP_GROUP( "GameFlow" );
+}
+
+
+//==============================================================================
+// GameFlow::PopContext
+//==============================================================================
+//
+// Description: Restore the previous context.
+//
+// Note: the new context will not take effect until the next
+// timer tick (game loop update).
+//
+// Constraints: Obviously we have a problem if there's nothing on the stack.
+//
+// Parameters: None.
+//
+// Return: None.
+//
+//==============================================================================
+void GameFlow::PopContext()
+{
+ rAssert( mContextStack.size() > 1 );
+
+ //
+ // Really bad news if this assert triggers. There's already a context
+ // change in the queue when this one was requested.
+ //
+ // This assert cannot be ignored, you must fix the problem.
+ //
+ rAssert( mCurrentContext == mNextContext );
+
+ mContextStack.pop();
+ mNextContext = mContextStack.top();
+}
+
+
+//==============================================================================
+// GameFlow::SetContext
+//==============================================================================
+//
+// Description: Change the context and clear out the stack.
+//
+// Note: the new context will not take effect until the next
+// timer tick (game loop update).
+//
+// Parameters: context - the new context
+//
+// Return: None.
+//
+//==============================================================================
+void GameFlow::SetContext( ContextEnum context )
+{
+ while( !mContextStack.empty() )
+ {
+ mContextStack.pop();
+ }
+
+ this->PushContext( context );
+}
+
+
+//==============================================================================
+// GameFlow::OnTimerDone
+//==============================================================================
+//
+// Description: This routine is invoked to run the game. It gets called by the
+// dispatcher once per frame.
+//
+// Parameters: elapsedtime - time it actually took for timer to expire
+// pUserData - custom user data
+//
+// Return: None.
+//
+//==============================================================================
+void GameFlow::OnTimerDone( unsigned int elapsedtime, void* pUserData )
+{
+ //////////////////////////////////////////////////
+ // Debugging stuff.
+ //////////////////////////////////////////////////
+
+ bool printMemory = CommandLineOptions::Get( CLO_PRINT_MEMORY );
+ if( printMemory )
+ {
+ static int accumulatedTime = 0;
+ const int printTimeIntervalMs = 3000;
+ accumulatedTime += elapsedtime;
+ if( accumulatedTime > printTimeIntervalMs )
+ {
+ accumulatedTime %= printTimeIntervalMs;
+ Memory::PrintMemoryStatsToTty();
+ }
+ }
+
+ #ifndef RAD_RELEASE
+
+ // HACK to prevent elapsedtime from being ridiculously huge.
+ // This is so that when we set breakpoints we don't have really huge
+ // elapsedtime values screwing us up.
+ if( elapsedtime > 1000 )
+ {
+ elapsedtime = 20;
+ }
+
+ #endif
+
+ //////////////////////////////////////////////////
+ // Switch contexts if appropriate.
+ //////////////////////////////////////////////////
+
+ // If current and next contexts are different...
+ if( mCurrentContext != mNextContext )
+ {
+ mpContexts[mCurrentContext]->Stop( mNextContext );
+ mpContexts[mNextContext]->Start( mCurrentContext );
+
+ mCurrentContext = mNextContext;
+ }
+
+ //////////////////////////////////////////////////
+ // See if have anything to update.
+ //////////////////////////////////////////////////
+
+ // If current context is exit, then stop the game.
+ if( mCurrentContext == CONTEXT_EXIT )
+ {
+ GetGame()->Stop();
+ return;
+ }
+
+ //////////////////////////////////////////////////
+ // Update managers and controllers.
+ //////////////////////////////////////////////////
+
+ //
+ // Run the once-per-frame sound update
+ //
+ SoundManager::GetInstance()->UpdateOncePerFrame( elapsedtime, mCurrentContext );
+
+ // Update the current context.
+ mpContexts[mCurrentContext]->Update( elapsedtime );
+}
+
+
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+
+//==============================================================================
+// GameFlow::GameFlow
+//==============================================================================
+//
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================//
+GameFlow::GameFlow() :
+ mpITimer( NULL ),
+ mCurrentContext( CONTEXT_ENTRY ),
+ mNextContext( CONTEXT_ENTRY )
+{
+ //
+ // Initialize members.
+ //
+ int i = CONTEXT_ENTRY;
+ for( ; i < NUM_CONTEXTS; ++i )
+ {
+ mpContexts[i] = NULL;
+ }
+
+ //
+ // Create the context controllers.
+ //
+ mpContexts[CONTEXT_ENTRY] = GetEntryContext();
+ mpContexts[CONTEXT_BOOTUP] = GetBootupContext();
+ mpContexts[CONTEXT_FRONTEND] = GetFrontEndContext();
+ mpContexts[CONTEXT_LOADING_DEMO] = GetLoadingDemoContext();
+ mpContexts[CONTEXT_DEMO] = GetDemoContext();
+ mpContexts[CONTEXT_LOADING_SUPERSPRINT] = GetLoadingSuperSprintContext();
+ mpContexts[CONTEXT_SUPERSPRINT] = GetSPCTX();
+ mpContexts[CONTEXT_SUPERSPRINT_FE] = GetSuperSprintFEContext();
+ mpContexts[CONTEXT_LOADING_GAMEPLAY] = GetLoadingGameplayContext();
+ mpContexts[CONTEXT_GAMEPLAY] = GetGameplayContext();
+ mpContexts[CONTEXT_PAUSE] = GetPauseContext();
+ mpContexts[CONTEXT_EXIT] = GetExitContext();
+
+ //
+ // Since we're starting with the entry context, call its Start function
+ // for the sake of symmetry and to allow memory tagging to work properly
+ //
+ mpContexts[mCurrentContext]->Start( mCurrentContext );
+}
+
+//==============================================================================
+// GameFlow::~GameFlow
+//==============================================================================
+//
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================//
+GameFlow::~GameFlow()
+{
+ //
+ // Release the context controllers.
+ //
+ int i = CONTEXT_ENTRY;
+ for( ; i < NUM_CONTEXTS; ++i )
+ {
+ rAssert( mpContexts[i] != NULL );
+ mpContexts[i]->DestroyInstance();
+ }
+}
+
+#undef DONTCHECKVECTORRESIZING \ No newline at end of file
diff --git a/game/code/gameflow/gameflow.h b/game/code/gameflow/gameflow.h
new file mode 100644
index 0000000..6a0f83a
--- /dev/null
+++ b/game/code/gameflow/gameflow.h
@@ -0,0 +1,106 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// Component: GameFlow
+//
+// Description: The GameFlow Controller orchestrates the overall game execution.
+//
+// History: + Stolen and cleaned up from Penthouse -- Darwin Chau
+//
+//=============================================================================
+
+#ifndef GAMEFLOW_H
+#define GAMEFLOW_H
+
+//========================================
+// System Includes
+//========================================
+#include <vector>
+#include <stack>
+
+#include <radtime.hpp> // IRadTimerCallback
+
+//========================================
+// Project Includes
+//========================================
+#include <contexts/contextenum.h>
+#include <memory/stlallocators.h>
+
+//========================================
+// Forward References
+//========================================
+class Context;
+
+
+//=============================================================================
+//
+// Synopsis: The game "loop"
+//
+//=============================================================================
+class GameFlow : public IRadTimerCallback
+{
+ public:
+
+ // Static Methods (for creating and getting an instance of the game)
+ static GameFlow* CreateInstance();
+ static GameFlow* GetInstance();
+ static void DestroyInstance();
+
+ // Functions to change the context.
+ void PushContext( ContextEnum context );
+ void PopContext();
+ void SetContext( ContextEnum context );
+
+ // Implement IRadTimerCallback interface.
+ // This member is called whenever the timer expires.
+ void OnTimerDone( unsigned int elapsedtime, void* pUserData );
+
+ ContextEnum GetCurrentContext() const { return mCurrentContext; }
+ ContextEnum GetNextContext() const { return mNextContext; }
+
+ Context* GetContext( ContextEnum which ) const { return mpContexts[which]; }
+/*
+ bool GetQuickStartLoading( void ) const { return mQuickStartLoading; }
+ void SetQuickStartLoading( bool IsQuickStartLoading ) { mQuickStartLoading = IsQuickStartLoading; }
+*/
+ private:
+
+ // Declared but not defined to prevent copying and assignment.
+ GameFlow( const GameFlow& );
+ GameFlow& operator=( const GameFlow& );
+
+ // Constructor - these are private to prevent anybody else from
+ // creating me.
+ GameFlow();
+ virtual ~GameFlow();
+
+ // This member is called when the gameflow is being initialized.
+ void Initialize();
+
+ // The one and only GameFlow instance.
+ static GameFlow* spInstance;
+
+ // Timer for gameflow updates.
+ IRadTimer* mpITimer;
+
+ // Contexts
+ ContextEnum mCurrentContext;
+ ContextEnum mNextContext;
+
+ typedef std::vector< ContextEnum, s2alloc<ContextEnum> > ContextEnumSequence;
+ typedef std::stack< ContextEnum, ContextEnumSequence > ContextStack;
+
+ ContextStack mContextStack;
+
+ Context* mpContexts[NUM_CONTEXTS];
+ bool mQuickStartLoading : 1;
+};
+
+
+//
+// A little syntactic sugar for getting at this singleton.
+//
+inline GameFlow* GetGameFlow() { return( GameFlow::GetInstance() ); }
+
+
+#endif