Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
SFML Game Development By Example

You're reading from   SFML Game Development By Example Create and develop exciting games from start to finish using SFML

Arrow left icon
Product type Paperback
Published in Dec 2015
Publisher
ISBN-13 9781785287343
Length 522 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Raimondas Pupius Raimondas Pupius
Author Profile Icon Raimondas Pupius
Raimondas Pupius
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. It's Alive! It's Alive! – Setup and First Program 2. Give It Some Structure – Building the Game Framework FREE CHAPTER 3. Get Your Hands Dirty – What You Need to Know 4. Grab That Joystick – Input and Event Management 5. Can I Pause This? – Application States 6. Set It in Motion! – Animating and Moving around Your World 7. Rediscovering Fire – Common Game Design Elements 8. The More You Know – Common Game Programming Patterns 9. A Breath of Fresh Air – Entity Component System Continued 10. Can I Click This? – GUI Fundamentals 11. Don't Touch the Red Button! – Implementing the GUI 12. Can You Hear Me Now? – Sound and Music 13. We Have Contact! – Networking Basics 14. Come Play with Us! – Multiplayer Subtleties Index

Drawing images in SFML

In order to draw an image on screen, we need to become familiar with two classes: sf::Texture and sf::Sprite. A texture is essentially just an image that lives on the graphics card for the purpose of making it fast to draw. Any given picture on your hard drive can be turned into a texture by loading it:

sf::Texture texture;
if(!texture.loadFromFile("filename.png"){
    // Handle an error.
}

The loadFromFile method returns a Boolean value, which serves as a simple way of handling loading errors, such as the file not being found. If you have a console window open along with your SFML window, you will notice some information being printed out in case the texture loading did fail:

Failed to load image "filename.png". Reason : Unable to open file

Tip

Unless a full path is specified in the loadFromFile method, it will be interpreted as relative to the working directory. It's important to note that while the working directory is usually the same as the executable's when launching it by itself, compiling and running your application in an IDE (Microsoft Visual Studio in our case) will often set it to the project directory instead of the debug or release folders. Make sure to put the resources you're trying to load in the same directory where your .vcxproj project file is located if you've provided a relative path.

It's also possible to load your textures from memory, custom input streams, or sf::Image utility classes, which help store and manipulate image data as raw pixels, which will be covered more broadly in later chapters.

What is a sprite?

A sprite, much like the sf::Shape derivatives we've worked with so far, is a sf::Drawable object, which in this case represents a sf::Texture and also supports a list of transformations, both physical and graphical. Think of it as a simple rectangle with a texture applied to it:

What is a sprite?

sf::Sprite provides the means of rendering a texture, or a part of it, on screen, as well as means of transforming it, which makes the sprite dependent on the use of textures. Since sf::Texture isn't a lightweight object, sf::Sprite comes in for performance reasons to use the pixel data of a texture it's bound to, which means that as long as a sprite is using the texture it's bound to, the texture has to be alive in memory and can only be de-allocated once it's no longer being used. After we have our texture set up, it's really easy to set up the sprite and draw it:

sf::Sprite sprite(texture);
...
window.draw(sprite);

It's optional to pass the texture by reference to the sprite constructor. The texture it's bound to can be changed at any time by using the setTexture method:

sprite.setTexture(texture);

Since sf::Sprite, just like sf::Shape, inherits from sf::Transformable, we have access to the same methods of manipulating and obtaining origin, position, scale, and rotation.

It's time to apply all the knowledge we've gained so far and write a basic application that utilizes it:

void main(int argc, char** argv[]){
  sf::RenderWindow window(sf::VideoMode(640,480),
    "Bouncing mushroom.");

  sf::Texture mushroomTexture;
  mushroomTexture.loadFromFile("Mushroom.png");
  sf::Sprite mushroom(mushroomTexture);
  sf::Vector2u size = mushroomTexture.getSize();
  mushroom.setOrigin(size.x / 2, size.y / 2);
  sf::Vector2f increment(0.4f, 0.4f);

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

    if((mushroom.getPosition().x + (size.x / 2) >
      window.getSize().x && increment.x > 0) ||
      (mushroom.getPosition().x - (size.x / 2) < 0 &&
      increment.x < 0))
    {
        // Reverse the direction on X axis.
        increment.x = -increment.x;
    }

    if((mushroom.getPosition().y + (size.y / 2) >
      window.getSize().y && increment.y > 0) ||
      (mushroom.getPosition().y - (size.y / 2) < 0 &&
      increment.y < 0))
    {
         // Reverse the direction on Y axis.
        increment.y = -increment.y;
    }

    mushroom.setPosition(mushroom.getPosition() + increment);

    window.clear(sf::Color(16,16,16,255)); // Dark gray.
    window.draw(mushroom); // Drawing our sprite.
    window.display();
  }
}

The code above will produce a sprite bouncing around the window, reversing in direction every time it hits the window boundaries. Error checking for loading the texture is omitted in this case in order to keep the code shorter. The two if statements after the event handling portion in the main loop are responsible for checking the current position of our sprite and updating the direction of the increment value represented by a plus or minus sign, since you can only go towards the positive or negative end on a single axis. Remember that the origin of a shape by default is its top-left corner, as shown here:

What is a sprite?

Because of this, we must either compensate for the entire width and height of a shape when checking if it's out-of-bounds on the bottom or the right side, or make sure its origin is in the middle. In this case, we do the latter and either add or subtract half of the texture's size from the mushroom's position to check if it is still within our desired space. If it's not, simply invert the sign of the increment float vector on the axis that is outside the screen and voila! We have bouncing!

What is a sprite?

For extra credit, feel free to play around with the sf::Sprite's setColor method, which can be used to tint a sprite with a desired color, as well as make it transparent, by adjusting the fourth argument of the sf::Color type, which corresponds to the alpha channel:

mushroom.setColor(sf::Color(255, 0, 0, 255)); // Red tint.
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime