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

Author Topic: Sprites appear white (Yes, I do know what that means)  (Read 1585 times)

0 Members and 1 Guest are viewing this topic.

PhoenixFFX

  • Newbie
  • *
  • Posts: 4
    • View Profile
Sprites appear white (Yes, I do know what that means)
« on: July 03, 2011, 01:00:36 am »
Okay, so I'm currently making a game with paperdoll (So you see the armor and hats of the other players, depending of what they have equipped), so I thought of having all the armors with their id on different files (So the armor id0 would be 0.png, etc...) and have created a class to handle those, but weirdly, only the last armor in the vector shows, the other shows as white squares.

(The code that loads the different armor into an "Image" vector)
Code: [Select]
for (int i=0; i<m_numBody; i++)
{
    Image img;
    m_body.push_back(img);
    m_body[i].Init("body", i);
}


(The code that calls the drawing function of the "Image" class, 'body' being the armor id)
Code: [Select]
m_body[body].Draw(App, pixelX, pixelY, direction, anim);

And then there is the Image class :

(image.h)
Code: [Select]
#ifndef IMAGE_H_INCLUDED
#define IMAGE_H_INCLUDED

#include <SFML/Graphics.hpp>
#include <string>

class Image
{
    public:
void Init(std::string type, int number);
void Draw(sf::RenderWindow &App, int pixelX, int pixelY, int direction, int anim);

    private:
sf::Image m_image;
sf::Sprite m_sprite;
};

#endif // IMAGE_H_INCLUDED


(image.cpp)
Code: [Select]
#include <string>
#include <sstream>
#include <iostream>
#include "image.h"

using namespace std;

void Image::Init(string type, int number)
{
// Load the sprite
ostringstream t_stream;
    t_stream << "data/sprites/" << type << "/" << number << ".png";
    string t_string = t_stream.str();

m_image.LoadFromFile(t_string.c_str());
m_image.SetSmooth(false);
m_image.CreateMaskFromColor(sf::Color(255, 0, 255));
m_sprite.SetImage(m_image);
}

void Image::Draw(sf::RenderWindow &App, int pixelX, int pixelY, int direction, int anim)
{
// Draw the sprite
m_sprite.SetSubRect(sf::IntRect(32*direction-32, 48*anim, 32*direction, 48*anim+48));
m_sprite.SetPosition(pixelX, pixelY);

App.Draw(m_sprite);
}


Like I said, only the last armor (I tested with different numbers) shows. So if there is 4 armors, only m_body[3].Draw(...) would work, the others, like m_body[1].Draw(...) would show a white square)

Thank you.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Sprites appear white (Yes, I do know what that means)
« Reply #1 on: July 03, 2011, 01:12:31 am »
Your Image class doesn't have correct copy semantics. When you copy an instance, the sf::Sprite keeps the pointer to the old sf::Image. This leads to problems because std::vector may copy its elements.

The solution is to separate sf::Sprite and sf::Image, as they are designed to be. Keep all images in a central place and let the sprites reference them. This has the additional advantage that there are no slow sf::Image copies necessary.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

PhoenixFFX

  • Newbie
  • *
  • Posts: 4
    • View Profile
Sprites appear white (Yes, I do know what that means)
« Reply #2 on: July 03, 2011, 01:28:10 am »
Yes but, the way I coded it, the images/sprites don't copy themselves, do they ? I mean, I place the Image class in a vector, THEN I tell it, from the vector, to load the image and set the sprite. The way I see it, nothing is copied, but it's maybe just me.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Sprites appear white (Yes, I do know what that means)
« Reply #3 on: July 03, 2011, 10:38:25 am »
As mentioned, std::vector may copy its elements when it is resized. Anyway, as soon as you write a class, it must either support copy semantics to prevent surprises like this one, or it should be noncopyable. Try to derive your class from sf::NonCopyable, you won't be able to store it in STL containers anymore. At least not with C++98.

Generally, you can implement copy constructor, assignment operator and destructor, but the need for this is often a hint that a class is not high-level enough. Ideally, only low-level classes such as smart-pointers, containers etc. should require manual overloads of the Big Three. That is why I think the better solution is to keep sf::Image separate from sf::Sprite, especially because these classes are designed to be separated.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything