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”]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.
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 & 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.
Wow, three 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.
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.
What is happening here is very simple yet powerful. It demonstrates in the simplest way possible how every game’s animation works.
- Update the scene
- Draw the scene
- 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.
Hi,
I was working through this tutorial and could not get the circles to move as written. Looking at the code, I noticed that the statements setting the position for the green and blue circles were not included in the while loop for the open window. If that is the case, I cannot figure out how the position is set to the new variable values each frame, and it appears that the circles are redrawn repeatedly in the same position. I tried moving the position statements inside the loop, and the application worked. Am I missing something, or do I win some sort of prize for finding a bug?
Best,
Mike Kelly
Hi Mike,
Many thanks! Please accept the “bug finder of the month” award ;-). I have added the missing code in the “Making the circles move” section. And I am just going to Google a tutorial on “how to copy & paste” :-(.
John, I humbly accept the award, with due gravity. And do not think anything of it. I know you were just testing your readers. Any of my students can tell a story or two of times when I, ahhh, deliberately provided opportunities for them to catch an “error” I made. That includes, by the way, dumping a half quart of iced tea down my front in class. Keep on doing what you’re doing. I have been playing around with it (relearning a little C++ as I go) and still think it is excellent.
Mike K
Hello. I noticed an error in the code that made it fail. Under “Making the circles move” in the “// Increase xBlue by three, hundreths each game frame” there was a command, possibly from the website’s HTML5 code. Removing the made the program run correctly.
The code: xBlue = xBlue + .03;
Many thanks! I have removed the error.
Hi John
Really good tutorial, enjoying it. Sorry but noticed two typos 😉
First is: (you’ve done it twice)
// Make a window that is 800 by 600 pixels
// And has the title —> “Hello from SFML”
sf::RenderWindow window(sf::VideoMode(800, 600), —> “Variables Demo”);
Second:
The setFillColor —> fumction then makes the circle in question into that color.
Many thanks for taking the time. I have fixed the typos
Hi John,
I have a problem of renaming the HelloSFML.cpp to main.cpp, the name remains the same and when I double click it an error message appears saying it cannot be opened, that it has been deleted, renamed or moved.
I retried the first SFML project and still the error appears
I solved the problem by copying the HelloSFML.cpp to the variables demo folder, but shouldn’t it have been there before? Did I make a mistake during the first SFML project?
Yes, the file should have been part of any new project made with that template. You could try making the template again but now you have found how to work around the problem, I would just progress with making some projects- much more fun than making templates.
Thanks John, but then I found out that I have to copy the header files and stdafx.cpp too. I know I made a mistake so I tried making the template again but the problem still persists and I cant find the mistake. I feel its similar to Phillip’s.
Try this:
The file should now be part of the project, so try running it again.
Thanks John, it works now.
For some reason whenever i load the template file and put in the code it says the stdafx.cpp and header file cannot be found?
Possibly, you made a wrong step when making the template. Maybe the part when selcting the project type. For the template to work as expected it needs to be C++ | Win 32 | Win 32 Console Application.
I have done all the tutorials to this point step by step multiple times using the exact same file locations you use and everything but it keeps failing and im not sure why? Keeps saying files are not present and other errors. at one point i had 21 errors
Hi there, thanks for your comment. I assume you are using the template project? Which errors do you get?
I don´t get it.
When I make a new project these files ” stdafx.h , targetver.h , HelloSFML.cpp and stdafk.cpp ” dosen´t go in the new folder. I have to put it in manualy.
Why?
Not sure Nymbus. I think it is something to do with the project options.
Hey John – I am having the same problem as Abhinav and Phillip but the troubleshooting steps that have been listed are not working. I have re-made the template several times, and have gone so far as to uninstall/reinstall Visual Studio to try and solve the problem.
Basically, I am unable to re-name HelloSFML.cpp to Main.cpp, so I created an identical template and Named it Main.cpp. However, when I get to the step where I need to double-click Main.cpp to edit the code, I get the following error “The document cannot be opened. It has been renamed, deleted, or moved.” I attempted the fix above that you recommended to Abhinav regarding the stdafx.cpp file, but that doesn’t seem to work either.
Any suggestions? I am quite frustrated at this point.
Hi Max,
The name of the file Main.cpp is just an organizational thing. As long as the file has the main function in it then it will be used as the entry point to the program. Try this as I am struggling to think what could be causing the behaviour you describe.
I think the root of the issue is that when I create a new project using the template made in the earlier exercise and then examine the files in Visual Studio Stuff–>Projects–>New Project–>New Project, the main.cpp and stdafx.cpp files are not present. So essentially the template does not seem to be copying over the appropriate files.
If I go through all of the setup steps from the HelloSFML project each time I create a new project, then everything works fine. But that doesn’t seem to be very efficient.
Any ideas? If not I will just go through set up each time. Only takes a few minutes.
I think you have the same problem as me.
I solved it by copying the ” stdafx.h , targetver.h , HelloSFML.cpp and stdafk.cpp ” files from the last project HelloSFML to your new project. I found the files on my comupter in C:\Program Files (x86)\Visual Studio 2015\Projects\HelloSFML\HelloSFML. Just copy them into C:\Program Files (x86)\Visual Studio 2015\Projects\Variables Demo\Variables Demo.
It´s a temporary solution and you have to do it everytime you make a new project but it works. Hope it helps.
It worked. Thanks for this, it helped me a lot.
Hi, I’m using Code Blocks instead of Visual Studio. When I run the code, it can’t find “stdafx.h” – but when I comment it out the program has no errors. My circles moves very very slowly – don’t know if it is suppose to do that and if it is because that file is needed ? If I do need it, how do I put it in so Code Blocks will find it ?
If you have it working without the file you don’t need to worry about it. It is not the cause of the speed. Move on with the tutorials and you will learn how to control the speed of the animation. If you want to know why stdafx is sometimes required a quick Google will inform you but it isn’t very interesting. I would just move on until you get to the Building a simple C++ game engine tutorial.
Thanks – I’ve googled and see that it is a Visual Studio file – I’ve also figured out the speed thanks …….
Hi.
I have a problem with my circles. They wont move unless i keep moving my mouse over the window. They stop moving as soon as i stop moving the mouse over the window.
The only thing I can think of that might cause this behaviiur is if the window.draw… calls were accidentally placed inside the while (window.pollEvent(Event)) loop instead of just outside.
Oops. I was putting all the window.draw… calls inside the inner loop. Thanks a lot for the help and the great tutorials . Really enjoying and learning a lot.
It seems many of us have the problem with some files not being found (HelloSFML.cpp, stdatx.cpp…) so they can’t be renamed or double-clicked (yet they still appear in the explorer on the right of Visual Studio but not in the real repository on the hard drive).
Hi Destal,
This is quite common it seems. I am fairly sure this is a Windows permissions thing. The easiest solution is to create a new file and copy-paste the code into it and then delete the code from the autogenerated file. The only other solutions that might “fix” it is to make sure you run VS as administrator when you create the template and when you create the project from the template.
Hi, in codeblocks i can use windows.h to replace stdafx.h ?
I am not sure. I have not tried this in CodeBlocks. Have I understood your question?
Hi,
I just wanted to mention that there is a mistake in the comments, when adding the movement statements:
// Let’s manipulate our coordinates variables
…..
// Increase xBlue by three, hundreths each game frame
xBlue = xBlue + .03;
// Increase yGreen by three, hundreths each game frame <—– Here you mean increase "yBlue"
yBlue = yBlue + .03;
I noticed since I copied the comments only, and then went along writing the code myself, for learning purposes.
Thanks a lot for your Tutorials.
Thanks, Holo, fixed that.