user2933244
user2933244

Reputation:

Global variable is out of scope! What the heck?

Houston, we have a problem. Here's a simplified code version:

main.cpp

#include <SFML/Graphics.hpp>
#include "global.hpp"
#include "init.hpp"
int main(void)
{
    createWindow();
    loadLevel();

    while(window.isOpen())
    {
        if(!handleEvents()) window.close();
        window.clear();
        window.draw(bgSprite);
        window.display();
    }
    return 0;
}

global.hpp

sf::Texture      bgTexture;
sf::Sprite       bgSprite;

init.hpp

void loadGraphics(void)
{
    bgTexture.loadFromFile("bg.png");
    bgSprite.setTexture(bgTexture);
}

Even though the texture and sprite variables are global, window screen remains black. However, when I put the variables inside the main() function, everything works perfectly. Could someone explain why is this happening?

I thought that you can call global variables whenever and wherever you wish, and they will disappear only when the program itself terminates.

By the way, I also tried putting the variables and loadGraphics() right behind main() (not in a header file), still, no results. I also commented out all additional code, so the problem definitely lies here.

EDIT: I AM AN IDIOT!

I didn't call the loadGraphics(function). Thank You! I'm sorry for your wasted time. Everything started working correctly. Sad lol - spent over 1 hour fixing this thing...

Upvotes: 0

Views: 653

Answers (3)

Mike Seymour
Mike Seymour

Reputation: 254461

You never call loadGraphics. Call that at the start of main, and your program will probably work.

But you'd almost certainly be better off without globals; and in any case, you don't want to define them in a header since that will break the One Definition Rule if you include that header more than once in your program.

If you really do want them to be global, then declare them (without definining them) in the header:

extern sf::Texture bgTexture;

and define them (as you've done) in just one source file.

Likewise, you shouldn't define a non-inline function in a header for the same reason. Either leave it in the header and make it inline:

inline void loadGraphics()     // void parameter is pointless
{
    bgTexture.loadFromFile("bg.png");
    bgSprite.setTexture(bgTexture);
}

or just declare it in the header

void loadGraphics();

and move your definition into a source file.

You might avoid globals by encapsulating them in a class:

struct Graphics {
    Graphics(std::string file) {
        texture.loadFromFile(file);
        sprite.setTexture(texture);
    }

    sf::Texture texture;
    sf::Sprite sprite;
};

and instantiating this in main

Graphics graphics("bg.png");
//...
window.draw(graphics.sprite);

Upvotes: 4

Jay Bosamiya
Jay Bosamiya

Reputation: 3209

When you place a variable global to a project, you need to place it in a .cpp file and make a .h which declares it as extern. This allows for all the files to refer to the same global variable.

In your case, you'd change the code as so:

global.hpp

extern sf::Texture bgTexture;
extern sf::Sprite  bgSprite;

global.cpp

sf::Texture      bgTexture;
sf::Sprite       bgSprite;

Also, as in Mike's answer, you never call loadGraphics().

Personally, I'd put that in another .cpp file and put a .hpp file with the prototype.

Also, when compiling, you'll have to compile all the cpp files together into a single executable (i.e. link them together)

Upvotes: 2

J&#233;r&#244;me
J&#233;r&#244;me

Reputation: 8066

bgTexture and bgSprite are never set. I don't see any call to your loadGraphics function in the main.

You should start by calling your loadGraphics function

Upvotes: 0

Related Questions