SFML help

Started by
13 comments, last by JTippetts 11 years, 4 months ago
If I am sending sf::Sprite objects between classes should I be using pointers?
Advertisement
Depends on what you want. It's safe to not use pointers, but you have to realize that the two classes will each have their own copy of the [font=courier new,courier,monospace]sf::Sprite[/font] if you don't use references/pointers. If you want them to share the same [font=courier new,courier,monospace]sf::Sprite[/font], you have to use references/pointers.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Depends on what you want. It's safe to not use pointers, but you have to realize that the two classes will each have their own copy of the [font=courier new,courier,monospace]sf::Sprite[/font] if you don't use references/pointers. If you want them to share the same [font=courier new,courier,monospace]sf::Sprite[/font], you have to use references/pointers.


Im talking about from an efficacy point of view. Will my code run slowly if I am sending a hand full of sprites around at start up?
Have you profiled to find out?

Typically, the first thing you should do when you have a question on performance is to construct some sort of prototype or test and profile it to see where the bottlenecks lie. Because, really, the only way you'll know whether something will be too slow for your particular needs is to profile, since the performance of any given technique is going to depend on so many different variables.

That being said, I'm having a hard time picturing exactly what it is you are doing. A SFML Sprite is a class that encapsulates a reference to a Texture along with a set of transforms for drawing at a given position/scale/orientation and a bounding rectangle for collisions, among other things. Typical use case is that each object that needs to be drawn on the screen has its own Sprite; it's not really common to have multiple objects sharing a Sprite. Usually, they might share a Texture (in the case of similar objects) but each will have their own Sprite, and the Texture is automatically shared by reference in the underlying implementation of the Sprite class so you don't really have to worry about that.
As a general rule of thumb, I pass structs and classes by const reference or non-const references, and only copy something when I actually want a duplicate.
Basic variables like int and float I pass by value, normally.

Could you show a real piece of code as an example, to clarify your question?

As a general rule of thumb, I pass structs and classes by const reference or non-const references, and only copy something when I actually want a duplicate.
Basic variables like int and float I pass by value, normally.

Could you show a real piece of code as an example, to clarify your question?


Basically how I have it set up right now I have Player class, Enemy class, and Graphics class.

The graphics calls loads all the textures. Then I send over the sprite using the function below to the class that needs it.

[source lang="cpp"]sf::Sprite GraphicsManager::getSprite(int textureID)
{
sf::Sprite sprite;
switch(textureID)
{
case 1:
sprite.setTexture(player);
return sprite;
case 2:
sprite.setTexture(enemie);
return sprite;
case 3:
sprite.setTexture(ball);
return sprite;
}
}
[/source]
Thinking about it now would it be better to keep everything in the graphics class and do something like this when drawing?

[source lang="java"]window.draw( graphics.getsprite(player.x,player.y,player_spriteID);[/source]
Personally, I would make sprite a member and return a reference to it:


class Enemy
{
// snip

public:
sf::Sprite &getSprite(){return sprite_;}

private:
sf::Sprite sprite_;
};


sf::Sprite does support the full range of copy constructors etc... so it's technically fine to constantly be copying, building temporaries, returning temporaries by value, etc... but it still amounts to a lot of unnecessary copying. Better to maintain a sprite per object, return by reference when necessary, and cut out some of that copying.
As JTippets mentioned, just give each object its own sprite. You could share textures between similar types of objects, but you don't need to do all the hassle of a "graphics manager", especially when that "manager" doesn't actually manage the lifetime of your graphics.

But hey, if every Enemy has the same appearance, you could even share their texture statically:
class Enemy
{
public:
static bool LoadResources(); //Loads all the static textures. Called once at program startup.

enum class Appearance {Normal, Fast, Powerful, Dead};

public:
Enemy();

void SetAppearance(Appearance appearance)
{
if(appearance == Appearance::Fast)
{
this->sprite.setTexture(Enemy::fastTexture);
}
else if(appearance == Appearance::Powerful)
{
this->sprite.setTexture(Enemy::powerfulTexture);
}
else if(appearance == Appearance::Dead)
{
this->sprite.setTexture(Enemy::deadTexture);
}
else //Normal appearance.
{
//Randomly choose one of the two 'normal' enemy textures.

if( random choice 1 )
{
this->sprite.setTexture(Enemy::normalTexture1);
}
else
{
this->sprite.setTexture(Enemy::normalTexture2);
}
}

}

private:
sf::Sprite sprite; //Each enemy has it's own sprite.

static sf::Texture normalTexture1; //Normal enemy texture, shared between all 'Enemy' instances.
static sf::Texture normalTexture2; //An alternative texture for normal enemies.
static sf::Texture fastTexture; //Texture for 'fast' enemies.
static sf::Texture powerfulTexture; //Texture for 'powerful' enemies.
static sf::Texture deadTexture; //Texture for dead enemies.

};

As JTippets mentioned, just give each object its own sprite. You could share textures between similar types of objects, but you don't need to do all the hassle of a "graphics manager", especially when that "manager" doesn't actually manage the lifetime of your graphics.

But hey, if every Enemy has the same appearance, you could even share their texture statically:
class Enemy
{
public:
static bool LoadResources(); //Loads all the static textures. Called once at program startup.

enum class Appearance {Normal, Fast, Powerful, Dead};

public:
Enemy();

void SetAppearance(Appearance appearance)
{
if(appearance == Appearance::Fast)
{
this->sprite.setTexture(Enemy::fastTexture);
}
else if(appearance == Appearance::Powerful)
{
this->sprite.setTexture(Enemy::powerfulTexture);
}
else if(appearance == Appearance::Dead)
{
this->sprite.setTexture(Enemy::deadTexture);
}
else //Normal appearance.
{
//Randomly choose one of the two 'normal' enemy textures.

if( random choice 1 )
{
this->sprite.setTexture(Enemy::normalTexture1);
}
else
{
this->sprite.setTexture(Enemy::normalTexture2);
}
}

}

private:
sf::Sprite sprite; //Each enemy has it's own sprite.

static sf::Texture normalTexture1; //Normal enemy texture, shared between all 'Enemy' instances.
static sf::Texture normalTexture2; //An alternative texture for normal enemies.
static sf::Texture fastTexture; //Texture for 'fast' enemies.
static sf::Texture powerfulTexture; //Texture for 'powerful' enemies.
static sf::Texture deadTexture; //Texture for dead enemies.

};




Each object does have its own sprite. I load up all the textures in the graphics class. Then I create a sprite and send it over to another class. I only do this once per class. Anyway thanks for the advice everyone
This is what my main looks like

[source lang="cpp"]int main()
{
sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), WINDOW_TITLE);
window.setTitle(WINDOW_TITLE);

GraphicsManager graphicsManager;
graphicsManager.loadTextures();

Player player;
player.setSprite( graphicsManager.getSprite(1) );
player.setWeaponSprite( graphicsManager.getSprite(3) );

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

player.getInput();


window.clear();
window.draw(player.getSprite());
window.display();
}

return 0;
}[/source]

This topic is closed to new replies.

Advertisement