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.