Moving the clouds and the bee

Let's use the elapsed time since the last frame, to breathe life into the bee and the clouds. This will solve the problem of having a consistent frame rate across different PCs.

Giving life to the bee

The first thing we want to do is to set up the bee at a certain height and a certain speed. We only want to do this when the bee is inactive. So we wrap the next code in an if block. Examine and add the highlighted code, then we will discuss it:

/* 
**************************************** 
Update the scene 
**************************************** 
*/ 
 
// Measure time 
Time dt = clock.restart(); 
 
// Setup the bee
if (!beeActive)
{   
  // How fast is the bee
  srand((int)time(0));   
  beeSpeed = (rand() % 200) + 200;   

  // How high is the bee   
  srand((int)time(0) * 10);   
  float height = (rand() % 500) + 500;   
  spriteBee.setPosition(2000, height);   
  beeActive = true;
} 
 
/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 

Now, if the bee is not active, just like it won't be when the game first starts, if(!beeActive) will be true and the code above will do the following things, in this order:

  • Seed the random number generator
  • Get a random number between 199 and 399 and assign the result to beeSpeed
  • Seed the random number generator again
  • Get a random number between 499 and 999 and assign the result to a new float variable called height
  • Set the position of the bee to 2000 on the x axis (just off-screen to the right) and to whatever height equals on the y axis
  • Set beeActive to true

Note

Note that the height variable is the first variable we have ever declared inside the game loop. Furthermore, because it was declared inside an if block, it is actually "invisible" outside the if block. This is fine for our use because once we have set the height of the bee we don't need it any more. This phenomenon, which affects variables, is called scope. We will explore this more fully in Chapter 4: Loops, Arrays, Switch, Enumerations, and Functions - Implementing Game Mechanics.

If we run the game, nothing will actually happen to the bee yet, but now the bee is active we can write some code that runs when beeActive is true.

Add the following highlighted code, which, as you can see, executes whenever beeActive is true. This is because it follows with an else after the if(!beeActive) block:

// Set up the bee 
if (!beeActive) 
{ 
 
   // How fast is the bee 
   srand((int)time(0) ); 
   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
{   
  spriteBee.setPosition(     
    spriteBee.getPosition().x -      
    (beeSpeed * dt.asSeconds()),     
    spriteBee.getPosition().y);  
 
  // Has the bee reached the right hand edge of the screen?   
  if (spriteBee.getPosition().x < -100)   
  {    
    // Set it up ready to be a whole new cloud next frame     
    beeActive = false;   
  }
} 
 
/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 

In the else block the following things happen.

The bee position is changed using the following criteria. The setPosition function uses the getPosition function to get the current x coordinate of the bee. It then adds beeSpeed * dt.asSeconds() to that coordinate.

The beeSpeed variable value is many pixels per second and was randomly assigned in the previous if block. The value of dt.asSeconds() will be a fraction of 1 that represents how long the previous frame of the animation took.

Assume that the bee's current x coordinate is 1000. Now suppose a fairly basic PC loops at 5000 frames per second. This would mean that dt.asSeconds would be 0.0002. And further suppose that beeSpeed was set to the maximum 399 pixels per second. Then the code that determines the value that setPosition uses for the x coordinate can be explained like this:

1000 - 0.0002 x 399

So the new position on the x axis for the bee would be 999.9202. We can see that the bee is, very smoothly drifting to the left, at well under a pixel per frame. If the frame rate fluctuates then the formula will produce a new value to suit. If we run the same code on a PC that only achieves 100 frames per second or a PC that achieves a million frames per second, the bee will move at the same speed.

The setPosition function uses getPosition().y to keep the bee in exactly the same y coordinate throughout this cycle of being active.

The final code in the else block we just added is this:

// Has the bee reached the right hand edge of the screen? 
if (spriteBee.getPosition().x < -100) 
{ 
   // Set it up ready to be a whole new cloud next frame 
   beeActive = false; 
} 

This code tests each and every frame (when beeActive is true), whether the bee has disappeared off the left-hand side of the screen. If the getPosition function returns less than -100, it will certainly be out of view of the player. When this has occurred, beeActive is set to false and, on the next frame, a new bee will be set flying at a new random height and a new random speed.

Try running the game and watch our bee dutifully fly from right to left and then come back to the right again at a new height and speed. It's almost like a new bee every time.

Tip

Of course a real bee would stick around for ages and pester you while you're trying to concentrate on chopping the tree. We will make some smarter game characters in the next project.

Now we will get the clouds moving in a very similar way.

Blowing the clouds

The first thing we want to do is set up the first cloud at a certain height and a certain speed. We only want to do this when the cloud is inactive. So we wrap the next code in an if block. Examine and add the highlighted code, just after the code we added for the bee, then we will discuss it. It is almost identical to the code we used for the bee:

else 
// Move the bee 
{ 
 
   spriteBee.setPosition( 
      spriteBee.getPosition().x -  
      (beeSpeed * dt.asSeconds()), 
      spriteBee.getPosition().y); 
 
   // Has the bee reached the right hand edge of the screen? 
   if (spriteBee.getPosition().x < -100) 
   { 
      // Set it up ready to be a whole new bee next frame 
      beeActive = false; 
   } 
} 
 
// Manage the clouds
// Cloud 1
if (!cloud1Active)
{   
  // How fast is the cloud   
  srand((int)time(0) * 10);   
  cloud1Speed = (rand() % 200);  
 
  // How high is the cloud   
  srand((int)time(0) * 10);   
  float height = (rand() % 150);   
  spriteCloud1.setPosition(-200, height);   
  cloud1Active = true;
} 
 
/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 

The only difference between the code we have just added and the bee code is that we work on a different sprite and use different ranges for our random numbers. Also, we use *10 to the result returned by time(0) so we are always guaranteed to get a different seed for each of the clouds. When we code the other cloud movement next you will see that we use *20 and*30 respectively.

Now we can take action when the cloud is active. We will do so in the else block. As with the if block, the code is identical to that of the bee, except that all the code works on the cloud and not the bee:

// Manage the clouds 
if (!cloud1Active) 
{ 
 
   // How fast is the cloud 
   srand((int)time(0) * 10); 
   cloud1Speed = (rand() % 200); 
 
   // How high is the cloud 
   srand((int)time(0) * 10); 
   float height = (rand() % 150); 
   spriteCloud1.setPosition(-200, height); 
   cloud1Active = true; 
 
 
} 
else
{   
  spriteCloud1.setPosition(     
    spriteCloud1.getPosition().x +      
    (cloud1Speed * dt.asSeconds()),     
    spriteCloud1.getPosition().y);   

  // Has the cloud reached the right hand edge of the screen?   
  if (spriteCloud1.getPosition().x > 1920)   
  {     
    // Set it up ready to be a whole new cloud next frame     
    cloud1Active = false;   
  }
} 
 
/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 

Now we know what to do, we can duplicate the same code for the second and third clouds. Add this highlighted code that handles the second and third clouds, immediately after the code for the first cloud:

... 
 
// Cloud 2
if (!cloud2Active)
{   
  // How fast is the cloud   
  srand((int)time(0) * 20);   
  cloud2Speed = (rand() % 200);   
  // How high is the cloud   
  srand((int)time(0) * 20);   
  float height = (rand() % 300) - 150;   
  spriteCloud2.setPosition(-200, height);   
  cloud2Active = true;
}
else
{   
  spriteCloud2.setPosition(     
    spriteCloud2.getPosition().x +      
    (cloud2Speed * dt.asSeconds()),     
    spriteCloud2.getPosition().y);   
  // Has the cloud reached the right hand edge of the screen?   
  if (spriteCloud2.getPosition().x > 1920)   
  {     
    // Set it up ready to be a whole new cloud next frame     
    cloud2Active = false;   
  }
}
if (!cloud3Active)
{   
  // How fast is the cloud   
  srand((int)time(0) * 30);   
  cloud3Speed = (rand() % 200);   
  // How high is the cloud   
  srand((int)time(0) * 30);   
  float height = (rand() % 450) - 150;   
  spriteCloud3.setPosition(-200, height);   
  cloud3Active = true;
}
else
{   
  spriteCloud3.setPosition(     
    spriteCloud3.getPosition().x +      
    (cloud3Speed * dt.asSeconds()),     
    spriteCloud3.getPosition().y); 
  
  // Has the cloud reached the right hand edge of the screen?   
  if (spriteCloud3.getPosition().x > 1920)   
  {     
    // Set it up ready to be a whole new cloud next frame     
    cloud3Active = false;   
  }
} 
 
/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 

Now you can run the game and the clouds will randomly and continuously drift across the screen, and the bee will buzz from right to left before re-spawning once more back on the right.

Blowing the clouds

Tip

Does all this cloud and bee handling seem a little bit repetitious? We will see how we could save lots of typing and make our code more readable. In C++ there are ways of handling multiple instances of the same type of variable or object. These are called arrays and we will learn about them in Chapter 4: Loops, Arrays, Switch, Enumerations, and Functions - Implementing Game Mechanics. At the end of the project, once we have learnt about arrays, we will discuss how we could improve our cloud code.

Take a look at a few frequently asked questions related to the topics in this chapter.

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

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