Beginning C++ Game Programming
上QQ阅读APP看书,第一时间看更新

Adding clouds, a tree, and a buzzing bee

In this section, we will add clouds, a tree, and a buzzing bee to our Timber!!! game. First, we will add a tree. This is going to be easy. The reason for this is because the tree doesn't move. We will use the same procedure that we used in the previous chapter when we drew the background. The bee and the clouds will also be easy to draw in their starting positions, but we will need to combine what we have just learned about manipulating variables with some new C++ topics to make them move.

Preparing the tree

Let's get ready to draw the tree! Add the following highlighted code. Notice the unhighlighted code, which is the code we have already written. This should help you to identify that the new code should be typed immediately after we set the position of the background but before the start of the main game loop. We will provide a recap regarding what is going on in the new code after we have added it:

int main()

{

    // Create a video mode object

    VideoMode vm(1920, 1080);

    // Create and open a window for the game

    RenderWindow window(vm, "Timber!!!", Style::Fullscreen);

    // Create a texture to hold a graphic on the GPU

    Texture textureBackground;

    // Load a graphic into the texture

    textureBackground.loadFromFile("graphics/background.png");

    // Create a sprite

    Sprite spriteBackground;

    // Attach the texture to the sprite

    spriteBackground.setTexture(textureBackground);

    // Set the spriteBackground to cover the screen

    spriteBackground.setPosition(0, 0);

    // Make a tree sprite

    Texture textureTree;

    textureTree.loadFromFile("graphics/tree.png");

    Sprite spriteTree;

    spriteTree.setTexture(textureTree);

    spriteTree.setPosition(810, 0);

    

    while (window.isOpen())

    {

This is what the following five lines of code (excluding the comment) do:

  1. First, we create an object of the Texture type called textureTree.
  2. Next, we load a graphic into the texture from the tree.png graphics file.
  3. Then, we declare an object of the Sprite type called spriteTree
  4. After, we associate textureTree with spriteTree. Whenever we draw spriteTree, it will show the textureTree texture, which is a neat tree graphic.
  5. Finally, we set the position of the tree using the coordinates 810 on the x axis and 0 on the y axis.

The tree sprite is ready to draw, along with the tree texture. Let's move on to the bee object, which is handled in an almost identical manner.

Preparing the bee

Preparing the bee sprite is very similar but not identical to preparing the tree sprite. The difference between the following code and the tree code is small but important. Since the bee needs to move, we also declare two bee-related variables. Add the following highlighted code and see whether you can work out how we might use the beeActive and beeSpeed variables:

// Make a tree sprite

Texture textureTree;

textureTree.loadFromFile("graphics/tree.png");

Sprite spriteTree;

spriteTree.setTexture(textureTree);

spriteTree.setPosition(810, 0);

// Prepare the bee

Texture textureBee;

textureBee.loadFromFile("graphics/bee.png");

Sprite spriteBee;

spriteBee.setTexture(textureBee);

spriteBee.setPosition(0, 800);

// Is the bee currently moving?

bool beeActive = false;

// How fast can the bee fly

float beeSpeed = 0.0f;

while (window.isOpen())

{

We create a bee in the same way we created a background and a tree. We use a Texture, a Sprite, and associate the two. Note that, in the previous bee code, there's some new code we haven't seen before. There is a bool variable for determining whether the bee is active. Remember that a bool variable can be either true or false. We initialize beeActive to false for now.

Next, we declare a new float variable called beeSpeed. This will hold the speed in pixels per second that our bee will fly across the screen at.

Soon, we will see how we use these two new variables to move the bee. Before we do, let's set up some clouds in an almost identical manner.

Preparing the clouds

Add the following highlighted code. Study the new code and try and work out what it will do:

// Prepare the bee

Texture textureBee;

textureBee.loadFromFile("graphics/bee.png");

Sprite spriteBee;

spriteBee.setTexture(textureBee);

spriteBee.setPosition(0, 800);

// Is the bee currently moving?

bool beeActive = false;

// How fast can the bee fly

float beeSpeed = 0.0f;

// make 3 cloud sprites from 1 texture

Texture textureCloud;

// Load 1 new texture

textureCloud.loadFromFile("graphics/cloud.png");

// 3 New sprites with the same texture

Sprite spriteCloud1;

Sprite spriteCloud2;

Sprite spriteCloud3;

spriteCloud1.setTexture(textureCloud);

spriteCloud2.setTexture(textureCloud);

spriteCloud3.setTexture(textureCloud);

// Position the clouds on the left of the screen

// at different heights

spriteCloud1.setPosition(0, 0);

spriteCloud2.setPosition(0, 250);

spriteCloud3.setPosition(0, 500);

// Are the clouds currently on screen?

bool cloud1Active = false;

bool cloud2Active = false;

bool cloud3Active = false;

// How fast is each cloud?

float cloud1Speed = 0.0f;

float cloud2Speed = 0.0f;

float cloud3Speed = 0.0f;

while (window.isOpen())

{

The only thing about the code we have just added that might seem a little odd is that we have only one object of the Texture type. It is completely normal for multiple Sprite objects to share a texture. Once a Texture is stored in GPU memory, it can be associated with a Sprite object very quickly. It is only the initial loading of the graphic in the loadFromFile code that is a relatively slow operation. Of course, if we wanted three different shaped clouds, then we would need three textures.

Apart from the minor texture issue, the code we have just added is nothing new compared to the bee. The only difference is that there are three cloud sprites, three bool variables to determine whether each cloud is active, and three float variables to hold the speed for each cloud.

At this stage, all of the sprites and variables have been prepared. We can now move on to drawing them.

Drawing the tree, the bee, and the clouds

Finally, we can draw them all to the screen by adding the following highlighted code in the drawing section:

/*

****************************************

Draw the scene

****************************************

*/

// Clear everything from the last run frame

window.clear();

// Draw our game scene here

window.draw(spriteBackground);

// Draw the clouds

window.draw(spriteCloud1);

window.draw(spriteCloud2);

window.draw(spriteCloud3);

// Draw the tree

window.draw(spriteTree);

// Draw the insect

window.draw(spriteBee);

// Show everything we just drew

window.display();

Drawing the three clouds, the bee, and the tree is done in the same way that the background was drawn. Note, however, the order in which we draw the different objects to the screen. We must draw all of the graphics after the background, or they will be covered, and we must draw the clouds before the tree, or they will look a bit odd drifting in front of the tree. The bee would look OK either in front or behind the tree. I opted to draw the bee in front of the tree so that it can try and distract our lumberjack, a bit like a real bee might.

Run Timber!!! and gaze in awe at the tree, three clouds, and a bee that… don't do anything! They look like they are lining up for a race; a race where the bee has to go backward:

Using what we know about operators, we could try and move the graphics we have just added, but there's a problem. The problem is that real clouds and bees move in a non-uniform manner. They don't have a set speed or location, with these elements determined by factors such as wind speed or how much of a hurry the bee might be in. To the casual observer, the path they take and their speed appear to be random.