A splash menu adds a touch of class to your game and also does a little bragging. Typically, the splash screen shows off your company logo. In fact, many game projects have multiple studios that work on them, so there are often multiple splash screens. We will use just one!
It is important to get the splash screen up and running as soon as possible, so we will do that before we perform any other loading. Part of the function of a splash screen is to give the player something pretty to look at while the rest of the game is loading.
It's up to you to create a splash screen that defines your game. For convenience, we have included one in the code resource package for this chapter called splash.png
. Make sure you copy splash.png
into your project. The only requirement for the splash image is that it is 800 x 600 pixels, the same resolution as our game screen.
As with all images in this game, we will implement the splash screen as a sprite. Declare the splash sprite at the top of RoboRacer2D.cpp
:
Sprite* splashScreen;
We also want to define some timers for the splash screen:
float splashDisplayTimer; float splashDisplayThreshold;
As we want to define the splash screen separately, we will create a separate function just to load it. Create the LoadSplash
function using the following code:
void LoadSplash() { m_gameState = GameState::GS_Splash; splashScreen = new Sprite(1); splashScreen->SetFrameSize(800.0f, 600.0f); splashScreen->SetNumberOfFrames(1); splashScreen->AddTexture("resources/splash.png", false); splashScreen->IsActive(true); splashScreen->IsVisible(true); }
We are not going to make a significant change to the StartGame
function. We are going to only load the splash screen, and defer loading the other game resources. This will get our splash screen up as soon as possible. Change the StartGame
function so that it looks like the following code:
void StartGame() { LoadSplash(); inputManager = new Input(hWnd); uiTimer = 0.0f; srand(time(NULL)); pickupSpawnThreshold = 3.0f; pickupSpawnTimer = 0.0f; enemySpawnThreshold = 7.0f; enemySpawnTimer = 0.0f; splashDisplayTimer = 0.0f; splashDisplayThreshold = 5.0f; }
Notice that we only load the splash resources and set a few variables here. We also set the splash timer so that it will show up for at least five seconds.
Next, modify the GS_Splash
case in the Update
function to look like the following code:
switch (m_gameState) { case GameState::GS_Splash: case GameState::GS_Loading: { splashScreen->Update(p_deltaTime); splashDisplayTimer += p_deltaTime; if (splashDisplayTimer > splashDisplayThreshold) { m_gameState = GameState::GS_Menu; } } break;
This code updates the splash timer. When the timer exceeds our threshold, then the game state changes to GS_Menu
. We will define the code to load the next menu.
Modify the GS_Splash
case in the Render
function to look like the following code:
case GameState::GS_Loading:
splashScreen->Render();
break;
If you have been paying attention, then you should realize that we removed the LoadTextures
call from the StartGame
function. Instead, we are going to load the textures in the GameLoop
function. Change GameLoop
so that it looks like the following code:
void GameLoop(const float p_deltatTime) { if (m_gameState == GameState::GS_Splash) { LoadTextures(); m_gameState = GameState::GS_Loading; } Update(p_deltatTime); Render(); }
If you recall, GameLoop
is called every frame. We need GameLoop
to be running to display our splash screen, which we have already loaded. But on the first call to GameLoop
, we haven't loaded our other resources.
We check to see whether our game state is GS_Splash
. If it is, we call load textures, and immediately change the game state to GS_Loading
. If we didn't change the game state, then the game would attempt to load the textures every frame, which would be a very bad thing! This is another practical example of why we define different game states in our state machine.
In a way, we haven't created a true splash screen. That is because our splash still depends on Windows and OpenGL initializing before the splash screen can even be loaded and rendered. True splash screens use a snippet of code that does not depend on all of this initialization so that they can load before everything else. Unfortunately, that level of detail is beyond the scope of our book. Sometimes, the splash screen will run on a separate thread so that it is independent of the startup code.
When you run the game now, you should see the splash screen display, but then nothing else happens. This is because we changed the game state to GS_Menu
in the Update
function, and we have not coded for that game state yet! If you want to test your splash screen, change m_gameState = GameState::GS_Menu
to m_gameState = GameState::GS_Running
in the Update
function. Just don't forget to change it back before you move on.
18.119.104.160