Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Trying to load sprites from List of Sprites, all sprites share one tex?  (Read 3464 times)

0 Members and 1 Guest are viewing this topic.

GregStuart

  • Newbie
  • *
  • Posts: 4
    • View Profile
Hey, I have a weird issue.

So, I have this method that should make 8x8 sprites from a spritesheet and put them into a list of sprites, which it does.

however, when I spawn a sprite, It shares the same texture as the very last Sprite in the list.

So, Sprite 1 should have texture 1, but it has the texture of sprite 128.

This is the same for every sprite in my list.

How would I resolve this?

If I was going to take a guess, I'd need to also store the texture somehow? perhaps in a second textures vector? but then whenever I loaded a sprite I'd need to set the texture of it equal to the texture at the same position in the sister vector? I feel like I'm overcomplicating this/doing it the wrong way.

http://imgur.com/gfkiCbb

Any help would be appreciated.

Quote
void SpriteMaker(int dimension, int scale)
{


   int c = 0, r = 0, y = sheetIMG.getSize().y, x = sheetIMG.getSize().x;

   do
   {
      for (int i = 0; i <= (x * y) / 64; i++)
      {
         if (r == 64)
            break;
         if (!tex.loadFromImage(sheetIMG, IntRect(c, r, dimension, dimension)))
            break;
         else
         {
            Sprite spr;
                spr.setTexture(tex);
            spr.setScale(scale, scale);
            Spritesheet.push_back(spr);
            c += dimension;
            if (c == x) { c = 0; r+=8; };
         }
      }
   } while (r < y);      
}
« Last Edit: May 06, 2016, 01:52:19 pm by GregStuart »

SpeCter

  • Full Member
  • ***
  • Posts: 151
    • View Profile
Are you reusing one and the same sf::Texture for each sprite?
If yes, the texture doesn't get copied into the sf::Sprite the sprite only holds a pointer/reference to it, so if you change the texture, it will be changed for every sprite.

GregStuart

  • Newbie
  • *
  • Posts: 4
    • View Profile
Basically, the texture is applied to the sprite, then the sprite is added to the list.


I reuse that tex object for all 128 sprites, so yes, it is overwritten 128 times.

Does this mean I need to have an instance of every texture in it's own array?

I'm changing my Game to a singleton object atm.

Mr_Blame

  • Full Member
  • ***
  • Posts: 192
    • View Profile
    • Email
Yes for 2 reasons
1.) you must have the sperate array for textures, because the sprite holds only a const pointer to texture.
2.) texture gets destroyed when its instance goes out of scope.

GregStuart

  • Newbie
  • *
  • Posts: 4
    • View Profile
Due to the lack of help.

I kinda did it "My way"

And I've probably done it in a very inefficient way.

I made this to hold the textures:

Quote
vector<Texture> Textures;

and in my MakeSprite method, after getting the texture, I push it onto the back, just like I do with sprites.

Quote
Textures.push_back(tex);
            Sprite spr;
                spr.setTexture(Textures.at(i));

then this basically sets the texture to the correct one.

Quote
Sprite Game::RenderSprite(int i, int x, int y)
{
   Spritesheet.at(i).setTexture(Textures.at(i));
   Spritesheet.at(i).setPosition(x, y);
   return Spritesheet.at(i);
}


The issue is, this is now getting called every frame.


Quote
int Game::MainLoop() {

   srand(time(NULL));


   RenderWindow window(VideoMode(1920, 1080), "Conduit");


   MakeCircle(10, 100, 100, Color::White);



   if (!LoadSpritesheet())
   {
      return 1;
   }

   while (window.isOpen()) {

      Event event;
      while (window.pollEvent(event)) {

         if (event.type == Event::Closed)
            window.close();
     
         
      }

      
      
      window.clear();

      window.draw(RenderSprite(2, 10, 10));
      window.draw(RenderSprite(4, 10, 40));
      window.draw(RenderSprite(10, 10, 80));
      window.draw(RenderSprite(11, 10, 120));

      DrawCircles(window);      
      window.display();
   }

}



But I guess it works?

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
There are seseveral problems with your solution.

- your vector holding textures is problematic since if the vector copies sprites when it needs to grow you'll invalidate any pointers held by sprites to elements in the vector. You can mitigate that either by holding pointers (or better yet, smart pointers) to textures in your vector or by making sure the vector never resizes by calling .reserve() on ot before you push_back the textures and then never push more into it than you reserve.

- don't use srand()/rand() they produce really poor random numbers and time(NULL) is a horrible seed. Use the facilities in the <tt>random</tt> header instead. See these two links:
 http://en.cppreference.com/w/cpp/numeric/random
 https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

- setting textures on all sprites every frame is inefficient and needless.

GregStuart

  • Newbie
  • *
  • Posts: 4
    • View Profile
What would you suggest I do?

Have a bool or something which I set to false after first render, and then only set to true again if the sprite has actually been changed?

fallahn

  • Sr. Member
  • ****
  • Posts: 495
  • Buns.
    • View Profile
    • Trederia
If you can, get a copy of the SFML Game Devleopment book. It has a good explanation on resource management (the source for which can be seen here)