Book Image

SFML Game Development

By : Artur Moreira, Henrik Vogelius Hansson, Jan Haller, Henrik Valter Vogelius, SFML
Book Image

SFML Game Development

By: Artur Moreira, Henrik Vogelius Hansson, Jan Haller, Henrik Valter Vogelius, SFML

Overview of this book

Game development comprises the combination of many different aspects such as game logics, graphics, audio, user input, physics and much more. SFML is an Open Source C++ library designed to make game development more accessible, exposing multimedia components to the user through a simple, yet powerful interface. If you are a C++ programmer with a stack of ideas in your head and seeking a platform for implementation, your search ends here.Starting with nothing more than a blank screen, SFML Game Development will provide you with all the guidance you need to create your first fully featured 2D game using SFML 2.0. By the end, you'll have learned the basic principles of game development, including advanced topics such as how to network your game, how to utilize particle systems and much more.SFML Game Development starts with an overview of windows, graphics, and user inputs. After this brief introduction, you will start to get to grips with SFML by building up a world of different game objects, and implementing more and more gameplay features. Eventually, you'll be handling advanced visual effects, audio effects and network programming like an old pro. New concepts are discussed, while the code steadily develops.SFML Game Development will get you started with animations, particle effects and shaders. As well as these fundamental game aspects, we're also covering network programming to the extent where you'll be able to support the game running from two different machines. The most important part, the gameplay implementation with enemies and missiles, will make up the core of our top-scrolling airplane shoot' em-up game!You will learn everything you need in SFML Game Development in order to start with game development and come closer to creating your own game.
Table of Contents (18 chapters)
SFML Game Development
Credits
Foreword
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

Displaying sprites on the screen


Now let's get something interesting on the screen. Instead of just rendering a boring single color circle to the screen, let's actually render an image. To do this, SFML provides a couple of tools to make your life easy. First we have the sf::Texture class that holds the actual image data loaded from the hard drive. Next is the sf::Sprite class that represents an instance with position and orientation in the scene. The texture describes the image, while the sprite describes where and how to put one on the screen.

A simple example of their relationship is as follows:

sf::Texture texture;
if (!texture.loadFromFile("path/to/file.png"))
{
  // Handle loading error
}
sf::Sprite sprite(texture);
sprite.setPosition(100.f, 100.f);
window.clear();
window.draw(sprite);
window.display();

Here, we load a texture from the hard drive, and check if loading has succeeded. We construct a new sprite to use the texture and set its position to (100, 100), relative to the upper-left window corner.

File paths and working directories

About file paths, it would be useful to make some things clear. First, the slashes that separate directories in a path in order to locate a file will be most often forward slashes (/), especially in Unix-like operating systems. In Windows, you will occasionally see back slashes (\) used instead, but probably not everywhere. Do not let this confuse you, the only true cross-platform way to specify a file path is using forward slashes, so make sure they are always your choice, even in Windows.

Also, it is of extreme importance to note that every program being run in the operating systems that SFML supports has a working directory while being executed. Usually, when you run the program from a graphical window manager, the working directory is exactly where the executable is located; however, this is not always the case. It is possible to run a program with any working directory, and it is even possible to change the working directory programmatically from inside the program. In the context of a game, the point of understanding working directories is for loading files, which are loaded in paths relative to the executable in most cases. All paths passed on to SFML are relative to the working directory, unless you make them absolute by starting them with a slash in Unix-like operating systems, or with a drive letter in Windows.

Real-time rendering

In a game simulation, it is highly likely that there will be changes to what's drawn in every frame. Even when there is no player input, you will observe in most cases some kind of animation, which will effectively change the end result on the screen for that given frame.

Many programs use a render-on-demand approach. They will only redraw a new frame on the screen when a change actually happens, minimizing the performance costs in applications where the screen doesn't change very often. But, by the nature of gaming software, this approach would be made redundant, as we would be requesting new frames all the time. Because of this, game programmers adopted entirely the concept of real-time rendering, which ignores frame requests as they were previously known, and blindly draws to the screen as fast as possible. If while playing your favorite game you eventually noticed a usual FPS count of 30 or 60, this is due to the fact that our eyes can't perceive, in regular circumstances, more frames than that amount in a second. Because it makes virtually no difference to the end user, the programmers limit the FPS count to such a number, and save the processor power for other tasks, such as logic processing. In short, nowadays, the whole scene is rendered again and again, independently of what changed since the last frame.

To explain the notion of real-time rendering a bit further, we would like to mention the concept of double buffering that comes inherently attached to it. Double buffering is a technique that was created to negate graphical glitches derived from asynchronies in the rendering tasks. Before this technique became widely used, programmers needed to have additional concerns when drawing to the screen, to ensure that only what belongs to a frame is drawn in it, and that there are no remains of pixels from previous frames.

Double buffering defines two virtual screens to draw graphics to. The front buffer and the back buffer are the names chosen to address these render targets. The front buffer is what is currently displayed on the screen, while the back buffer is the one we are drawing to at the moment, preparing a new frame. Once our frame is fully drawn in the back buffer, we use the SFML's sf::RenderWindow::display() function to put the contents of the back buffer on the screen. The back buffer becomes the front buffer, while the front buffer that was set will now be the back buffer to draw on. This way we ensure that we always have a buffer with the previous frame unharmed, as well as a working buffer that we can safely change at any time, without affecting what is on the screen. By clearing, drawing, and then displaying these buffers in an interleaved manner, we achieve double buffering.

Adapting the code

In our code, we replace sf::CircleShape with sf::Sprite, which only requires minor modifications. We load an image file called Eagle.png. The relative path to it is Media/Textures. Don't worry if you don't have the file; you can download it together with the whole source code.

// Game.hpp
class Game
{
    public:
                    Game();
        ...
    private:
        sf::Texture mTexture;
        sf::Sprite  mPlayer;
        ...
};

// Game.cpp
Game::Game()
: ...
, mTexture()
, mPlayer()
{
    if (!mTexture.loadFromFile("Media/Textures/Eagle.png"))
    {
        // Handle loading error
    }
    mPlayer.setTexture(mTexture);
    mPlayer.setPosition(100.f, 100.f);
}

No code changes have to be done to get our render() function to work with sprites instead of shapes. SFML is nice in that way. Everything that can be drawn to a window has to inherit from the abstract class sf::Drawable. As long as it is possible, the SFML API keeps a consistency to it. This makes it a lot easier to use, because if you have used a function on one class, you can be pretty sure there will be identical or similar functions in other classes.

Now you have achieved the results you observed in the screenshot we had in the beginning of the chapter. You are also very well on the way to making your game. With these few tools alone you would be able to make a simple game, such as Snake or Pac-Man with ease.