Beginning C++ Game Programming

4.8 (16 reviews total)
By John Horton
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. C++, SFML, Visual Studio, and Starting the First Game

About this book

This book is all about offering you a fun introduction to the world of game programming, C++, and the OpenGL-powered SFML using three fun, fully-playable games. These games are an addictive frantic two-button tapper, a multi-level zombie survival shooter, and a split-screen multiplayer puzzle-platformer.

We will start with the very basics of programming, such as variables, loops, and conditions and you will become more skillful with each game as you move through the key C++ topics, such as OOP (Object-Orientated Programming), C++ pointers, and an introduction to the Standard Template Library. While building these games, you will also learn exciting game programming concepts like particle effects, directional sound (spatialization), OpenGL programmable Shaders, spawning thousands of objects, and more.

Publication date:
October 2016
Publisher
Packt
Pages
520
ISBN
9781786466198

 

Chapter 1. C++, SFML, Visual Studio, and Starting the First Game

Welcome to Beginning C++ Game Programming. I will waste no time in getting you started on your journey to writing great games for the PC, using C++ and OpenGL-powered SFML.

This is quite a hefty first chapter, but we will learn absolutely everything we need to, in order to have the first part of our first game up-and-running. Here is what we will cover in this chapter:

  • Find out about the games we will build

  • Learn a bit about C++

  • Explore SFML and its relationship with C++

  • Look at the Visual Studio software, which we will use throughout the book

  • Set up a game development environment

  • Create a reusable project template, which will save a lot of time

  • Plan and prepare for the first game project, Timber!!!

  • Write the first C++ code of the book and make a runnable game that draws a background

 

The games


We will learn the fundamentals of the super-fast C++ language, a step at a time, and then put the new knowledge to use, so it should be fairly easy to add cool features to the three games we are building.

Tip

If you get stuck with any of the content in this chapter, take a look at the sections near the end Handling errors and FAQs.

These are our three projects for the book:

Timber!!!

The first game is an addictive, fast-paced clone of the hugely successful Timberman, which can be found at http://store.steampowered.com/app/398710/. Our game, Timber!!!, will introduce us to all the C++ basics at the same time as building a genuinely playable game. Here is what our version of the game will look like when we are done and we have added a few last-minute enhancements.

Zombie Arena

Next, we will build a frantic, zombie survival shooter, not unlike the Steam hit, Over 9000 Zombies, which can be found at http://store.steampowered.com/app/273500/. The player will have a machine gun, and must fight off ever-growing waves of zombies. All this will take place in a randomly generated, scrolling world. To achieve this we will learn about object-oriented programming and how it enables us to have a large code base (lots of code) that is easy to write and maintain. Expect exciting features such as hundreds of enemies, rapid-fire weaponry, pick-ups, and a character that can be "leveled-up" after each wave.

Thomas was Late

The third game will be a stylish and challenging puzzle platformer, which can be played as a single player and coop. It is based on the very popular game, Thomas was Alone, which can be found at http://store.steampowered.com/app/220780/. Expect to learn about cool topics such as particle effects, OpenGL Shaders, and split-screen cooperative multiplayer features.

Tip

If you want to play any of the games now, you can do so from the download bundle in the Runnable Games folder. Just double-click on the appropriate .exe file. Notice that in this folder you can either run the completed games or any game in its partially completed state from any chapter.

Let's get started by introducing C++, Visual Studio, and SFML!

 

Meet C++


One question you might have is, why use C++ at all? C++ is fast, very fast. What makes this the case is the fact that the code that we write is directly translated into machine executable instructions. These instructions make the game. The executable game is contained within an .exe file that the player can simply double-click to run.

There are a few steps in the process. First, the pre-processor looks to see if any other code needs to be included within our own code and adds it when necessary. Next, all the code is compiled into object files by the compiler program. Finally, a third program, called the linker, joins all the object files into the executable file, which is our game.

In addition, C++ is well established at the same time as being extremely up-to-date. C++ is an object oriented programming ( OOP ) language, which means we can write and organize our code in a proven way that makes our games efficient and manageable. The benefits, as well as the necessity for this, will reveal themselves as we progress through the book.

Most of the other code to which I referred is SFML, and we will find out more about SFML in just a minute. The pre-processor, compiler, and linker programs I have just mentioned, are all part of the Visual Studio Integrated Development Environment(IDE).

 

Microsoft Visual Studio


Visual Studio hides away the complexity of the pre-processing, compiling, and linking. It wraps it all up into one press of a button. In addition to this, it provides a slick user interface for us to type our code and manage what will become a large selection of code files, and other project assets as well.

While there are advanced versions of Visual Studio that cost hundreds of dollars, we will be able to build all three of our games in the free Express 2015 for Desktop version.

 

SFML


Simple Fast Media Library (SFML) is not the only C++ library for games and multimedia. It is possible to make an argument for using other libraries, but SFML seems to be the best for me, every time. First it is written using object oriented C++. The benefits of this are numerous. Most of these benefits you will experience as you progress through the book.

SFML is so easy to get started and is therefore a good choice if you are a beginner. At the same time, it also has the potential to build the highest-quality 2D games if you are a professional. So a beginner can get started using SFML and not worry about having to start again with a new language/library as their experience grows.

Perhaps the biggest benefit is that most modern C++ programming uses OOP. Every C++ beginners guide I have ever read uses and teaches OOP. OOP is, in fact, the future (and the now) of coding in almost all languages. So why, if you're learning C++ from the beginning, would you want to do it any other way?

SFML has a module (code) for just about anything you would ever want to do in a 2D game. SFML works using OpenGL, which can also make 3D games. OpenGL is the de-facto free-to-use graphics library for games when you want them to run on more than one platform. When you use SFML, you are automatically using OpenGL.

SFML drastically simplifies:

  • 2D graphics and animation including scrolling game worlds.

  • Sound effects and music playback, including high-quality directional sound.

  • Online multiplayer features

  • The same code can be compiled and linked on all major desktop operating systems, and soon mobile, as well!

Extensive research has not uncovered any more suitable way to build 2D games for PC, even for expert developers, and especially if you are a beginner and want to learn C++ in a fun gaming environment.

 

Setting up the development environment


Now you know a bit more about how we will be making these games, it is time to set up a development environment so we can get coding.

What about Mac and Linux?

The games that we make can be built to run on Windows, Mac and Linux! The code we use will be identical for each. However, each version does need to be compiled and linked on the platform for which it is intended and Visual Studio will not be able to help us with Mac and Linux.

It would be unfair to say that this book is entirely suited for Mac and Linux users, especially complete beginners. Although, I guess, if you are an enthusiastic Mac or Linux user, and you are comfortable with your operating system, the vast majority of the extra challenges you will encounter will be in the initial setup of the development environment, SFML, and the first project.

To this end, I can highly recommend the following tutorials which will hopefully replace the next 10 pages (approximately), up to the section Planning Timber!!!, when this book should again become relevant to all operating systems.

For Linux, read this for an overview: http://www.sfml-dev.org/tutorials/2.0/start-linux.php .

For Linux, read this for step-by-step guidance: http://en.sfml-dev.org/forums/index.php?topic=9808.0 .

On Mac, read this tutorial as well as the linked out articles: http://www.edparrish.net/common/sfml-.osx.html .

Installing Visual Studio Express 2015 on your desktop

Installing Visual Studio can be almost as simple as downloading a file and clicking a few buttons. It will help us, however, if we carefully run through exactly how we do this. For this reason, I will walk through the installation process a step at a time.

The Microsoft Visual Studio site says that you need 5 GB of hard disk space. From experience, however, I would suggest you need at least 10 GB of free space. In addition, these figures are slightly ambiguous. If you are planning to install it on a secondary hard drive, you will still need at least 5 GB on the primary hard drive because no matter where you choose to install Visual Studio, it will need this space too.

Note

To summarize this ambiguous situation: It is essential to have a full 10 GB space on the primary hard disk, if you intend to install Visual Studio to that primary hard disk. On the other hand, make sure you have 5 GB on the primary hard disk as well as 10 GB on the secondary, if you intend to install to a secondary hard disk. Yep, stupid, I know!

  1. The first thing you need is a Microsoft account and the login details. If you have a Hotmail or MSN email address then you already have one. If not, you can sign up for a free one here: https://login.live.com/.

  2. Visit this link: https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx. Click on Visual Studio 2015, then Express 2015 for desktop then the Downloads button. The next screenshot shows the three places to click:

  3. Wait for the short download to complete and then run the downloaded file. Now you just need to follow the on-screen instructions. However, make a note of the folder where you choose to install Visual Studio. If you want to do things exactly the same as me, then create a new folder called Visual Studio 2015 on your preferred hard disk and install to this folder. This whole process could take a while depending on the speed of your Internet connection.

  4. When you see the next screen, click on Launch and enter your Microsoft account login details.

Now we can turn to SFML.

Setting up SFML

This short tutorial will take you through downloading the SFML files that allow us to include the functionality contained in the library. In addition, we will see how to use the SFML DLL files that will enable our compiled object code to run alongside SFML:

  1. Visit this link on the SFML website: http://www.sfml-dev.org/download.php. Click on the button that says Latest stable version as shown next.

  2. By the time you read this guide, the latest version will almost certainly have changed. That doesn't matter as long as you do the next step correctly. We want to download the 32-bit version for Visual C++ 2014. This might sound counter-intuitive because we have just installed Visual Studio 2015 and you probably (most commonly) have a 64-bit PC. The reason we choose this download is because Visual C++ 2014 is part of Visual Studio 2015 (Visual Studio offers more than just C++) and we will be building games in 32-bit so that they run on both 32- and 64- bit machines. To be clear, click the following download:

  3. When the download completes, create a folder at the root of the same drive where you installed Visual Studio and name it SFML. Also create another folder at the root of the drive where you installed Visual Studio and call it Visual Studio Stuff. We will store all kinds of Visual Studio-related things here so Visual Studio Stuff seems like a good name. Just to be clear, here is what my hard drive looks like after this step:

  4. Obviously, the folders you have in between the highlighted three folders in the screenshot will probably be totally different to mine. Now we are ready for all the projects we will soon be making, create a new folder inside Visual Studio Stuff. Name the new folder Projects.

  5. Finally, unzip the SFML download. Do this on your desktop. When unzipping is complete you can delete the zip folder. You will be left with a single folder on your desktop. Its name will reflect the version of SFML that you downloaded. Mine is called SFML-2.3.2-windows-vc14-32-bit. Your file name will likely reflect a more recent version. Double-click this folder to see the contents, then double-click again into the next folder (mine is called SFML-2.3.2). The following screenshot shows what my SFML-2.3.2 folder's contents looks like, when the entire contents have been selected. Yours should look the same.

  6. Copy the entire contents of this folder, as seen in the previous screenshot, and paste/drag all the contents into the SFML folder you created in Step 3. For the rest of the book I will refer to this folder simply as your SFML folder.

Now we are ready to start using C++ and SFML in Visual Studio.

Creating a reusable project template

As setting up a project is a fairly fiddly process, we will create a project and then save it as a Visual Studio template. This will save us quite a significant amount of work each time we start a new game. So, if you find the next tutorial a little tedious, rest assured that you will never need to do this again:

  1. Start Visual Studio and, in the New Project window, click the little drop-down arrow next to Visual C++ to reveal more options, then click Win32, and click Win32 Console Application. You can see all these selections in the next screenshot.

  2. Now, at the bottom of the New Project window, type HelloSFML in the Name: field.

  3. Next, browse to the Visual Studio Stuff\Projects\ folder that we created in the previous tutorial. This will be the location where all our project files will be kept. All templates are based on an actual project. So, we will have a project called HelloSFML but the only thing we will do with it is make a template from it.

  4. When you have completed the steps above, click OK. The next screenshot shows the Application Settings window. Check the box for Console application, and leave the other options as shown below.

  5. Click Finish and Visual Studio will create the new project.

  6. Next, we will add some fairly intricate and important project settings. This is the laborious part but, as we will create a template, we will only need to do this once. What we need to do is tell Visual Studio, or more specifically the code compiler that is part of Visual Studio, where to find a special type of code file from SFML. The special type of file I am referring to is a header file. Header files are the files that define the format of the SFML code. So when we use the SFML code, the compiler knows how to handle it. Note that the header files are distinct from the main source code files and they are contained in files with the .hpp file extension. (All this will become clearer when we eventually start adding our own header files in the second project). In addition, we need to tell Visual Studio where it can find the SFML library files. From the Visual Studio main menu select Project | HelloSFML properties.

  7. In the resulting HelloSFML Property Pages window, perform the following steps, flagged in the next screenshot.

  8. Select All Configurations from the Configuration: drop-down.

  9. Select C/C++ then General from the left-hand menu.

  10. Locate the Additional Include Directories edit box and type the drive letter where your SFML folder is located, followed by \SFML\include. The full path to type, if you located your SFML folder on your D drive, is as shown in the screenshot: D:\SFML\include. Vary your path if you installed SFML to a different drive.

  11. Click Apply to save your configurations so far.

  12. Now, still in the same window, perform these next steps, again flagged in the next screenshot. Select Linker then General.

  13. Find the Additional Library Directories edit box and type the drive letter where your SFML folder is, followed by \SFML\lib. So the full path to type if you located your SFML folder on your D drive is, as shown in the screenshot, D:\SFML\lib. Vary your path if you installed SFML to a different drive.

  14. Click Apply to save your configurations so far.

  15. Finally for this stage, still in the same window, perform these steps, which again refer to the next screenshot. Switch the Configuration: drop-down(1) to Debug as we will be running and testing our games in Debug mode.

  16. Select Linker then Input (2).

  17. Find the Additional Dependencies edit box (3) and click into it on the far left-hand side. Now copy and paste/type the following: sfml-graphics-d.lib;sfml-window-d.lib;sfml-system-d.lib;sfml-network-d.lib;sfml-audio-d.lib; at the indicated place. Again, be really careful to place the cursor precisely, and dont overwrite any of the text that is already there.

  18. Click OK.

  19. Let's make a template from our HelloSFML project so we never have to do this slightly mind-numbing task again. Creating a reusable project template is really easy. In Visual Studio select File | Export Template.... Then, in the Export Template Wizard window, make sure the Project template option is selected, and then select HelloSFML project for the From which project do you want to create a template option.

  20. Click Next and then Finish.

Phew, that's it! Next time we create a project, I'll show you how to do it from this template. Now let's build Timber!!!

 

Planning Timber!!!


Whenever you make a game it is always best to start with a pencil and paper. If you don't know exactly how your game is going to work on the screen, how can you possibly make it work in code?

Tip

At this point, if you haven't already, I suggest you go and watch a video of Timberman in action, so you can see what we are aiming for. If you feel your budget can stretch to it, then grab a copy and give it a play. It is often on sale for under a dollar on Steam. http://store.steampowered.com/app/398710/ .

The features and objects of a game, which define the gameplay, are known as the mechanics. The basic mechanics of the game are:

  • Time is always running out.

  • Get more time by chopping the tree.

  • Chopping the tree causes the branches to fall.

  • The player must avoid the falling branches.

  • Repeat until the time runs out or the player is squished.

Expecting you to plan the C++ code at this stage is obviously a bit silly. This is, of course, the first chapter of a C++ beginner's guide. We can, however, take a look at all the assets we will use and an overview of what we will need to make our C++ do what we want it to.

Take a look at a annotated screenshot of the game:

You can see that we have the following features:

  • Player's current score: Each time the player chops a log he will get one point. He can chop a log with either the left or the right arrow.

  • Player Character: Each time the player chops, he will move/stay on the same side of the tree. Therefore the player must be careful which side he chooses to chop on. When the player chops, a simple ax graphic will appear in the player character's hands.

  • Shrinking time-bar: Each time the player chops, a small amount of time will be added to the ever-shrinking time bar.

  • Lethal branches: The faster the player chops, the more time he will get, but also the faster the branches will move down the tree, and therefore the more likely he is to get squished. The branches spawn randomly at the top of the tree and move down with each chop.

  • When the player gets squished, which he will quite regularly, a gravestone graphic will appear.

  • Chopped log: When the player chops, a chopped log graphic will whiz off away from the player.

  • There are three floating clouds that will drift at random heights and speeds as well as a bee that does nothing but fly around.

  • All this takes place on a pretty background.

So, in nutshell the player must frantically chop to gain points and avoid running out of time. As a slightly perverse but fun consequence, the faster he chops, the more likely his squishy demise.

We now know what the game looks like, how it is played, and the motivation behind the game mechanics. We can go ahead and start to build it.

 

Creating a project from the template


Creating a new project is now extremely easy. Just follow these straightforward steps in Visual Studio:

  1. Select File | New Project from the main menu.

  2. Make sure that Visual C++ is selected in the left-hand menu and then select HelloSFML from the list of presented options. This next screenshot should make this clear.

  3. In the Name: field, type Timber and also make sure that the Create directory for solution option is checked. Now click OK.

  4. Now we need to copy the SFML .dll files into the main project directory. My main project directory is D:\Visual Studio Stuff\Projects\Timber\Timber. It was created by Visual Studio in the previous step. If you put your Projects folder somewhere else, then perform this step there instead. The files we need to copy into the project folder are located in your SFML\bin folder. Open a window for each of the two locations and highlight the required files as shown in the next screenshot on the left.

  5. Now copy and paste the highlighted files into the project folder on the right of the previous screenshot.

The project is now set up and ready to go. You will be able to see the screen shown in this next screenshot. I have annotated the screenshot so you can start to familiarize yourself with Visual Studio. We will revisit all these areas, and others, soon.

Your layout might look slightly different from the screenshot because the windows of Visual Studio, like most applications, are customizable. Take the time to locate the Solution Explorer window on the right and adjust it to make its contents nice and clear, such as they are in the previous screenshot.

We will be back here really soon to start coding.

 

Project assets


Assets are anything you need to make your game. In our case the assets include:

  • A font for the writing on the screen

  • Sound effects for different actions such as chopping, dying, and running out of time

  • Graphics for the character, background, branches, and other game objects

All the graphics and sound required for the game are included in the download bundle. They can be found in the Chapter 1/graphics and Chapter 1/sound folders as appropriate.

The font that is required has not been supplied. This is because I wanted to avoid any possible ambiguity regarding licensing. This will not cause a problem though, as I will show you exactly where and how to choose and download fonts for yourself.

Although I will provide either the assets themselves or information on where to get them, you might like to create and acquire them for yourself.

Outsourcing assets

There are a number of websites that allow you to contract artists, sound engineers, and even programmers. One of the biggest is the www.upwork.com. You can join this site for free and post your jobs. You need to write a clear explanation of your requirements as well as state how much you are prepared to pay. Then you will probably get a good selection of contractors bidding to do the work. Be aware, there is a lot of unqualified contractors whose work might be disappointing, but if you choose carefully you will likely find a competent, enthusiastic, and great value person or company to do the job.

Making your own sound FX

Sound effects can be downloaded for free from sites like www.freesound.org but often the license won't allow you to use them if you are selling your game. Another option is to use an open source software called BFXR from www.bfxr.net, which can help you generate lots of different sound effects that are yours to keep and do as you like with.

Adding assets to the project

Once you have decided which assets you will use, it is time to add them to the project. These next instructions will assume you are using all the assets supplied in the book's download bundle. Where you are using your own, simply replace the appropriate sound or graphic file with your own, using exactly the same file name.

  1. Browse to the Visual D:\Visual Studio Stuff\Projects\Timber\Timber.

  2. Create three new folders within this folder and name them as graphics, sound, and fonts.

  3. From the download bundle, copy the entire contents of Chapter 1/graphics into the D:\Visual Studio Stuff\Projects\Timber\Timber\graphics folder.

  4. From the download bundle, copy the entire contents of Chapter 1/sound into the D:\Visual Studio Stuff\Projects\Timber\Timber\sound folder.

  5. Now visit: http://www.1001freefonts.com/komika_poster.font in your web browser and download the Komika Poster font.

  6. Extract the contents of the zipped download and add the KOMIKAP_.ttf file to the D:\Visual Studio Stuff\Projects\Timber\Timber\fonts folder.

Let's take a look at these assets, especially the graphics, so we can better visualize what is happening when we use them in our C++ code.

Exploring assets

Graphical assets form the individual parts of the screen in our Timber!!! game. Take a look at the graphical assets and it should be clear where, in our game, they will be used.

The sound files are all .wav format. These are files containing the sound effects that we will play at certain events throughout the game. They were all generated using BFXR. They are:

  • chop.wav: A sound that is a bit like an ax (a retro ax) chopping a tree

  • death.wav: A sound a bit like a retro "losing" sound.

  • out_of_time.wav: Plays when the player loses by running out of time, as opposed to being squashed

 

Understanding screen and internal coordinates


Before we move on to the actual C++ coding, let's talk a little about coordinates. All the images that we see on our monitors are made out of pixels. Pixels are little tiny dots of light that combine to make the images we see.

There are many different monitor resolutions but, as an example, a fairly typical gamer's monitor might have 1920 pixels horizontally and 1080 pixels vertically.

The pixels are numbered starting at the top left of the screen. As you can see from the next diagram, our 1920 x 1080 example is numbered from 0 through to 1919 on the horizontal (x) axis and 0 through 1079 on the vertical (y) axis.

A specific and exact screen location can therefore be identified by x and y coordinate. We create our games by drawing game objects such as background, characters, bullets and, text, to specific locations on the screen. These locations are identified by the coordinates of the pixels. Take a look at this next hypothetical example of how we might draw at, approximately, the central coordinates of the screen. In the case of a 1920 x 1080 screen this would be at position 960, 540.

In addition to the screen coordinates, our game objects will each have their own similar coordinate system as well. As with the screen coordinate system, their internal or local coordinates start at 0,0 in the top left-hand corner.

We can see in the previous screenshot that 0,0 of the character is drawn at 960, 540 of the screen.

A visual, 2D game object, such as a character or perhaps a zombie, is called a sprite. A sprite is typically made from an image file. All sprites have what is known as an origin.

If we draw a sprite at a specific location on the screen, the origin will be located at this specific location. The 0,0 coordinates of the sprite are the origin. The next screenshot demonstrates this.

This is why, in the screenshot showing the character drawn to the screen, although we drew the image at the central position (960, 540) it appears off to the right and down a bit.

We just need to bear in mind how this works as we progress through the first project.

Note that, in the real world, gamers have a huge variety of screen resolutions and our games will need to work with as many of them as possible. In the second project we will see how we can make our games dynamically adapt to almost any resolution. In this first project we will need to assume that the screen resolution is 1920 x 1080. Don't worry if your screen is different to this, as I have provided a separate set of code for each chapter, for the Timber!!! game. The code files are nearly identical, apart from adding and swapping a few lines of code near the beginning. If you have a lower-resolution screen, then simply follow the code in the book that assumes a 1920 x 1080 resolution and when it comes to trying out the game you can copy and paste the code files from the low res folder in each of Chapters 1 to 5, as appropriate. In fact, once the extra lines have been added in this first chapter, all the rest of the code will be identical regardless of your screen resolution. I have supplied the low-res code for each chapter, just as a convenience. We will discuss how the few lines of code work their magic (scale the screen) in the second project. The alternative code will work on resolutions as low as 960 x 540 so should be good on almost any PC or laptop.

Now we can write our first C++ code, and very soon we will see it in action.

 

Starting to code the game


Open up Visual Studio if it isn't already, open up the Timber project (if it isn't already open) by left-clicking it from the Recent list on the main Visual Studio window.

The first thing we will do is to rename our main code file. It is currently called HelloSFML.cpp and we will rename it to the more appropriate Timber.cpp. The .cpp stands for C plus plus.

  1. Find the Solution Explorer window on the right-hand side.

  2. Locate the HelloSFML.cpp file under the Source Files folder.

  3. Right-click HelloSFML.cpp and choose Rename.

  4. Edit the filename to Timber.cpp and press Enter.

Make some minor edits in the code window so that you have exactly the same code as shown next. You can do so in exactly the same way that you would with any text editor or word processor; you could even copy and paste it if you prefer. After you have made the slight edits, we can talk about them:

// Include important C++ libraries here 
#include "stdafx.h"  
int main() 
{ 
   return 0; 
} 

This simple C++ program is a good place to start. Let's go through it line by line

Making code clearer with comments

As you can see, the only code that needed to change was a little bit at the very top. The first line of code is this:

// Include important C++ libraries here 
 

Any line of code that starts with // is a comment and is ignored by the compiler. As such, this line of code does nothing. It is used to leave any information that we might find useful when we come back to the code at a later date. The comment ends at the end of the line, so anything on the next line is not part of the comment. There is another type of comment called a multi-line or c-style comment, which can be used to leave comments that take up more than a single line. We will see some of them later in this chapter. Throughout this book I will leave hundreds of comments to help add context and further explain the code.

#including Windows essentials

Now that you know what comments are for, you can probably take a decent guess at what the next line of code does. Here it is again:

#include "stdafx.h" 

The #include  directive tells Visual Studio to include, or add the contents of another file before compiling. The effect of this is that some other code, that we have not written ourselves, will be a part of our program when we run it. The process of adding code from other files into our code is called pre-processing and, perhaps unsurprisingly, is performed by something called a pre-processor. The file extension .h stands for header file.

You might be wondering what this code will do? The stdafx.h file actually contains more #include directives itself. It adds into our program, all the necessary code that is required to run our program on Windows. We will never need to see this file and definitely don't need to concern ourselves with what is in it. We just need to add the line of code at the top of every game that we make.

What is more significant and relevant to us, and the reason it is worth discussing the #include directive, is that we will add many more #include directives at the top of our code files. This is to include code that we will use and take the trouble to understand.

The main files that we will be including are the SFML header files, which give us access to all the cool game coding features. We will also use #include to access the C++ Standard Library header files. These header files give us access to core features of the C++ language itself.

That's two lines squared away, so let's move on.

The main function

The next line we see in our code is this:

int main() 

The code int is what is known as a type. C++ has many types and they represent different types of data. An int is an integer or whole number. Hold that thought and we will come back to it in a minute.

The main() code part is the name of the section of code that follows. This section of code is marked out between the opening curly brace { and the next closing curly brace }.

So, everything in between these curly braces {...} is a part of main. We call a section of code like this, a function.

Every C++ program has a main function and it is the place where the execution (running) of the entire program will start. As we progress through the book, eventually our games will have many code files. However, there will only ever be one main function, and no matter what code we write, our game will always begin execution from the first line of code inside the opening curly brace of the main function.

For now, don't worry about the strange brackets that follow the function name (). We will discuss them further in Chapter 4: Loops, Arrays, Switch, Enumerations, and Functions-Implementing Game Mechanics, where we will get to see functions in a whole new and more interesting light.

Let's look closely at the one single line of code within our Main function.

Presentation and syntax

Take a look at the entirety of our Main function again:

int main() 
{ 
   return 0; 
} 

We can see that inside Main there is just one single line of code, return 0;. Before we move on to find out what this line of code does, let's look at how it is presented. This is useful because it can help us prepare to write code that is easy to read, and distinguish, from other parts of our code.

First notice that return 0; is indented to the right by one tab. This clearly marks it out as being internal to the main function. As our code grows in length we will see that indenting our code and leaving white space will be essential to maintaining readability.

Next, notice the punctuation on the end of the line. A semicolon ; tells the compiler that it is the end of the instruction and whatever follows it is a new instruction. We call an instruction terminated by a semicolon, a statement.

Note that the compiler doesn't care whether you leave a new line or even a space between the semicolon and the next statement. However, not starting a new line for each statement will lead to desperately hard-to-read code, and missing the semicolon altogether will result in a syntax error so that the game will not compile or run.

A section of code together, often denoted by its indentation with the rest of the section, is called a block.

Now that you are comfortable with the idea of the main function, indenting your code to keep it tidy and putting a semicolon on the end of each statement, we can move on to find out exactly what the return 0; statement actually does.

Returning values from a function

Actually, return 0; does almost nothing in the context of our game. The concept, however, is an important one. When we use the return keyword, either on its own or followed by a value, it is an instruction for the program execution to jump/move back to the code that got the function started in the first place.

Often this code that got the function started will be yet another function somewhere else in our code. In this case, however, it is the operating system that started the main function. So, when the line return 0; is executed, the main function exits and the entire program ends.

As we have a 0 after the return keyword, that value is also sent to the operating system. We could change the value of zero to something else and that value would be sent back instead.

We say that the code that starts a function, calls the function, and that the function returns the value.

You don't need to fully grasp all this function information just yet. It is just useful to introduce it here. There's one last thing on functions before we move on. Remember the int from int Main()? That tells the compiler that the type of value returned from Main must be an int (integer/whole number). We can return any value that qualifies as an int. Perhaps 0, 1, 999, 6358, and so on. If we try and return something that isn't an int, perhaps 12.76, then the code won't compile and the game won't run.

Functions can return a big selection of different types, including types that we invent for ourselves! That kind of type, however, must be made known to the compiler in the way we have just seen.

This little bit of background information on functions will make things smoother as we progress.

Running the game

You can actually run the game at this point. Do so by clicking the Local Windows Debugger button in the quick-launch bar of Visual Studio, or you can use the F5 shortcut key.

You will just get a flash of a black screen. This flash is the C++ console, which we can use for debugging our game. We don't need to do this for now. What is happening is that our program is starting, executing from the first line of Main, which of course is return 0; and then immediately exiting back to the operating system.

 

Opening a window using SFML


Now let's add some more code. The code that follows will open a window that Timber!!! will eventually run in. The window will be 1920 pixels wide by 1080 pixels high and will be full-screen (no border or title).

Enter the new code that is highlighted below amongst the existing code and then we will examine it. As you type (or copy and paste) try and work out what is going on:

// Include important C++ libraries here 
#include "stdafx.h" 
#include <SFML/Graphics.hpp>
// Make code easier to type with "using namespace"
using namespace sf; 
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); 
   return 0; 
} 

#including SFML features

The first thing we notice in our new code is another, albeit slightly different, #include directive. #include <SFML/Graphics.hpp> tells the pre-processor to include the contents of the file Graphics.hpp contained within the folder named SFML which we created while setting up the project.

So what this line achieves is that it adds code from the aforementioned file, which gives us access to some of the features of SFML. Exactly how it achieves this will become clearer when we start writing our own separate code files and using #include to use them.

Note

If you are wondering about the difference between pre-processor directives where the file name is contained like this <filename.hpp> and "filename.h", <...> is for files contained within our folder structure, such as the SFML files or anything we code ourselves. The "..." is for files included with Visual Studio. Also the .hpp file extension is just a more C++-oriented version of a .h file, which is more of a C-style extension. Both styles and both file extensions end up doing exactly the same thing and will work fine in our games.

What matters, for now, is that we have a whole bunch of new functionality provided by SFML, available for use.The next new line is using namespace sf;. We will come back to what this line does in a few paragraphs-time.

OOP, classes, objects

We will more fully discuss OOP, classes, and objects as we proceed through the book. What follows is the briefest introduction, so we can understand what is happening.

We already know that OOP stands for object-oriented programming. OOP is a programming paradigm, a way of coding. OOP is generally accepted throughout the world of programming, in almost every language, as the best, if not the only, professional way to write code.

OOP introduces a lot of coding concepts, but fundamental to them all are classes and objects. When we write code, whenever possible we want to write code that is reusable. The way we do this is to structure our code as a class. We will learn how to do this in Chapter 6: Object-Oriented Programming, Classes and SFML Views.

All we need to know about classes, for now, is that once we have coded our class, we don't just execute that code as part of our game instead we create usable objects from the class.

For example, if we wanted a hundred zombie Non-Player Characters (NPCs) we could carefully design and code a class called Zombie and then, from that single class, create as many zombie objects as we like. Each and every zombie object would have the same functionality and internal data types, but each and every zombie object would be a separate and distinct entity.

To take the hypothetical zombie example further, but without showing any code for the Zombie class, we might create a new object based on the Zombie class like this:

Zombie z1; 

The object, z1, is now a fully coded and functioning Zombie object. We could then do this:

Zombie z2; 
Zombie z3; 
Zombie z4; 
Zombie z5; 

We now have five separate zombies, but they are all based on one carefully coded class. Let's take things one step further before we get back to the code we have just written. Our zombies can contain both behaviors (defined by functions), as well as data that might represent things such as the zombie's health, speed, location, or direction of travel. As an example, we could code our Zombie class to enable us to use our zombie objects, perhaps like this:

z1.attack(player); 
z2.growl(); 
z3.headExplode(); 

Note

Note again that all this zombie-code is hypothetical for the moment. Don't type this code in to Visual Studio; it will just produce a bunch of errors.

We will design our class to enable us to use the data and behaviors in the most appropriate manner to suit our game's objectives. For example, we could design our class so that we can assign values for the data for each zombie object at the time we create it.

Perhaps we need to assign a unique name and speed in meters per second, at the time we create each zombie. Careful coding of the Zombie class could enable us to write code like this:

// Dave was a 100 meter Olympic champion before infection  
// He moves at 10 meters per second 
Zombie z1("Dave", 10); 
 
// Gill had both of her legs eaten before she was infected 
// She drags along at .01 meters per second 
Zombie z2("Gill", .01); 

The point is that classes are almost infinitely flexible, and once we have coded the class, we can go about using them by creating an object from them. It is through classes and the objects that we create from them that we will harness the power of SFML. And yes, we will also write our own classes, including a Zombie class.

Let's get back to the real code we just wrote.

Using namespace sf

Before we move on to look more closely at VideoMode and RenderWindow, which, as you've probably guessed, are classes provided by SFML, we will learn what the using namespace sf; line of code does.

When we create a class, we do so in a namespace. We do this to distinguish our classes from those that others have written. Consider the VideoMode class. It is entirely possible that, in an environment like Windows, somebody has already written a class called VideoMode. By using a namespace, we, and the SFML programmers, can make sure that the names of classes never clash.

The full way of using the VideoMode class is like this:

sf::VideoMode...

The code using namespace sf; enables us to omit the prefix sf:: from everywhere in our code. Without it, there would be over 100 instances of sf:: in this simple game alone. It also makes our code more readable as well as shorter.

SFML VideoMode and RenderWindow

Inside the Main function we now have two new comments and two new lines of actual code. The first line of actual code is this:

VideoMode vm(1920, 1080); 

This code creates an object called vm from the class called VideoMode and sets up two internal values of 1920 and 1080. These values represent the resolution of the player's screen.

The next new line of code is this:

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

In the previous line of code, we were creating a new object called window from the SFML provided class called RenderWindow. Furthermore, we were setting up some values inside our window object.

Firstly, the vm object is used in order to initialize part of the window. At first this might seem confusing. Remember, however, that a class can be as varied and flexible as its creator wants to make it. And yes, some classes can contain other classes.

Tip

It is not necessary to fully understand how this works at this point, just as long as you appreciate the concept. We code a class and then make usable objects from that class. A bit like an architect might draw a blueprint. You certainly can't move all your furniture, kids, and dog into the blueprint; but you could build a house (or many houses) from the blueprint. In this analogy, a class is like the blueprint and an object is like a house.

Next we use the value Timber!!! to give the window a name. And we use the predefined value Style::FullScreen to make our window object full screen.

Tip

Style::FullScreen is a value defined in SFML. It is useful so that we don't need to remember the integer number that the internal code uses to represent a full screen. The coding term for this type of value is a constant. Constants and their close C++ relatives, variables, are covered in the next chapter.

Let's see our window object in action.

Running the game

You can run the game again at this point. You will see a bigger black screen flash on then disappear. This is the 1920 x 1080 full-screen window that we just coded. Unfortunately, what is still happening is that our program is starting, executing from the first line of Main, creating the cool new game window, then coming to return 0;, and immediately exiting back to the operating system.

 

The main game loop


We need a way to stay in the program until the player wants to quit. At the same time, we should clearly mark out where the different parts of our code will go as we progress with Timber!!!. Furthermore, if we are going to stop our game from exiting, we had better provide a way for the player to exit when they are ready. Otherwise the game will go on forever!

Add the highlighted code, inside the existing code, and then we will go through and discuss it all:

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); 
    
   while (window.isOpen())   
     {
        /*     
        ****************************************
        Handle the players input
        ****************************************
        */     
        if (Keyboard::isKeyPressed(Keyboard::Escape))
        {
            window.close();     
        }    
        /*     
        ****************************************     
        Update the scene
        ****************************************     
        */     
 
        /*     
        ****************************************     
        Draw the scene     
        ****************************************     
        */        
        // Clear everything from the last frame     
        window.clear();     

        // Draw our game scene here    
 
        // Show everything we just drew     
        window.display();   
      } 
 
   return 0; 
} 

While loops

The very first thing we see in the new code is this:

while (window.isOpen()) 
{ 

The very last thing we see in the new code is a closing }. We have created a while loop. Everything between the opening { and closing } of the while loop will continue to execute, over and over, potentially forever.

Look closely between the parentheses (...) of the while loop as shown highlighted in the next code:

while (window.isOpen()) 

The full explanation of this code will have to wait until we discuss loops and conditions in Chapter 4: Loops, Arrays, Switch, Enumerations, and Functions-Implementing Game Mechanics. What is important for now is that, when the window object is set to closed, the execution of the code will break out of the while loop and onto the next statement. Exactly how a window is closed will be covered soon.

The next statement is of course return 0;, which ends our game.

We now know that our while loop will whiz round and round, repeatedly executing the code within it, until our window object is set to closed.

C-style code comments

Just inside the while loop we see what, at first glance, might look a bit like ASCII art:

      /* 
      **************************************** 
      Handle the player's input 
      **************************************** 
      */ 

Note

ASCII art is a niche but fun way of creating images with computer text. You can read more about it here: https://en.wikipedia.org/wiki/ASCII_art .

This previous code is simply another type of comment. This type of comment is known as a C-style comment. The comment begins with /* and ends with */. Anything in between is just for information and is not compiled. I have used this slightly elaborate text to make it absolutely clear what we will be doing in this part of the code file. And of course you can now work out that any code that follows will be related to handling the player's input.

Skip over a few lines of code and you will see that we have another C-style comment announcing that, in that part of the code, we will be updating the scene.

Jump to the next C-style comment and it is plain where we will be drawing all the graphics.

Input, update, draw, repeat

Although this first project uses the simplest possible version of a game loop, every game will need these phases in the code:

  1. Get the player's input (if any).

  2. Update the scene based on things such as artificial intelligence, physics, or the player's input.

  3. Draw the current scene.

  4. Repeat the above at a fast enough rate to create a smooth and animated game world.

Now let's look at the code that actually does something within the game loop.

Detecting a key press

Firstly, within the section labeled Handle the player's input we have the following code:

if (Keyboard::isKeyPressed(Keyboard::Escape)) 
{ 
     window.close(); 
} 

This code checks whether the Escape key is currently pressed. If it is, the highlighted code uses the window object to close itself. Now, the next time the while loop begins, it will see that the window object is closed and jump to the code immediately after the closing curly brace } of the while loop and the game will exit. We will discuss if statements more fully in Chapter 2: Variables, Operators, and Decisions-Animating Sprites.

Clearing and drawing the scene

At the moment there is no code in the Update the scene section, so let's move on to the Draw the scene section.

The first thing we do is to rub out the previous frame of animation using the code:

window.clear(); 

What we do now is draw each and every object from the game. At the moment, however, we don't have any game objects.

The next line of code is this:

window.display(); 

When we draw all the game objects, we are drawing them to a hidden surface ready to be displayed. The code window.display() flips from the previously displayed surface to the newly updated (previously hidden) one. This way, the player will never see the drawing process as the surface has all the sprites added to it. It also guarantees that the scene will be complete before it is flipped. This prevents a graphical glitch known as tearing. The process is called double buffering.

Also, notice that all this drawing and clearing functionality is performed using our window object, which was created from the SFML RenderWindow class.

Running the game

Run the game and you will get a blank, full-screen window that remains until you press the Esc keyboard key.

 

Drawing the game background


At last we will get to see some real graphics in our game. What we need to do is create a sprite. The first one we will create will be the game background. We can then draw it in between clearing the window and displaying/flipping it.

Preparing the sprite using a texture

The SFML RenderWindow class allowed us to create our window object to take care of all the functionality that our game's window needs.

We will now explore two more SFML classes, which will take care of drawing sprites to the screen. One of these classes, perhaps unsurprisingly, is called Sprite. The other class is called Texture. A texture is a graphic stored in memory on the Graphics Processing Unit (GPU).

An object made from the Sprite class needs an object made from the Texture class in order to display itself as an image. Add the following highlighted code. Try and work out what is going on as well. Then we will go through it one line at a time:

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); 
 
    
   while (window.isOpen()) 
   { 

First, we create an object called textureBackground from the SFML Texture class.

Texture textureBackground; 

Once this is done, we can use the textureBackground object to load a graphic from our graphics folder, into the textureBackground, like this:

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

Tip

We only need to specify graphics/background as the path is relative to the Visual Studio working directory where we created the folder and added the image.

Next, we create an object called spriteBackground from the SFML Sprite class with this code:

Sprite spriteBackground; 

Then, we can associate the texture object textureBackground with the Sprite object spriteBackground, like this:

spriteBackground.setTexture(textureBackground); 

Finally, we can position the spriteBackground object in the window object at coordinates 0,0:

spriteBackground.setPosition(0,0); 

As the background.png graphic in the graphics folder is 1920 pixels wide by 1080 pixels high, it will neatly fill the entire screen. Just note that this previous line of code doesn't actually show the sprite. It just sets its position ready for when it is shown.

The object, backgroundSprite, can now be used to display the background graphic. Of course you are almost certainly wondering why we had to do things in such a convoluted way. The reason is because of the way that graphics cards and OpenGL work.

Textures take up graphics memory and this memory is a finite resource. Furthermore, the process of loading a graphic into the GPU's memory is very slow. Not so slow that you can watch it happen, or that you will see your PC noticeably slow down while it is happening, but slow enough that you can't do it every frame of the game loop. So it is useful to dissociate the actual texture textureBackground from any code that we will manipulate during the game loop.

As you will see when we start to move our graphics, we will do so using the sprite. Any objects made from the Texture class will sit happily on the GPU, just waiting for an associated Sprite object to tell them where to show themselves. In later projects we will also reuse the same Texture object with multiple different Sprite objects, which makes efficient use of GPU memory.

In summary:

  • Textures are very slow to load onto the GPU

  • Textures are very fast to access once they are on the GPU

  • We associate a sprite object with a texture

  • We manipulate the position and orientation of sprite objects (usually in the Update the scene section)

  • We draw the Sprite object, which in turn displays the texture that is associated with it (usually in the Draw the scene section).

So all we need to do now is use our double-buffering system, provided by our window object, to draw our new Sprite object (spriteBackground), and we should actually get to see our game in action.

Double-buffering the background sprite

Finally we need to draw that sprite, and its associated texture, in the appropriate place in the game loop.

Tip

Note that, when I present code that is all from the same block, I don't add the indenting because it lessens the instances of line wraps in the text of the book. The indenting is implied. Check out the code file in the download bundle to see the full use of indenting.

Add the highlighted code:

/* 
**************************************** 
Draw the scene 
**************************************** 
*/ 
       
// Clear everything from the last run frame 
window.clear(); 
 
// Draw our game scene here 
window.draw(spriteBackground);           
 
// Show everything we just drew 
window.display(); 

The new line of code simply uses the window object to draw the spriteBackground object, in between clearing the display and showing the newly drawn scene.

Running the game

Run the program now and you will see the first signs that we have a real game in progress.

It's not going to get Greenlit on Steam in its current state, but we are on our way at least!

Let's take a look at some of the things that might go wrong in this chapter, and as we proceed through the book.

 

Handling errors


There will always be problems and errors in every project you make, that is guaranteed! The tougher a problem is, the more satisfying it is when you solve it. When, after hours of struggling, a new game feature finally bursts into life, it can cause a genuine high. Without the struggle, it would somehow be less worthwhile.

At some point in this book there will probably be some struggle. Remain calm, be confident that you will overcome it, and then set to work.

Remember that, whatever your problem, it is very unlikely you are the first person in the world to have ever had this same problem. Think of a concise sentence that describes your problem or error and then type it in to Google. You will be surprised how quickly, precisely, and often, someone else will already have solved your problem for you.

Having said that, here are a few pointers (pun intended; see Chapter 8: Pointers, Standard Template Library, and Texture Management) to get you started, in the event you are struggling with making this first chapter work.

Configuration errors

The most likely cause of problems in this chapter will be configuration errors. As you probably noticed during the process of setting up Visual Studio, SFML, the project template, and the project itself, there are an awful lot of filenames, folders, and settings that need to be just right. Just one wrong setting could cause one of a number of errors in which the text doesn't make it clear exactly what is wrong.

If you can't get the empty project with the black screen working in the Creating a reusable template section, it might be easier to start that section again. Make sure all the filenames and folders are appropriate for your specific setup and then get the simplest part of the code running (the part where the screen flashes black and then closes). If you can get to this stage, then configuration is probably not the issue.

Compile errors

Compile errors are probably the most common error we will experience going forward. Check that your code is identical to mine, especially semicolons on the ends of lines and subtle changes in upper and lower case for class and object names. If all else fails, open the code files in the download bundle and copy and paste it. While it is always possible that a code typo made it into the book, the code files were made from actual working projects - they definitely work!

Link errors

Link errors are most likely caused by missing SFML .dll files. Did you copy all of them into the project folder in the section Creating a project from the template?

Bugs

Bugs are what happen when your code works, but not as you expect it to. Debugging can actually be fun. The more bugs you squash the better your game and the more satisfying your day's work will be. The trick to solving bugs is to find them early! To do this I recommend running and playing your game every time you implement something new. The sooner you find the bug, the more likely the cause will be fresh in your mind. In this book we will run the code to see the results at every possible stage.

 

FAQ


Here are some questions that might be on your mind:

Q) I am struggling with the content presented so far. Am I cut out for programming?

A) Setting up a development environment and getting your head round OOP as a concept is probably the toughest thing you will do in this book. As long as your game is functioning (drawing the background), you are ready to proceed with the next chapter.

Q) All this talk of OOP, classes, and objects is too much and kind of spoiling the whole learning experience.

A) Don't worry. We will keep returning to OOP, classes, and objects constantly. In Chapter 6: Object-Oriented Programming, Classes, and SFML Views, we will really begin to get grip with the whole OOP thing. All you need to understand for now is that SFML has written a whole load of useful classes and we get to use this code by creating usable objects from those classes.

Q) I really don't get this function stuff.

A) It doesn't matter, we will return to it again and will learn about functions more thoroughly. You just need to know that, when a function is called, its code is executed, and when it is done (reaches a return statement), then the program jumps back to the code that called it.

 

Summary


That was quite a challenging chapter and perhaps I was a little bit mean to make it so demanding. It is true that configuring an IDE to use a C++ library can be a bit awkward and time consuming. Also it is well known that the concept of classes and objects is slightly awkward for people who are new to coding.

Now that we are at this stage, however, we can totally focus on C++, SFML, and games. As the chapters progress, we will learn more and more C++, as well as how to implement increasingly interesting game features. As we do so, we will take a further look at things such as functions, classes, and objects, to help demystify them a little more. Next up we will learn all the C++ we need to draw some more sprites and animate them as well.

About the Author

Latest Reviews

(16 reviews total)
Recently bought the book, haven't finished it yet. The examples in the book are well explained and easy to follow.
Excelent service and excelent book.
The book is good for those who are starting out, it also has SFML material in there for those who are wanting to go more into game programming and needing to know where to go after learning the basics of C++. Only issue with the book is that it teaches SFML on top of beginning lessons which I feel would make it a bit harder to grasp at first.

Recommended For You

Book Title
Access this book, plus 7,500 other titles for FREE
Access now