Jump to content

  • Log In with Google      Sign In   
  • Create Account


SFML help


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 PhantomRonin   Members   -  Reputation: 131

Like
0Likes
Like

Posted 15 December 2012 - 09:21 PM

If I am sending sf::Sprite objects between classes should I be using pointers?

Sponsor:

#2 Cornstalks   Crossbones+   -  Reputation: 6966

Like
0Likes
Like

Posted 15 December 2012 - 09:36 PM

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 sf::Sprite if you don't use references/pointers. If you want them to share the same sf::Sprite, you have to use references/pointers.
[ 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 ]

#3 PhantomRonin   Members   -  Reputation: 131

Like
0Likes
Like

Posted 15 December 2012 - 09:38 PM

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 sf::Sprite if you don't use references/pointers. If you want them to share the same sf::Sprite, 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?

#4 JTippetts   Moderators   -  Reputation: 8161

Like
2Likes
Like

Posted 15 December 2012 - 09:56 PM

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.

#5 Servant of the Lord   Crossbones+   -  Reputation: 17281

Like
1Likes
Like

Posted 15 December 2012 - 10:08 PM

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?

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#6 PhantomRonin   Members   -  Reputation: 131

Like
0Likes
Like

Posted 15 December 2012 - 10:26 PM

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]

#7 JTippetts   Moderators   -  Reputation: 8161

Like
1Likes
Like

Posted 15 December 2012 - 10:54 PM

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.

#8 Servant of the Lord   Crossbones+   -  Reputation: 17281

Like
0Likes
Like

Posted 15 December 2012 - 11:12 PM

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.
     
};

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#9 PhantomRonin   Members   -  Reputation: 131

Like
0Likes
Like

Posted 16 December 2012 - 08:59 AM

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

#10 PhantomRonin   Members   -  Reputation: 131

Like
0Likes
Like

Posted 16 December 2012 - 09:14 AM

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]

#11 JTippetts   Moderators   -  Reputation: 8161

Like
0Likes
Like

Posted 16 December 2012 - 09:14 AM

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


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:

player.setTexture(graphicsManager.getTexture("playerSprite.png"));

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

Edited by JTippetts, 16 December 2012 - 09:20 AM.


#12 EddieV223   Members   -  Reputation: 1393

Like
0Likes
Like

Posted 16 December 2012 - 04:33 PM

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, 16 December 2012 - 09:32 PM.

If this post or signature was helpful and/or constructive please give rep.

 

// C++ Video tutorials

http://www.youtube.com/watch?v=Wo60USYV9Ik

 

// Easy to learn 2D Game Library c++

SFML2.1 Download http://www.sfml-dev.org/download.php

SFML2.1 Tutorials http://www.sfml-dev.org/tutorials/2.1/

 

// SFML 2 book

http://www.amazon.com/gp/product/1849696845/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1849696845&linkCode=as2&tag=gamer2creator-20

 


#13 Cornstalks   Crossbones+   -  Reputation: 6966

Like
0Likes
Like

Posted 16 December 2012 - 04:38 PM

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.

In SFML, a Sprite 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.
[ 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 ]

#14 EddieV223   Members   -  Reputation: 1393

Like
0Likes
Like

Posted 16 December 2012 - 09:33 PM


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.

In SFML, a Sprite 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.


Ok I changed Image to data.

If this post or signature was helpful and/or constructive please give rep.

 

// C++ Video tutorials

http://www.youtube.com/watch?v=Wo60USYV9Ik

 

// Easy to learn 2D Game Library c++

SFML2.1 Download http://www.sfml-dev.org/download.php

SFML2.1 Tutorials http://www.sfml-dev.org/tutorials/2.1/

 

// SFML 2 book

http://www.amazon.com/gp/product/1849696845/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1849696845&linkCode=as2&tag=gamer2creator-20

 


#15 JTippetts   Moderators   -  Reputation: 8161

Like
0Likes
Like

Posted 16 December 2012 - 10:31 PM

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS