Adding a time bar

As time is a crucial mechanic in the game, it is necessary to keep the player aware of it. He needs to know if his allotted six seconds are about to run out. It will give him a sense of urgency as the end of the game draws near, and a sense of accomplishment if he performs well enough to maintain or increase his remaining time.

Drawing the number of seconds remaining on the screen is not easy to read (when concentrating on the branches) or a particularly interesting way to achieve the objective.

What we need is a time bar. Our time bar will be a simple red rectangle, prominently displayed on the screen. It will start off nice and wide, but rapidly shrink as time runs out. When the player's remaining time reaches zero, the time bar will be gone completely.

At the same time as adding the time bar, we will add the necessary code to keep track of the player's remaining time, as well as to respond when he runs out. Let's go through it a step at a time.

Find the Clock clock; declaration from earlier and add the highlighted code:

// Variables to control time itself 
Clock clock; 
 
// Time bar
RectangleShape timeBar;
float timeBarStartWidth = 400;
float timeBarHeight = 80;
timeBar.setSize(Vector2f(timeBarStartWidth, timeBarHeight));
timeBar.setFillColor(Color::Red);
timeBar.setPosition((1920 / 2) - timeBarStartWidth / 2, 980);

Time gameTimeTotal;
float timeRemaining = 6.0f;
float timeBarWidthPerSecond = timeBarStartWidth / timeRemaining; 
 
// Track whether the game is running 
bool paused = true; 

First we declare an object of the type RectangleShape and call it timeBar. RectangleShape is an SFML class that is perfect for drawing simple rectangles.

Next we add a few float variables, timeBarStartWidth and timeBarHeight. We initialize them to 400 and 80 respectively. These variables will help us keep track of the size we need to draw the timeBar each frame.

Next we set the size of the timeBar using the timeBar.setSize function. We don't just pass in our two new float variables. First we create a new object of type Vector2f. What is different here, however, is that we don't give the new object a name. We simply initialize it with our two float variables and it is passed straight in to the setSize function.

Tip

Vector2f is a class which holds two float variables. It also has some other functionality that will be introduced throughout the book.

After that we color the timeBar red by using the setFillColor function.

The last thing we do to the timeBar, in the previous code, is to set its position. The y coordinate is completely straightforward, but the way we set the x coordinate is slightly convoluted. Here is the calculation again:

(1920 / 2) - timeBarStartWidth / 2

The code first divides 1920 by 2. Then it divides timeBarStartWidth by 2. Finally it subtracts the latter from the former.

The result makes the timeBar sit nice and horizontally centered on the screen.

The final three lines of code that we are talking about declare a new Time object called gameTimeTotal, a new float called timeRemaining that is initialized to 6, and a curious-sounding float named timeBarWidthPerSecond which we will discuss further.

The timeBarWidthPerSecond variable is initialized with timeBarStartWidth divided by timeRemaining. The result is exactly the amount of pixels that the timeBar needs to shrink by, each second of the game. This will be useful when we resize the timeBar in each frame.

Obviously we need to reset the time remaining each time the player starts a new game. The logical place to do this is the Enter key press. We can also set the score back to zero at the same time. Let's do that now by adding this highlighted code:

// Start the game 
if (Keyboard::isKeyPressed(Keyboard::Return)) 
{ 
   paused = false; 
 
   // Reset the time and the score   
   score = 0;   
   timeRemaining = 5; 
 } 

Now, each frame we must reduce the amount of time remaining and resize the timeBar accordingly. Add the following highlighted code in the update section as shown here:

/* 
**************************************** 
Update the scene 
**************************************** 
*/ 
if (!paused) 
{ 
   // Measure time 
   Time dt = clock.restart(); 
 
   // Subtract from the amount of time remaining   
   timeRemaining -= dt.asSeconds();
   // size up the time bar
   timeBar.setSize(Vector2f(timeBarWidthPerSecond *
     timeRemaining, timeBarHeight)); 
 
   // Set up the bee 
   if (!beeActive) 
   { 
 
      // How fast is the bee 
      srand((int)time(0) * 10); 
      beeSpeed = (rand() % 200) + 200; 
 
      // How high is the bee 
      srand((int)time(0) * 10); 
      float height = (rand() % 1350) + 500; 
      spriteBee.setPosition(2000, height); 
      beeActive = true; 
 
   } 
   else 
      // Move the bee 

First we subtracted the amount of time the player has left by however long the previous frame took to execute with this code:

timeRemaining -= dt.asSeconds(); 

Then we adjusted the size of the timeBar with the following code:

timeBar.setSize(Vector2f(timeBarWidthPerSecond * 
      timeRemaining, timeBarHeight)); 

The x value of the Vector2F is initialized with timebarWidthPerSecond multiplied by timeRemaining. This produces exactly the correct width, relative to how long the player has left. The height remains the same and timeBarHeight is used without any manipulation.

And, of course, we must detect when time has run out. For now, we will simply detect that time has run out, pause the game, and change the text of the messageText. Later we will do more work here. Add the highlighted code right after the previous code we added, and we will look at it in more detail:

// Measure time 
Time dt = clock.restart(); 
 
// Subtract from the amount of time remaining 
timeRemaining -= dt.asSeconds(); 
 
// resize up the time bar 
timeBar.setSize(Vector2f(timeBarWidthPerSecond * 
   timeRemaining, timeBarHeight)); 
 
if (timeRemaining <= 0.0f) 
{   
  // Pause the game   
  paused = true;   

  // Change the message shown to the player   
  messageText.setString("Out of time!!");   

  //Reposition the text based on its new size   
  FloatRect textRect = messageText.getLocalBounds();
  messageText.setOrigin(textRect.left +     
    textRect.width / 2.0f,     
    textRect.top +     
    textRect.height / 2.0f);   

  messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);
} 
 
// Set up the bee 
if (!beeActive) 
{ 
 
   // How fast is the bee 
   srand((int)time(0) * 10); 
   beeSpeed = (rand() % 200) + 200; 
 
   // How high is the bee 
   srand((int)time(0) * 10); 
   float height = (rand() % 1350) + 500; 
   spriteBee.setPosition(2000, height); 
   beeActive = true; 
 
} 
else 
   // Move the bee 

Stepping through the previous code:

  • First we test whether time has run out with if(timeRemaining <= 0.0f)
  • Then we set paused to true so this will be the last time the update part of our code is executed (until the player presses Enter again).
  • Then we change the message of messageText, calculate its new center to set it as its origin, and position it in the center of the screen.

Finally, for this part of the code, we need to draw the timeBar. There is nothing new in this code that we haven't seen many times before. Just note that we draw the timeBar after the tree, so it is visible. Add the highlighted code to draw the time bar:

// Draw the score 
window.draw(scoreText); 
 
// Draw the timebar
window.draw(timeBar); 
 
if (paused) 
{ 
   // Draw our message 
   window.draw(messageText); 
} 
 
// Show everything we just drew 
window.display(); 

Now you can run the game. Press Enter to start, and watch the time bar smoothly disappear down to nothing.

Adding a time bar

The game then pauses and the OUT OF TIME!! message will appear.

Adding a time bar

You can, of course, press Enter again to start the whole thing running from the start.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.51.191