Sign in to follow this  
PhantomRonin

SFML help

Recommended Posts

Cornstalks    7030
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.

Share this post


Link to post
Share on other sites
PhantomRonin    131
[quote name='Cornstalks' timestamp='1355628973' post='5011153']
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.
[/quote]

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?

Share this post


Link to post
Share on other sites
JTippetts    12950
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
PhantomRonin    131
[quote name='Servant of the Lord' timestamp='1355630922' post='5011163']
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?
[/quote]

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]

Share this post


Link to post
Share on other sites
JTippetts    12950
Personally, I would make sprite a member and return a reference to it:

[code]
class Enemy
{
// snip

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

private:
sf::Sprite sprite_;
};
[/code]

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.

Share this post


Link to post
Share on other sites
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:
[code]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.

};[/code]

Share this post


Link to post
Share on other sites
PhantomRonin    131
[quote name='Servant of the Lord' timestamp='1355634729' post='5011175']
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:
[code]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.

};[/code]
[/quote]


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

Share this post


Link to post
Share on other sites
PhantomRonin    131
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]

Share this post


Link to post
Share on other sites
JTippetts    12950
[quote name='PhantomRonin' timestamp='1355669990' post='5011281']
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
[/quote]

So essentially you are having your graphics manager create a sprite, passing that sprite a texture, then returning the sprite by value from the method so that elsewhere you are assigning that returned sprite to your class Sprite member? It's okay to do it that way, the Sprite copy and assignment operators are well implemented. It does result in some unnecessary copying, but since it's only done once per object it shouldn't be a problem, and it's a very miniscule amount of data to be copied anyway

Edit: My own personal preference in a situation like that is to have the graphic manager manage graphics only (ie, textures). I write a method, called something like getTexture(), which will load the named texture if not already loaded. Then rather than a method in my object class called setSprite(), I would call setTexture() instead. The reasoning for this is that it should not be the responsibility of the graphic manager to know what texture to assign a given object. The graphic manager should not be the one making the decision that this object gets the player texture, while that object gets the enemy texture. What if you want to implement more than one type of enemy? Or what about special effects? The graphic manager should just be a dumb class, solely responsible for managing graphics. (The Single Responsibility Principle) Giving it more responsibility than that only complicates the code when you want to expand it.

.In that case, your player creation might look like this instead:

[code]
player.setTexture(graphicsManager.getTexture("playerSprite.png"));
[/code]

In this case, it is trivial to use a different sprite image for another object. Edited by JTippetts

Share this post


Link to post
Share on other sites
EddieV223    1839
IF you have a Sprite object that is the same through out your program, you should use the same sprite, no need to have mutliple of the same data loaded. Creating a sprite manager class that manages them and has methods for getting pointers to sprites, and/or use shared_ptr/weak_ptr.

This is a pretty good place to use shared_ptr, because you may not want the added complexity of a SpriteManager, however you do want to pass around the same object in a reference style. If you have a c++11 compiler ( VS2012, MINGW, GNU ) then you can use shared_ptr to do this, it would be a good solution.

You could even type def to something easier like

typedef std::shared_ptr<Sprite> SharedSprite; Edited by EddieV223

Share this post


Link to post
Share on other sites
Cornstalks    7030
[quote name='EddieV223' timestamp='1355697194' post='5011379']
IF you have a Sprite object that is the same through out your program, you should use the same sprite, no need to have mutliple of the same image loaded. Creating a sprite manager class that manages them and has methods for getting pointers to sprites, and/or use shared_ptr/weak_ptr.
[/quote]
In SFML, a [font=courier new,courier,monospace]Sprite[/font] doesn't own the texture, it just stores a reference to it. You can have multiple sprites all using the same texture without any kind of sprite manager.

Share this post


Link to post
Share on other sites
EddieV223    1839
[quote name='Cornstalks' timestamp='1355697497' post='5011383']
[quote name='EddieV223' timestamp='1355697194' post='5011379']
IF you have a Sprite object that is the same through out your program, you should use the same sprite, no need to have mutliple of the same image loaded. Creating a sprite manager class that manages them and has methods for getting pointers to sprites, and/or use shared_ptr/weak_ptr.
[/quote]
In SFML, a [font=courier new,courier,monospace]Sprite[/font] doesn't own the texture, it just stores a reference to it. You can have multiple sprites all using the same texture without any kind of sprite manager.
[/quote]

Ok I changed Image to data.

Share this post


Link to post
Share on other sites
JTippetts    12950
Doesn't really make sense to share sprites, since they encapsulate transformation data. If the two objects share the exact same position, orientation, scale and image, then I would say you have not two different objects, just one object and one duplicate.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this