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

Author Topic: textures not rendering once called through visitor (white square problem?)  (Read 1177 times)

0 Members and 1 Guest are viewing this topic.

cryptocrayon

  • Newbie
  • *
  • Posts: 1
    • View Profile
Hello all, I have been working with sfml for about a month now and this is the first major issue I haven't been able to solve through the documentation or other forum posts.

In my project I currently use variants and visitors to tell objects to update and to draw their shapes, but now textures are not rendering for anything using this method. I am not sure where the problem originates so I will include blocks of code.

class Eventmanager{
 public:
        void loadup(){
        Boss boss;
        EnemyShip eship;
       
        boss.setsprite();
        eship.setsprite();

        Event ll;
        Event kk;

        ll.myVari = boss;
        kk.myVari = eship;

        ll.create(500.f,150.f);
        kk.create(200.f,300.f);

        //ll.myAny = boss;

        ll.doevent();
        kk.doevent();  
       
        Eventlist.push_back(ll);
        Eventlist.push_back(kk);
        }
       
        void update(){

        for (std::list<Event>::iterator rt = Eventlist.begin() ; rt !=  Eventlist.end(); ++rt){
         rt->update();
         }

        }

};
 

This is the class that creates and updates other objects using visitors.

class Event{
 public:
 //std::variant<Boss,EnemyShip> myVariant;
   //Boss rat;
   std::variant<Boss, EnemyShip> myVari;

 void create(float c, float d){
  setvars sv;
  sv.a = c;
  sv.b = d;
  std::visit(sv, myVari);
 }

 void doevent(){
  std::visit(Viss{}, myVari);
 }
 
 void update(){
  std::visit(MyVisitor{}, myVari);
 }

};
 
This is the class that functions as a kind of generic shell for other classes so that they can be manipulated
struct MyVisitor
{
   void operator()(Boss& _in){_in.update();}
   void operator()(EnemyShip& _in){_in.update();}
};

struct Viss
{
   void operator()(Boss& _in){_in.x = 500;}
   void operator()(EnemyShip& _in){_in.update();}
};

struct setvars
{
   float a;
   float b;
   void operator()(Boss& _in){_in.setsprite(); _in.x = a; _in.y = b;}
   void operator()(EnemyShip& _in){_in.setsprite(); _in.x = a; _in.y = b;}
};
 
This are the visitors that are used on the variants.
class Boss{
        public:
        sf::Texture texture;
        sf::Sprite sprite;
        float x;
        float y;
        void setsprite(){
        if (!texture.loadFromFile("/home/cryptocrayon/Downloads/C++ Projects/BossHead.png"))
        {
                std::cerr << "Error while loading texture" << std::endl;
        }
        texture.setSmooth(true);
        sprite.setTexture(texture);
        sf::FloatRect spriteSize=sprite.getGlobalBounds();
        sprite.setOrigin(spriteSize.width/2.,spriteSize.height/2.);
        x=500;
        y=150;
        sprite.setPosition(x,y);
        }

        void shoot(int which){
        Bullet B1;
        B1.setsprite();
       

        currentangle+=((6.29/bnum)+0.05)*mode;
        B1.setvars(x,y,currentangle,3.f);
        Bulletlist.push_back(B1);
        }
        void update(){
         sprite.setPosition(x,y);
          if (timer>=3){
          for (int i=0; i<bnum; ++i) {
          shoot(1);      
          }
          timer=0;
          }else{
          timer++;
          }
          window.draw(sprite);
        }
};
 

This is a (cut down) class of a object that would be updated through the event class by a visitor.
So the texture is set in the setsprite() function as is other variables, and the object still retains the changes to the variables through the visitor functions, and it updates normally because the bullet objects still spawn in the normal place, if I add the settexture to the update function the texture actually appears, although without the correct origin. If anyone can figure out what my issue is I would be very grateful. I will include the entire (messy) code if anyone finds that useful.

Edit: Ok it seems this issue is also called the white square problem, however I still have no idea how to proceed with this.
« Last Edit: October 03, 2019, 07:58:18 pm by cryptocrayon »

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
The SFML tutorials on sprites and textures talks about what can cause the "white square problem".

I didn't go through all of your code but there is a decent chance the problem is coming from this (simplified) snippet.
Boss boss;
boss.setsprite();
Event ll;
ll.myVari = boss;
Eventlist.push_back(ll);
 
Your boss object holds on to both the texture and the sprite. It's important to remember that sprites are pretty lightweight objects that contain a pointer to the texture, not the texture data itself. Now think about what will happen when your boss variable gets copied. The member variables will also get copied, which means the new copied sprite will have the same value as the old original sprite, which is a pointer to the old original texture, not the new one.

You may need to find a new strategy for managing your textures. Ideally to where they don't get copied around and their memory addresses don't change.