Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
20. October 2015

 

In the previous tutorial we covered the basics of using graphics in SFML.  Chances are however your game isn’t going to be composed of simple shapes, but instead made up of many sprites.  That is exactly what we are going to cover today.

 

As always, there is an HD version of this tutorial available here

 

First off, we should start by defining what exactly a Sprite is.  In the early days of computers, sprite had special meaning as there was literally sprite hardware built into early 8bit computers.  A sprite is basically an image on screen that can move.  That’s it.   In SFML this relationship is easily demonstrated by it’s class hierarchy.

 

image

 

There is one very key concept to understand with sprites however.  A sprite in SFML represents and image or texture on screen that can be moved around.  However, it does not own the texture or image!  This makes the Sprite class fairly light weight, which certainly isn’t true about Texture or Image, the classes that actually contain all the data in the image.  Perhaps it’s easiest to start with a simple demonstration.

 

First we need an image to work with.  I am using a dragon sprite from the recent Humble Indie Gamedev Bundle.  The image looks like so:

dragonBig

 

Obviously you can use whatever image you want, just be sure to copy it into the working directory of your application.  In Visual Studio, the working directory can be located in the project’s properties panel under Debugging called Working Directory:

image

 

The image can be any of the following formats: bmp, hdr, gif, jpg, png, pic, psd, tga.  Keep in mind, not all formats are created equal.  Bitmap for example does not support transparency encoding and are generally quite large, but lose no image details and are simple to work with.  Gif has some patent issues and should generally be avoided.  Png seems like genuinely a good mix between features, size and quality and is well supported by content creation tools.

 

Ok, enough setup, let’s get to some code.

// Demonstrate sprite drawing in SFML
#include "SFML/Graphics.hpp"

int main(int argc, char ** argv){
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Demo Game");

  sf::Event event;

  sf::Texture texture;
  texture.loadFromFile("images/dragonBig.png");

  sf::Sprite sprite(texture);

  while (renderWindow.isOpen()){
    while (renderWindow.pollEvent(event)){
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }

    renderWindow.clear();
    renderWindow.draw(sprite);
    renderWindow.display();
  }
}

 

And when you run that:

image

 

As you can see, the experience is remarkably consistent to drawing using graphics primitives.  The big difference here is that we create our Sprite by providing a texture, which in turn we loaded from file with a call to Texture::loadFromFile().  There exist methods to load from stream or memory if preferred.  It is again important to remember that the Sprite does not own the Texture.  This means if the texture goes out of scope before the Sprite, the sprite will draw a blank rectangle.  This also means that several sprites can use the same texture.

 

Now you may have noticed that in addition to sf::Texture, there is a class called sf::Image and you may be wondering why.  There is one very simple difference at play here.  A Texture resides in the memory of your graphics card, while an image resides in system memory.  The act of copying an image from system memory to the GPU is quite expensive, so for performance reasons you almost certainly want to use Texture.  That said, Texture isn’t easily modified, so if you are working on a dynamic texture or say, creating a screen shot, Image is the better choice.  There exist methods to switch between the two types, but they are also fairly heavy in performance, so do not do them on a frame by frame basis.  At the end of the day

 

Let’s take a quick look at creating a dynamic image next.  Not something you are going to do often for most games granted, but it makes sense to mention it now.

// Demonstrate creating an Image
#include "SFML/Graphics.hpp"

int main(int argc, char ** argv){
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Demo Game");

  sf::Event event;

  sf::Image image;
  image.create(640, 480, sf::Color::Black);
  
  bool isBlackPixel = false;
  sf::Color blackPixel(0,0,0,255);
  sf::Color whitePixel(255, 255, 255, 255);

  //Loop through each vertical row of the image
  for (int y = 0; y < 480; y++){
    //then horizontal, setting pixels to black or white in blocks of 8
    for (int x = 0; x < 640; x++){


      if (isBlackPixel)
        image.setPixel(x, y, blackPixel);
      else
        image.setPixel(x, y, whitePixel);
      // Every 8th flip colour
      if (!(x % 8))
        isBlackPixel = !isBlackPixel;
    }
    // Offset again on vertical lines to create a checkerboard effect
    if(!(y%8))
      isBlackPixel = !isBlackPixel;
  }

  sf::Texture texture;
  texture.loadFromImage(image);
  sf::Sprite sprite(texture);

  while (renderWindow.isOpen()){
    while (renderWindow.pollEvent(event)){
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }

    renderWindow.clear();
    renderWindow.draw(sprite);
    renderWindow.display();
  }
}

 

When you run this example you should see:

image

 

Here you can see we can modify the pixels directly in our sf::Image.  However to display it on screen we still need to move it to texture and populate a sprite.  The difference is direct access to the pixel data.  Another important capability of sf::Image is the method saveToFile which enables you to well, save to file.  Obviously useful for creating screenshots and similar tasks.

 

You may notice depending on the resolution or composition of your source image that you texture may not look exactly like your source image.  This is because there is a smoothing or antialiasing filter built in to SFML to make images look smoother.  If you do not want this, perhaps going for that chunky 8bit look, you can turn it off with a call to setSmooth(false);

 

That is all we are going to cover today.  In the next tutorial part we will take a look at spritesheets, so we can have multiple different sprites in a single source image.

 

The Video

 

Programming


15. October 2015

 

In the previous tutorials we covered configuration, game loop and finally keyboard handling.  Today we are going to move on to the basics of graphics programming in SFML.  We are going to start with simple geographic primitives, then in the following tutorial we will move on to sprites.  You will notice right away that SFML is remarkably consistent in it’s approach to graphics, just like it is with Events.

 

As always, there is an HD video of this tutorial available here.

 

Let’s jump right in with a simple example that draws a blue circle on the screen.

// Demonstrate primitve drawing in SFML

#include "SFML/Graphics.hpp"

int main(int argc, char ** argv){
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Demo Game");

  sf::Event event;

  sf::CircleShape circleShape(200);
  circleShape.setFillColor(sf::Color::Blue);

  while (renderWindow.isOpen()){
    while (renderWindow.pollEvent(event)){
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }

    renderWindow.clear();
    renderWindow.draw(circleShape);
    renderWindow.display();
  }


}

Run this code and you will see:

image

This example creates a circle with a radius of 200 pixels that is filled with the colour blue.  Drawing is simply a matter of passing the shape into the draw() method of RenderWindow.  This is the way you draw pretty much everything in SFML.  If you take a look at the class reference for Drawable, the base class of any object passed into draw(), you can get a good idea of what classes are available.

image

 

As you can see, our CircleShape is part of that hierarchy.   Other than showing how to draw things to a window, this example shows us a few key concepts.  First, notice that we didn’t specify the location of our circle and by default it drew itself at the top left corner of the screen?  This shows us two critical things.  First, that the origin (0,0) of a window in SFML is the top left corner.  Second, that the origin/pivot ( the point within a shape a Drawable is drawn relative to ) is also it’s top left corner.  What if for example we wanted to position our circle relative to it’s midpoint instead?  Fortunately this is quite simple:

  sf::CircleShape circleShape(200);
  circleShape.setOrigin(circleShape.getRadius(), circleShape.getRadius());
  // or you could have calculated the mid point like so:
  // circleShape.setOrigin(circleShape.getLocalBounds().width / 2.0f, circleShape.getLocalBounds().height / 2.0f);

  circleShape.setFillColor(sf::Color::Blue);

Here we are setting the point draw calls are performed relative to by calling setOrigin().  This call sets that point in pixel coordinates relative to the top left corner of the Drawable.  Now this code will result in the following:

image

One other concept we didn’t cover is actually positioning our objects.  It is simply a matter of calling setPosition() like so:

circleShape.setPosition(100.0f, 100.0f);

This will result in the shape being drawn 100 pixels right and 100 pixels down from the top left corner of the window.  Of course the origin value is going to influence how that draw is performed.

 

Another important concept to cover is draw order.  Let’s throw in another circle, this time a red one, to illustrate what I mean:

    sf::CircleShape circleShape(200);
    circleShape.setFillColor(sf::Color::Blue);
    circleShape.setPosition(100.0f, 100.0f);

    sf::CircleShape circleShape2(200);
    circleShape2.setPosition(0.0f,0.0f);
    circleShape2.setFillColor(sf::Color::Red);
  
    //snip

    renderWindow.clear();
    renderWindow.draw(circleShape);
    renderWindow.draw(circleShape2);
    renderWindow.display();
  

 

Now run it and:

image

 

The order of draw calls is critically important.  Swap around the code, like so:

    renderWindow.clear();
    renderWindow.draw(circleShape2);
    renderWindow.draw(circleShape);
    renderWindow.display();

And you get:

image

 

As you can see, the later the draw call, the higher the z order.  Or put simply, things draw first are drawn first, then subsequent draw calls are drawn over top.  For future reference, this order is often referred to as the z-index.

 

Now that we have graphics to play with, there are a few things we can do with them…  such as move, rotate and scale.  Each of those functions transforms relative to the current position.  You can also directly set all three values using setPosition, setRotation and setScale.  With shapes, you also have control over the contour or line that composes the shape, like so:

  sf::CircleShape circleShape(200);
  circleShape.setFillColor(sf::Color::Blue);
  circleShape.setPosition(50.0f, 50.0f);
  circleShape.setOutlineThickness(10);
  circleShape.setOutlineColor(sf::Color::Green);

Here we set the line width to 10pixels and the color to green, resulting in:

image

 

As you may have noticed from the inheritance diagram earlier, there exist other shapes, ConvexShape and RectangleShape.  RectangleShape should be pretty self explanatory, bull ConvexShape requires a touch of explanation.  The Convex shape represents a convex hull, which is to say a closed shape of lines that never intersect or exceed 180 degrees.  You define a ConvexShape as a series of points, but it is important that you draw your shape in either a clockwise or counter-clockwise order so SFML knows how to draw it.  Here is an example creating a ConvexShape:

  sf::ConvexShape convexShape;
  convexShape.setPointCount(5);
  convexShape.setFillColor(sf::Color(147, 112, 227)); // PURPLE!
  convexShape.setOutlineThickness(3.0f);
  convexShape.setOutlineColor(sf::Color::White);
  convexShape.setPoint(0, sf::Vector2f(0.0f, 0.0f));
  convexShape.setPoint(1, sf::Vector2f(renderWindow.getSize().x, 0.0f));
  convexShape.setPoint(2, sf::Vector2f(renderWindow.getSize().x, renderWindow.getSize().y));
  convexShape.setPoint(3, sf::Vector2f(renderWindow.getSize().x / 2, renderWindow.getSize().y / 2));
  convexShape.setPoint(4, sf::Vector2f(0, renderWindow.getSize().y));


Resulting in

image

 

That’s it for basic graphics and shape rendering.  In the next tutorial we will expand upon this graphics knowledge and start looking at using sprites.

 

The Video

 

Programming


12. October 2015

 

In our prior tutorial we created a simple application that showed the basics of event handling in SFML.  In this tutorial we are going to expand upon that concept a bit further and show how to read the keyboard, both using events and direct polling.  Although not strictly SFML related (anymore anyways), we are also going to be covering random number generators as part of our demonstration, a very common task in game development.

 

As always, there is an HD video version of this tutorial.

 

Earlier we used the RenderWindow method pollEvent() to check for and respond to the Closed event.  Now let’s look at the process of responding to keyboard events.

while (renderWindow.pollEvent(event)){
    //Handle events here
    if (event.type == sf::Event::EventType::Closed)
      renderWindow.close();

    //Respond to key pressed events
    if (event.type == sf::Event::EventType::KeyPressed){
      if (event.key.code == sf::Keyboard::Space){
        // Do something here
      }
    }
  }

 

As we can see, responding to a KeyPressed event is nearly identical to a Closed event.  The key difference is, once you have identified that the event is a keyboard event you have additional information available in the event’s key structure.  The value of key.code is a sf::Keyboard::Key enum for each available key.  In addition to the KeyPressed event, there is also a KeyReleased event that is sent when the key is, well, released.  By default KeyPressed will be fired again and again if held down.  If you would prefer to have only a single event fired for a key press you can change this behaviour using the RenderWindow setKeyRepeatEnabled().

 

This is an example of Event driven programming in which your program responds to events as they occurred.  Sometimes however you would rather poll for input then wait for it to occur.  For example you might want to ask “hey computer, what keys are pressed?” or “is the control key down?”.  Fortunately SFML supports this out of the box, like so:

  if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
      // Do something

 

This code snippet first checks if the ‘R’ key is currently pressed.  It then checks to see if the Control key is pressed, as you can see in the example above the left and right control keys are separate events.  You can mix and match event driven and polled input handling however you want, but be careful not to get in a situation where you are accidentally handling the same input multiple times.

 

We are going to create a full example in a second that puts all of these processes together by randomly changing the screen color based on keys being pressed.  First, lets cover that process of creating a random number, a very common process in game development.  In fact, random number generation used to be part of SFML, but as of SFML 2.0 it was removed, partly because it didn’t make sense and partly because it’s now well entrenched in the language in a cross platform manner.

 

There are two ways we can generate random numbers, using the older C style, or the more modern C++ 11 style.  The new way is more appropriate for generating truly random numbers for security reasons and has no global state, but the old C style way should be more than sufficient for game development, so pick the way you like best.  The process is very similar… you generate a sequence of random numbers using some form of seed value, then massage the results into the numeric range you want.  Let’s look first at the C way of generating randoms:

  srand(time(NULL));               //seed random number generator with the current time
  auto randomNumber = rand() % 255;//generate a random number then confine it to a value of 0-255.

The first call sends the random number generator using the current system time.  Then we call rand() to get a random number.  One important thing to be wary off, the seeding process is fairly slow, while the rand() call is slightly lighter weight.  Next we look at the C++ way:

  std::uniform_int_distribution<int> randomColorRange(0, 255);
  std::random_device rd;
  std::mt19937 randomNumbers(rd());
  auto randomVal = randomColorRange(randomNumbers);

This example does basically the same thing as the earlier version.  The uniform_int_distribution object is a lightweight object that can be used to massage the data generated by mt19937 algorithm into actual int values within the defined range.  The mt19937 is an implementation of Mersenne Twister algorithm for generating random numbers.  The random_device is a built in object for creating a seed for your random number generator instead of using the current time ( although it’s quite possible that random_device uses the time behind the scenes ).  Using random_device is heavy weight, as is mt19937, so be careful where you generate random numbers.  However using those generated numbers with a uniform_int_distribution is light weight.

 

Ok, so we now know how to respond to keyboard events, poll the keyboard directly and generate random numbers, let’s tie it all together in a single example.

// This example demostrates the main loop

#include "SFML/Graphics.hpp"
#include <iostream>
#include <random>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // A Clock starts counting as soon as it's created
  sf::Color color(sf::Color::Red);


  // C++ 11 way of generating a random between 0 - 255
  // mt19937 is an implementation of the Mersenne Twister pseudo random number generator
  // random_device() returns a random number to use as a seed for the mt algorithm... slow however so that's why we dont just use it for all randoms if you were wondering
  // mt results arent in a human friendly format, so we use uniform_int_distribution to "shape" the results to our range and type
  // uniform_int_distribution is a fairly "light" object.  random_device and mt19937 aren't.
  std::uniform_int_distribution<int> randomColorRange(0, 255);
  std::random_device rd;
  std::mt19937 randomNumbers(rd());
  
  // Pre-C++ 11 but more common way (*with issues, see:
  //https://www.reddit.com/r/programming/comments/1rnudl/quite_interesting_why_cs_rand_is_considered/
  // Mostly doesn't apply to game devs if not using rand for say... security.
  
  /*
  srand(time(NULL));          //seed random number generator with the current time
  auto randomNumber = rand() % 255;   //generate a random number then confine it to a value of 0 - 255.
  */

  while (renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();

      //Respond to key pressed events
      if (event.type == sf::Event::EventType::KeyPressed){
        if (event.key.code == sf::Keyboard::Space){
          color.r = randomColorRange(randomNumbers);
        }
      }
    }

                      
    // Now demonstrate input via polling
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.r = 0;
      else
        color.r = randomColorRange(randomNumbers);

    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::G))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.g = 0;
      else
        color.g = randomColorRange(randomNumbers);
    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::B))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.b = 0;
      else
        color.b = randomColorRange(randomNumbers);

    

    renderWindow.clear(color);
    renderWindow.display();
  }

}

 

All we are doing in this example is setting the clear color of the RenderWindow based on keyboard input.  On pressing the spacebar we handle this using event driven input and set the Red channel of our clear color to a random value between 0-255.  A value of 0 means no red, while 255 is fully red.  We then directly poll the keyboard for input look to see if the R/G/B keys are pressed.  If they are, we assign that color channel to a random value.  If we also have the control key pressed, we instead set that channel to 0.  Therefore pressing CTRL+R, CTRL+G, CTRL+B will result in a black window.

 

As you can see, SFML makes it simple to handle keyboard input, both using an event driven model or by polling.  One thing it does not provide however is any sense of history.  We can check if a key was pressed or released during a given frame but we can’t really track the history a very common requirement.  That said, rolling your own solution is very simple, as shown below:

// This example demostrates the main loop

#include "SFML/Graphics.hpp"
#include <unordered_map>
#include <iostream>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // If true, you will continue to receive keyboard events when a key is held down
  // If false, it will only fire one event per press until released
  renderWindow.setKeyRepeatEnabled(false);

  std::unordered_map<int, bool> keys;
  std::list<int> changedKeys;

  while (renderWindow.isOpen()){
    changedKeys.clear();

    while (renderWindow.pollEvent(event)){
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();

      if (event.type == sf::Event::EventType::KeyPressed){
        if (keys.count(event.key.code) == 0){
          keys[event.key.code] = true;
          changedKeys.push_back(event.key.code);
        }
      }
      if (event.type == sf::Event::EventType::KeyReleased){
        if (keys.count(event.key.code) == 1){
          keys.erase(event.key.code);
          changedKeys.push_back(event.key.code);
        }
      }
    }

    std::cout << "Currently pressed keys: ";

    // To get the actual value as a string, you need to use Thor or write your own version
    for (auto& keyValue : keys)
      std::cout << keyValue.first << " ";
    std::cout << std::endl;

    if (!changedKeys.empty()){
      std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Keys changed" << std::endl;
    }
    renderWindow.clear();
    renderWindow.display();
  }

}


This approach is pretty typical of SFML.  The basic tools are there for you, but you may have to build a layer on top to fit your game.  That said, there is a library called Thor that covers many of these common scenarios, essentially a utility library built over top of SFML providing additional functionality.  For example, in addition to providing the kind of functionality we just implemented above, there is also a utility for turning SFML Key enum values into a printable format.  We will probably cover using at least parts of Thor at a later point in this series, but for now I want to focus on core SFML.

 

The Video


Programming


9. October 2015

 

In this part of the SFML we will look at creating our first basic SFML application.  At the heart of every SFML application is the RenderWindow which provides both a way to draw things on screen and receive input events from the user.

 

As always, there is an HD video of this tutorial here.

 

At the heart of every non-trivial game is the game loop.  In some game engines it’s hidden away from you inside the engine, but it is always there somewhere.  In SFML it is your responsibility to implement, which is what we will do today.  A game loop is a pretty simple concept… it’s a loop that runs over and over until your game is completed.  Each pass through the loop the screen is cleared and new graphics are drawn (this is referred to as a frame, so when you hear Frames Per Second, this is what is being referred to).  There are several other tasks a game is responsible for handling… input and physics to name just two.

 

Let’s start off with a very simple application:

#include "SFML/Graphics.hpp"

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  while (true) {
    renderWindow.clear();
    renderWindow.display();
  }

}

This represents about the simplest meaningful SFML application you can create.  We create a new RenderWindow, passing in both its dimensions and title.  Then we simply loop forever and each pass through the loop we clear the window then draw it again with a call to display().

 

When you run this code you will get a black 640x480 window on screen, however if you attempt to move or close this window you will quickly notice something is wrong.  It doesn’t respond to any of your actions.  In fact, if you lose focus (click on a different window) you can’t even get it to focus again!  This is because we aren’t responding to any events.  Let’s switch things up a bit so that are window is a tad more responsive.  Instead of simply looping forever, we will create a slightly more intelligent game loop.

  sf::Event event;
  while(renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }
  
    renderWindow.clear();
    renderWindow.display();
  }

Now your window properly responds to events, it can be moved around and most importantly, it can be closed.  Let’s take a quick look at what we’ve done here.

 

First off, instead of looping forever, we instead loop until our RenderWindow is closed.  Next inside this loop we’ve implemented another while loop that calls pollEvent.  pollEvent checks for all of the events that occurred since the last time pollEvent was called.  It is called inside a while loop because it is possible that multiple events occurred since the last pass through the outer loop.  pollEvent() will return false when no more events exist.  Events exist for things such as mouse and keyboard actions or the window being resized.  In this particular case we are checking to see if the EventType is Closed, which means a close request has occured.  In the event that one does we call renderWindow.close() which will result in the next check of isOpen() to return false, thus ending our game.

 

We will cover events in more detail later, but for an idea of what EventTypes exist, click here.  There are two very important things to realize in this game loop.  Notice that the sf::Event is declared outside of the loop?  This code is going to be called ALOT.  Never put variable allocations, even stack based ones like this, inside a high frequency loop if it can be helped.  Second, notice how the clear() and display() calls are outside of the inner pollEvent() loop?  This is also important, as otherwise your screen with only update when an event occurs!

 

There is one final important concept to cover before we move on to the next tutorial… time.  It is quite common for a game engine to provide the elapsed time since the last frame.  This value is very useful to your entire game as we will see shortly.  In SFML however you are rolling your own game loop, so you are also rolling your own time tracking system.  Don’t worry though, the process is extremely simple.  That’s see one final complete sample that also keeps track of the elapsed time per frame.

#include "SFML/Graphics.hpp"
#include <iostream>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // A Clock starts counting as soon as it's created
  sf::Clock clock;
  
  while(renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }
  
    // A microsecond is 1/1,000,000th of a second, 1000 microseconds == 1 millisecond
    std::cout << "Elapsed time since previous frame(microseconds): " << clock.getElapsedTime().asMicroseconds() << std::endl;
    // Start the countdown over.  Think of laps on a stop watch.
    clock.restart();


    renderWindow.clear();
    renderWindow.display();
  }

}

You will notice the addition of an sf::Clock to our game.  The Clock provides the most accurate time that the underlying OS is capable of giving (different timers have different resolutions, and this timer needs to be very precise!).  As soon as it is declared, it starts counting.  Think of sf::Clock like a stopwatch that starts automatically.  Each “lap” you can read the elapsed time using getElapsedTime() and you can start a new lap by calling restart().   In this example we get the elapsed time in microseconds.  There are 1000 microseconds in a millisecond, and 1000 milliseconds in a second, so a microsecond is one millionth of a second.  Like I said, we need precision!

 

So that is the process of creating a very simple SFML application, clearing and displaying the window, tracking how much time elapsed and handling events.  In the next tutorial we will look at events a bit closer and see how best to handle keyboard input.

 

The Video

 

Programming


7. October 2015

 

This text tutorial is a companion to this video tutorial showing how to create and configure a new SFML project using Visual C++ 2013.  If you are running Visual Studio 2015 instead, the process should be virtually 100% identical, although you will have to download a different set of files.

 

First you need to download a version of SFML.  Head on over to the SFML download page and select the newest SFML version, as of writing 2.3.2:

image 

 

Now you need to figure out which version to download.  This mostly comes down to identifying what C++ compiler you are using as well as the “bit-ness” you want to target.  Keep in mind, even though you OS is 64bit, it is likely that you want to use the 32bit version.  This is especially true if your game is meant to run on Windows XP.  A 32bit binary can run on a 64bit OS, but not the opposite.  Additionally, for a 2D game, 64bit doesn’t really get you all that much in return.  In the end though, it doesn’t really matter which one you choose, just be aware of the results.

image

 

Now that we have SFML downloaded, extract the resulting zip file somewhere.

 

Now load up Visual Studio and create a new C++ project of type Win32 Console Application:

image

Name it and locate it however you want then click ok.

 

A new window will pop up, click next, then on the next screen, I used the following settings:

image

Click Finish.

 

We now have a project, let’s add a bit of code to it.   In solution explorer, right click your the Source Files folder in your project and choose Add->New Item..

image

 

Now choose C++ file and name it Main.cpp.

image

 

Click Add and your file is created.

 

Now enter the following code:

#include "SFML/Graphics.hpp"


int main(int argc, char** argv)
{
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Hello SFML");
  while (true){
    renderWindow.clear();
    renderWindow.display();
  }
}

 

You will notice lots of errors in Visual Studio, like so:

image

Don’t worry, we will fix these in a second.

 

Copying files from SFML

Open up the archive you downloaded earlier from sfml.  The contents should look something like this:

image

Copy the folders include and lib to your project directory, which should now look something like this:

image

 

Leave the SFML folder open, we will need it again in a second.

 

Configuring Visual Studio

 

Now that we have the libraries and header files copied into our project, we need to tell Visual Studio about them.  Right click your project and select Properties:

image

 

In the resulting dialog, select C++ on the left, then Additional Include Directories:

image

 

Enter the following value (for more detailed explanations, watch the video, it goes more into the why of things):

image

Make sure to hit enter and it goes bold so you know your setting was saved.

 

Now we need to configure the linker.  On the left hand side select Linker instead of C++ then Additional Library Directories:

image

 

Now enter the following:

image

 

Next we need to add our lib files.  Under linker, select Input, then locate Additional Dependencies on the right.

image

 

Assuming you are using all of the components of SFML and linking to DLLs ( see video for more options ), click in the white area and select edit and add the following (order is important!):

image

 

Your project should now be configured.  Hit CTRL+SHIFT+B to build it.  Don’t run it yet, it wont work without the DLLs, but we need to build it once to have the proper folders made.  Assuming your build went without errors, you should now have a Debug folder inside your project directory, like so:

image

 

Now, remember the SFML zip file I told you to keep open?  Switch back to it and select the contents of the bin folder:

image

And paste them into your Debug directory.  This folder actually contains both debug and release dlls, and you only need the debug for now, but disk space is cheap, no? :)  We will cover building for release at a later date and I will go into the difference in more details then.

 

Now your “game” should be ready to run, hit F5:

image

 

Congratulations, you just completed your first successful SFML project.  Now let’s head over to the next tutorial and make it actually do something!

 

The Video

 

Programming


GFS On YouTube

See More Tutorials on DevGa.me!

Month List