In this mini-project we will get to experiment with how we can use C++ variables in our games. We will play around with some float variables and see how they can be used with the SFML CircleShape class to put circles on the screen. We will then see how we can use what we learnt in the manipulating C++ game variables tutorial to move them around the screen. Kind of like giant pong (without the paddles). If you don’t know what a class is yet it doesn’t matter. We will see some neat things in action but learn about what is going on behind the scenes in a later tutorial.

[widgets_on_pages id=”udemy_advert_cpp_1″][widgets_on_pages id=”udemy_code_details”]

About this project

Skill level 1
Time to complete 30 minutes

New concepts

  • Using C++ variables
  • Changing C++ variables
  • Using a Visual Studio project template
  • Another look at the main game loop
  • Brief introduction SFML event handling
  • SFML CircleShape
  • SFML setFillColor

To get started we need to create a new project complete with all the required properties to work with SFML. If you haven’t completed the Building your first SFML game project you will need to do that first. In that last project we created a Visual Studio project template so that starting a new SFML project is now a two minute job instead of a half an hour long chore.

Open Visual Studio and from the main menu choose File | New Project. In the left-hand menu click C++ and you will see the following options.

using_visual_studio_template_for _sfml_game_project

 

Select the HelloSFML template as highlighted in the previous image. Name your project Variables Demo as also highlighted in the above image. Now click OK.

Right-click the HelloSFML.cpp file under the Source Files heading from the right-hand Solution Explorer window. Choose Rename and rename the file to Main. This is a more appropriate name as this will indeed be our “main” source file. Open Main.cpp by double-clicking it. Now delete all of its contents as we will be starting fresh and discussing all of the code as well.

The only thing we need to do now is to copy all the .dll files to the current project’s working folder.

[widgets_on_pages id=”bcgp_cfgp_gpp”]

Copying the .dll files to the project folder

My project folder is D:\Visual Studio Stuff\Projects\Variables Demo\Variables Demo. The files we need to copy into there are located at D:\SFML\bin. Of course, if you installed Visual Studio and the Visual Studio Stuff folder on a different drive then replace D: from the previous paths with your appropriate drive letter. Open a window for each of the two locations and highlight the required files as shown in the next screenshot on the left.

copy_sfml_dll_files_to_project_directory

 

Copy & paste the files in the YOUR_DRIVE:\SFML\bin to YOUR_DRIVE:\Visual Studio Stuff\Projects\Variables Demo\Variables Demo. Don’t drag and drop them because that will move them and they will be harder to find when we do the next project.

The  actual Code

Add the entire starting code for this variables demo by copy and pasting the code below. Unlike when we were just doing a “hello world” SFML project, this time, we will discuss all sections of the code. Some aspects like variables, because they are the real topic of this mini-project, we will make sure we know exactly what is going on. Some of the other aspects we will look at from a distance just to get a feel for what is happening and then revisit them after we have completed the related C++ tutorials.

Be sure to read all of the comments and the code. It won’t all make sense but that doesn’t matter as we will break it down into chunks and go through it all soon. Here is the code to copy and paste into Main.cpp.

// Anything after // is a comment not actual C++ code
// Comments are important and I use them to explain things
// Why not read the comments in this code

// These "include" code from the C++ library and SFML too
#include "stdafx.h"
#include <SFML/Graphics.hpp>

// This is the main C++ program- Duh!
// It is where our game starts from
int main()
{
	// Make a window that is 800 by 600 pixels
	// And has the title "Variables Demo"
	sf::RenderWindow window(sf::VideoMode(800, 600), "Variables Demo");

	// Make three circles with 50 pixels radius
	// called circleRed, circle Green and circleBlue
	sf::CircleShape circleRed(50);
	sf::CircleShape circleGreen(50);
	sf::CircleShape circleBlue(50);

	// Color the circles appropriately
	circleRed.setFillColor(sf::Color(255, 0, 0));
	circleGreen.setFillColor(sf::Color(0, 255, 0));
	circleBlue.setFillColor(sf::Color(0, 0, 255));

	// Here's the variables stuff
	float xGreen = 200;
	float yGreen = 200;

	float xBlue = 300;
	float yBlue = 300;

	// Position the red circle at x,y 100,100 "Hard-coded"
	circleRed.setPosition(100, 100);

	// Position the green circle at the postion -
	// stored in xGreen and yGreen
	circleGreen.setPosition(xGreen, yGreen);

	// Position the blue circle at the postion -
	// stored in xBlue and yBlue
	circleBlue.setPosition(xBlue, yBlue);

	// Now all our circles are ready to draw -
	// we can enter the main game loop
	// This "while" loop goes round and round...
	// until player closes window
	while (window.isOpen())
	{
		// The next 6 lines of code detect if the window is closed
		// And then shuts down the program
		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				// Someone closed the window- bye
				window.close();
		}
                // End user input detection

		// Clear everything from the last run of the while loop
		window.clear();

		// Process game logic, AI, movement etc
		// We will add some new code here in a minute!!!!!!

        // End of new code

		// Draw our game scene here
		//Draw the cirlces
		window.draw(circleRed);
		window.draw(circleGreen);
		window.draw(circleBlue);

		// Show everything on the screen
		window.display();

	}// This is the end of the "while" loop

	return 0;
}

Running the demo

Now click the button shown in the next image to run our Variables Demo project.

sfml_run_hello_world_app

 

Wow, three circles!

sfml_project_drawing_circles

 

Wouldn’t it be cool to make them move? We will soon by manipulating the variables but first, let’s understand the code we have written so far.

Explaining the code block by block

At the top of the Main.cpp file we have a bunch of comments and then we have two #include directives. These make available other files into our project. Sometimes we will add #include directives for code that we have written ourselves and other times, like now we include other people’s code. The stdafx.h file is a usual suspect of a Windows program and nothing to do with games. I suggest for now you just accept that we need it but if you’re really curious you could do a Web search for its purpose.

More interesting is the SFML/Graphics.hpp file. This is a header file. We know it is a header file because of its .hpp file extension. Header files are the files where we declare the format of the C++ code which does the actual work. This sounds a bit odd but will make sense when we learn about functions in a later tutorial. The reason we need to include Graphics.hpp is because it declares some SFML classes and  functions which we use in this project.

At this stage, we can think of a class as a container for our code and we can think of a function as part of a class which performs a specific task. CircleShape is a class in this header file,  setFillColor and setPosition are both functions from this header file. We will look more closely at these soon in this tutorial. Take another look at the code we have just discussed.

// Anything after // is a comment not actual C++ code
// Comments are important and I use them to explain things
// Why not read the comments in this code

// These "include" code from the C++ library and SFML too
#include "stdafx.h"
#include <SFML/Graphics.hpp>

 

This next code is where the code begins execution from. When the player double-clicks on our .exe in a finished game or we click the Local Windows Debugger button, this is where it starts from. All C++ programs have an  main() entry point. Actually main is itself a function.

// This is the main C++ program- Duh!
// It is where our game starts from
int main()
{
    ...

 

In the next block of code, we see the slightly daunting sf::RenderWindow window(sf::VideoMode(800, 600), "Variables Demo"); line of code. For now, we just need to know that it will create a window that is 800 pixels by 600 pixels and has a title of Variables Demo.

Next, we create three circles. Or, more specifically three CircleShape objects. The exact way this works isn’t important at this stage except that the code is able to make these CircleShape objects because we #included Graphics.hpp. What is more important to us right now is that these three CircleShape objects have names, very much like we have variables with names we can also create objects, from classes and give them a name. The names are circleRed, circleGreen and circleBlue. The 50 inside the brackets () is the radius we would like our CircleShape objects to have, in pixels. Try changing one of them now and re-run the project. Don’t worry about understanding objects and classes, just note that we have three CircleShapes with names.

Study the code we have just discussed one more time.

// Make a window that is 800 by 600 pixels
// And has the title "Variables Demo"
sf::RenderWindow window(sf::VideoMode(800, 600), "Variables Demo");

// Make three circles with 50 pixels radius
// called circleRed, circle Green and circleBlue
sf::CircleShape circleRed(50);
sf::CircleShape circleGreen(50);
sf::CircleShape circleBlue(50);

 

In the next block of code, you can see we use our object names followed by setFillColor. As mentioned previously, setFillColor is a function (code that does something) and we are able to use that function on each of our three objects. When we do this we say we are calling the function. Basically, we are executing the C++ code in that function. Notice in the brackets following the

Notice in the brackets following the setFillColor function call it looks a little convoluted but each has a set of three numbers. These three numbers are values for red, green and blue respectively. We can think of this as a mixing palette. And depending upon the amounts of each color that are mixed in determines the color that is made. The setFillColor function then makes the circle in question into that color. Each RGB color value ranges from 0 (none of that color) to 255 (strongest possible value of that color). So, 255,0,0 makes red; 0,255,0 makes green and 0,0,255 makes blue. Understanding the RGB color model at this point isn’t important. If you just about get that calling setFillColor on a CircleShape object allows you to set its color we can move on.

Study the code block we have just discussed and then we will look at the next bit of code.

// Color the circles appropriately
circleRed.setFillColor(sf::Color(255, 0, 0));
circleGreen.setFillColor(sf::Color(0, 255, 0));
circleBlue.setFillColor(sf::Color(0, 0, 255));

 

In the next block of code, we are initializing our four float variables with values, just like we did in the Game variables in C++ tutorial. What is more interesting is how we put those variables to work in the code block that comes after it. Make sure you are comfortable with initializing the variables in this next block of code then move on.

// Here's the variables stuff
float xGreen = 200;
float yGreen = 200;

float xBlue = 300;
float yBlue = 300;

 

Now we see the setPosition function being called on each of our CircleShape objects in turn. When we call setPosition on circleRed we use the values 100, 100. These values are passed to the setPosition function and circleRed will be drawn at the screen coordinates 100 pixels on the x-axis and 100 pixels on the y-axis.

Next, we call setPosition on the circleGreen object. The difference here is that we don’t use actual, real values; we use variables that contain values. circleGreen.setPosition(xGreen, yGreen) will draw the circle at 200 pixels on the x-axis and 200 pixels on the y-axis. This is because the xGreen and yGreen variables store the values 200 and 200. At first glance a commonly asked question might be, “Why bother with the variables? We could have just passed in the values 200, 200″.

The simple answer is that when we use variables instead of hard-coded values, we can change them while the game is actually running.

Let’s quickly finish explaining the last few blocks of code then we will see how this helps us. After circleGreen.setPosition is called using the xGreen and yGreen variables we then call circleBlue.setPosition with the xBlue and yBlue variables. As these two variables were both initialized to 300 the position of the circle is set to the x and y-axes accordingly. Study the code we have just discussed.

// Position the red circle at x,y 100,100 "Hard-coded"
circleRed.setPosition(100, 100);

// Position the green circle at the postion -
// stored in xGreen and yGreen
circleGreen.setPosition(xGreen, yGreen);

// Position the blue circle at the postion -
// stored in xBlue and yBlue
circleBlue.setPosition(xBlue, yBlue);

 

We are going to brush over this next code until we have covered a later tutorial. Here is the important parts explained. The code while (window.isOpen()) is the start of the main game loop which is repeated over and over again. It processes all the ai, physics, user input and draws the scene. We will aim to keep this loop running at around 60 frames per second (FPS).  For now, with this simple code, it is more likely running at thousands of frames per second.

There is another loop within this loop that begins while (window.pollEvent(/event)). This short code loops through all the messages that might have been received from the operating system. Sometimes there will be zero messages, other times there might be many. We can choose which ones we care about and respond to them. It is here where we will handle the player’s input, moving the game character, quitting, etc. In this code, we just handle what happens when the player closes the window and quits the program. To properly understand this code we need to learn a bit more C++ but take a look at it anyway the code isn’t entirely unfathomable.

// Now all our circles are ready to draw -
// we can enter the main game loop
// This "while" loop goes round and round...
// until player closes window
while (window.isOpen())
{
	// The next 6 lines of code detect if the window is closed
	// And then shuts down the program
	sf::Event event;
	while (window.pollEvent(event))
	{
		if (event.type == sf::Event::Closed)
			// Someone closed the window- bye
			window.close();
	}
        // End user input detection</pre>

 

Now we clear whatever we drew in the last frame with window.clear(). Then we draw our circles  circleRed, circleGreen and circleBlue by calling window.draw for each circle in turn. Remember that at this point our program has already executed the code to color and position these circles. Also remember when we run this code; although we are looking at three static circles they are actually being rubbed out and redrawn thousands of times per second.

The final bit of code in this block is the closing } of the while loop that started with  while (window.isOpen()).

Study this next code and as you do identify the code comments that say // We will add some more code here in a minute!!!!!! and the next code comment that says // End of new code. It is between these two lines that we will add some more code soon. Study the code we have just discussed.

	// Clear everything from the last run of the while loop
	window.clear();

	// Process game logic, AI, movement etc
	// We will add some more code here in a minute!!!!!!

    // End of new code

	// Draw our game scene here
	//Draw the cirlces
	window.draw(circleRed);
	window.draw(circleGreen);
	window.draw(circleBlue);

	// Show everything on the screen
	window.display();

}// This is the end of the "while" loop

 

The return 0 line of code quits the entire program. So when we call window.close() the main game loop ends and execution comes to this line and it’s all over. We will explore how the loop control works in more detail in a later tutorial.

	return 0;
}

Making the circles move

[widgets_on_pages id=”udemy_advert_cpp_2″][widgets_on_pages id=”udemy_code_details”]
Now add this next block of code between  // We will add some more code here in a minute!!!!!! and the next code comment that says // End of new code.

// We will add some more code here in a minute!!!!!!

// Let's manipulate our coordinates variables
// Increase xGreen by one hundreth each game frame
xGreen = xGreen + .01;
// Decrease yGreen by one hundreth each game frame
yGreen = yGreen - .01;

// Increase xBlue by three, hundreths each game frame
xBlue = xBlue + .03;
// Increase yBlue by three, hundreths each game frame
yBlue = yBlue + .03;

// Position the green circle at the postion -
// stored in xGreen and yGreen
circleGreen.setPosition(xGreen, yGreen);

// Position the blue circle at the postion -
// stored in xBlue and yBlue
circleBlue.setPosition(xBlue, yBlue);

// End of new code

Now click the button shown in the next image to run our Variables Demo project again.

sfml_run_hello_world_app

 

And their off.. Each time through the loop the values of xGreen, yGreen, xBlue and yBlue are modified. Then when we call setPosition again the circles are in those new locations when the scene is drawn. It is because the change is gradual over time that we see them move smoothly.

sfml_moving_circles_demo

What is happening here is very simple yet powerful. It demonstrates in the simplest way possible how every game’s animation works.

  1. Update the scene
  2. Draw the scene
  3. Repeat

The code xGreen = xGreen + .01 adds .01 onto the value stored in xGreen. The code yGreen = yGreen - .01 subtracts .01 from the value of yGreen. Also, as we are already aware, this happens many times per second making the circle smoothly animate itself upwards and to the right.

The code xBlue = xBlue + .03 adds .03 onto the value stored in xBlue. The code yBlue = yBlue + .03 adds .03 to the value stored in yBlue. As with circleGreen this happens many times per second making the blue circle smoothly (but faster than circleGreen) animate itself down and to the right.

Things to do and what’s next?

Try playing with the values that we use to move the circles to make them faster or head in different directions. What happens when we move objects by different amounts on the x-axis than that of the y-axis.

Something to consider about the code we have just written is this: If we let the program run for just a short time the moving circles will disappear into oblivion. We need a way to ‘know’ when they are going somewhere we don’t want them to go so we can change their behavior.

That’s as far as this tutorial will explore. The next logical step and part of the solution to the problem of ‘knowing’ posed above would be to read the Checking for conditions in C++ code where we will get to the bottom of all those odd looking if keywords.

Something else to think about as an aside is to consider the imperfections of the code we have just written. Our green circle moved by .01 pixels per frame. The number of frames that are executed per second is entirely dependent upon how powerful the computer that it is running on. We are going to need to solve this problem. Otherwise, a shooter would be faster (and probably harder) on newer PCs.