C++ Fast Track for Games Programming Part 5: Conditions

C++ Fast-track

C++ Fast-track for Games Programming Part 5: Conditions

This tutorial is about the condition commands C/C++ has which allow you to make automated decisions in your program. You already used conditions when you did loops (perhaps without realising it), but in this episode we will look at more explicit conditions.

Previous Part: Sprites and LoopsNext Part: Floats

Getting the stuff you need

For this tutorial, you will be using the same template from the 2nd tutorial:

TheTemplate.zip TheTemplate.zip

As in the previous episodes, we’ll use the template again. But you will need to know how to use your sprites from our last adventure – so if you have not done that one please go back and do so now.

Extract a fresh version of the template to a folder (for example, C:\Projects\conditions or wherever you saved your projects from the previous tutorials), remove the hello world code from the Game::Tick function, and then we’re ready to begin.

Your Game::Tick function should look like this now:

void Game::Tick(float deltaTime)
{

}
Rename the Project Files (Optional)

At this point you probably have several projects that are all called tmpl_2019-08, which can get annoying, especially if you have several projects open at once.

You can quite easily rename your project:

  1. First, make sure Visual Studio is closed.
  2. Then, run clean.bat file that is in the root folder of the template project. This script removes all of the files that are regenerated by Visual Studio when you recompile the project. It reduces the size of the folder and gets rid of clutter.
  3. Next, rename the project files: tmpl_2019-08.sln becomes e.g. myproject.sln; tmpl_2019-08.vcxproj becomes myproject.vcxproj and tmpl_2019-08.vcxproj.filters becomes myproject.vcxproj.filters. Make sure you use the same name each time (in this case, myproject).
  4. Now, right-click myproject.sln, select Open With, and use Notepad (or Notepad++) to edit the file. You will see that tmpl_2019-08.vcxproj is mentioned in there; replace this by myproject.vcxproj.
  5. Optionally, replace Template by something else, e.g. Conditions. If you do this, you also need to open myproject.vcxproj in Notepad. Look for a line that reads Template and replace Template by Conditions here as well.

Now open the .sln file with Visual Studio again. Remember, Visual Studio is just a tool, and we just gained a bit more control over it.

To Bounce or not to Bounce

In your Game::Tick loop from the last lesson, you put a sprite on screen. Let’s do that again.

Add a Sprite variable above the Game::Tick function:

Sprite theSprite(new Surface("assets/ball.png"), 1);
void Game::Tick(float deltaTime)
{
    ...

Make your Game::Tick function look like this:

void Game::Tick( float deltaTime )
{
    screen->Clear( 0 );
    theSprite.Draw( screen, 0, 0 );
}

Try and run this and make sure you get an image of a ball in the top-left corner of the screen.

Ball in top-left corner of the screen.

Ball in top-left corner of the screen.

Let’s move our Sprite down a little bit and then move it around using your variable skills. Above the Tick function and below the Sprite definition add a couple of global variables.

Sprite theSprite(new Surface("assets/ball.png"), 1);
int spriteX = 0;
int spriteY = 100;
int speed = 1;
void Game::Tick(float deltaTime)
{
    ...

Hopefully these variable names will explain their function. Notice also that each variable is set to an initial value.

Now let’s alter the Game::Tick function a little:

void Game::Tick( float deltaTime )
{
    screen->Clear( 0 );
    theSprite.Draw( screen, spriteX, spriteY );
}

Run this and you should see your sprite is now drawn a little lower in the screen.

Ball slighter lower on the screen.

Ball slighter lower on the screen.

Now let’s make the sprite move. Add two lines to the Game::Tick function:

void Game::Tick(float deltaTime)
{
    screen->Clear(0);
    theSprite.Draw(screen, spriteX, spriteY);
    spriteY += speed;
    speed += 1;
}

Now the sprite quickly leaves the bottom of the screen. It would be nice obviously if it would bounce back at the bottom… That’s where conditions come in. If it has reached the bottom of the screen is a condition, and we can actually use something very close to that in our code:

    if (spriteY > (512 - 50))
    {
        spriteY = 512 - 50;
        speed = -speed;
    }

That looks simple enough, but there’s a lot of detail in there.

First, 512: That’s the bottom of the screen, but sprites are positioned relative to their upper-left corner. The sprite we use has a height of 50 pixels, so we can make it bounce on the bottom of the screen when the sprite’s Y coordinate is greater than (512 - 50).

Next, lines 39-40 is the code that is executed if the condition is true. On line 39 the Y-coordinate of the sprite is reset to be exactly at the bottom of the screen in case the sprite has traveled farther than the bottom of the screen.

On line 40, the speed is inverted which causes the ball to move in the opposite direction.

You may have noticed that there are parentheses around (512 - 50) on line 37. Why? Well, we want to compare spriteY against the result of 512 - 50, instead of subtracting 50 from the result of spriteY > 512.

Read more about operator precedence here: Operator Precedence in C++. Are the parenthesis really needed in this case?

Or Else

To add a bit of drama to the bouncing, we can flash the background when the ball hits the bottom of the screen. Try this:

void Game::Tick( float deltaTime )
{
    spriteY += speed;
    speed++;
    if (spriteY > (512 - 50))
    {
        spriteY = 512 - 50;
        speed = -speed;
        screen->Clear( 0xff0000 );
        theSprite.Draw( screen, spriteX, spriteY );
    }
    else
    {
        screen->Clear( 0 );
        theSprite.Draw( screen, spriteX, spriteY );
    }
}

This time, we have two code blocks related to the condition. The second block is executed when the condition is false.

Booleans

In many programming languages, true and false are boolean values. We can store these in a bool variable:

    bool hitBottom = spriteY > 512 - 50; 
    if (hitBottom) { … }

Interesting question is of course how the computer stores these values in memory. Let’s try to gain some insight. Modify your Tick so that it uses the hitBottom boolean. Then, print the boolean to the text window:

    void Game::Tick(float deltaTime)
    {
        spriteY += speed;
        speed++;
        bool hitBottom = spriteY > (512 - 50);
        printf("hitBottom: %i\n", hitBottom);
        if (hitBottom)
        {
            ...

Run the program, and bring the console window into focus. Things move fast, but if you watch carefully, you will see that false apparently equals 0, and true equals 1. In C/C++, this works both ways: 0 is false, and anything that is not 0 is true.

So:

    int a = 1000, b = -1000;
    if (a && b)
    {
        printf("both true.\n");
    }

will print both true to the console window which implies that both a and b are true. Not directly useful, but now you know. 🙂

Assignment

Let’s combine some things from the last couple of episodes.

Add a variable speedX to make the ball move horizontally as well. Use this to make the ball bounce from the left to the right side of the screen. When it reaches the right side, make it deflect on the right wall so it starts moving back to the left. After, say, 50 bounces, stop testing the screen bottom collision, so that the ball falls through and disappears.

Previous Part: Sprites and LoopsNext Part: Floats

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.