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

Author Topic: Overriding sf::Drawable::draw  (Read 15158 times)

0 Members and 1 Guest are viewing this topic.

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Overriding sf::Drawable::draw
« on: October 16, 2015, 04:43:42 pm »
Hi all,

here's my problem: I want to push some objects, that have textures and sprites into a vector from STL. I met some issues and I found on this forum that I have to override draw method. The problem is I just want to keep rest of my code untouched as long as it's possible, the best thing for me is to write same or similar code to original draw method.

Here is what I have:

*.h file:
class Wyswietlacz : public Drawable, public Transformable
{
public:
        void draw(sf::RenderTarget& target, sf::RenderStates states) const;
};
 

*.cpp file:
void Wyswietlacz::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        //here is what I need you to help me with
}
 

some example classes to show you how I want to use it:
class example1 : public Wyswietlacz
{
private:
        Texture texture1;
        Sprite sprite1;
        // other stuff
};

class example2 : public Wyswietlacz
{
private:
        Texture texture2;
        Sprite sprite2;
        // other stuff
};

int main()
{
        vector<example1> EX1;
        vector<example2> EX2;

        // creating and pushing some objects into vectors
        // setting Sprites in right places and all other things needed
        // creating window

        window.draw(EX1[0].sprite1);
        window.draw(EX2[3].sprite2);
        window.draw(EX1[7].sprite1);
        window.draw(EX2[2].sprite2);
        window.draw(EX2[7].sprite2);
        return 0;
}
 

So I need help in what exactly should I write in those method's definition. I want it to work as originally. And, if it is possible, I'd love to see original draw definition (NOT declaration).

Sorry for my english and maybe stupid question :)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Overriding sf::Drawable::draw
« Reply #1 on: October 16, 2015, 04:50:20 pm »
The documentation is pretty verbose on that topic.

Let us know if you have trouble understanding it. :)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #2 on: October 16, 2015, 05:52:05 pm »
Thank you for fast reply.

Well, yes, I have troubles. I was trying to make something using those documentation, I also googled my answer for 3 days all my free time, so I read many ideas and so. The problem is I tried some of them and no one worked.
And the example you've linked. It looks for me as it is a class like my 'example1' and 'example2' classes, because that class from documentation has it's own Sprite to display. I want it to display Sprites from classes that inherit it.

Again, I'm sorry for my english.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Overriding sf::Drawable::draw
« Reply #3 on: October 16, 2015, 06:14:31 pm »
You shouldn't inherit from a sprite, but your code isn't doing that anyways.
Since you put the sprite into the derived class, you need to override the draw function in the derived class.

Personally I'd suggest to add the sprite to the base class and implement the drawing there.
It's a bad idea to make the Entity hold the texture and the sprite, because whenever the entity is moved in memory the texture would need to be reset for the sprite, plus copying a texture costs quite a bit.
Additionally it's advised to stick to English names, that way you learn a bit more English and other people can easily read your code.

So here's an example that will

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

class Entity : public sf::Drawable, public sf::Transformable
{
public:
    Entity(sf::Texture& tex);
    void draw(sf::RenderTarget& target, sf::RenderStates states) const;

private:
    sf::Sprite m_sprite;
};

Entity::Entity(sf::Texture& tex)
: m_sprite(tex)
{

}

void Entity::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    states.transform *= getTransform();
    target.draw(sprite, states);
}

class example1 : public Base
{
public:
    example1(sf::Texture& tex)
    : Base(tex)
    {

    }
};

class example2 : public Base
{

public:
    example2(sf::Texture& tex)
    : Base(tex)
    {

    }
};

int main()
{
    std::vector<example1> EX1;
    std::vector<example2> EX2;

    sf::Texture tex;

    // creating and pushing some objects into vectors
    // pass the texture at object creation
    // setting Sprites in right places and all other things needed
    // creating window

    window.draw(EX1[0]);
    window.draw(EX2[3]);
    window.draw(EX1[7]);
    window.draw(EX2[2]);
    window.draw(EX2[7]);
}
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #4 on: October 16, 2015, 06:33:56 pm »
Oh, now that's clear to me :) Thank you!

EDIT:

You shouldn't inherit from a sprite, but your code isn't doing that anyways. (...)

I mean inherit from class Wyswietlacz, not from Sprite. Sorry for missleading sentence.

(...) Additionally it's advised to stick to English names, that way you learn a bit more English and other people can easily read your code. (...)

I'm writing it with people who don't know english so it's the only right way working on that project. I usualy don't use english names anyway.
« Last Edit: October 16, 2015, 06:44:35 pm by Skorpion »

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #5 on: October 22, 2015, 12:49:31 am »
Well, I had much to do so I didn't check your code earlier and I'm doing it now. I have this:
//Base.h:
class Base
{
public:
        Texture texture;
        Sprite sprite;
        void draw(sf::RenderTarget& target, sf::RenderStates states) const;
};

//Base.cpp:
void Base::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        states.transform *= getTransform();     // As in your code
        target.draw(sprite, states);
}

//Example1:
class Example1 : public Base   // Basicly I get texture and sprite from 'Base' class, so I can manipulate them
{
        texture.loadFromFile(//file directory);
        sprite.setTexture(texture);
}

//main:
int main()
{
        vector<Example1> EX1;
        Example1 exapmle = new Example;
        EX1.push_back(example);
        window.draw(EX1[0].sprite);     //worked when I stored my classes in table doesn't, when changed to
                                                        //vector
        window.draw(EX1[0]);    //doesn't work either
        return 0;
}
 

All I see is white shape of what that picture was. Maybe the problem is that the file is *.jpg?

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #6 on: October 22, 2015, 04:41:49 am »
Your vector of Example1 should be a vector of (unique) pointers to example one. Your vector stores copies but you are trying to push_back a pointer. NEVER use naked new unless you are experienced and you know what you are doing and you clean it up. From your code it looks like you dont know what you are doing with it AND you never clean it up so enjoy memory leaks.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Overriding sf::Drawable::draw
« Reply #7 on: October 22, 2015, 09:02:36 pm »
class Example1 doesn't seem to have any public members or methods nor constructor. It doesn't look like a class at all really; it looks more like a function.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #8 on: October 22, 2015, 11:59:56 pm »
Your vector of Example1 should be a vector of (unique) pointers to example one. Your vector stores copies but you are trying to push_back a pointer. NEVER use naked new unless you are experienced and you know what you are doing and you clean it up. From your code it looks like you dont know what you are doing with it AND you never clean it up so enjoy memory leaks.

Well, I'm sorry, I simplified my code in last post, so it had not so much to do with the original one. I also used 'new' while in my code I create whole objects, not only pointers. The 'main' function looks in fact more like this:

class My_Class
{
private:
        vector<Example1> EX1;
public:
        void my_fun1()
        {
                for(int i=0; i<10; i++)
                {
                        Example1 example;
                        example.do_things();    // method that
                        EX1.push_back(example);
                }
        }

        void my_fun2()
        {
                my_fun1();     
               
                //much stuff
       
                window.draw(EX1[0].sprite);     // <- this worked when I stored my classes in table stopped, when      
                                                                // changed to vector
                window.draw(EX1[0]);    // <-this doesn't work either
        }
};
 

Whole code:
(click to show/hide)

class Example1 doesn't seem to have any public members or methods nor constructor. It doesn't look like a class at all really; it looks more like a function.

Are you really intrested in class members that are not involved in this case? All my algorithms of moving things on the screen, getting events etc.? It's about 300 lines of code, when you can see those few that are manipulating on sprites up here and in my previous post.

Sorry for my english, I hope it's not so incomprehensible :)

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Overriding sf::Drawable::draw
« Reply #9 on: October 23, 2015, 12:20:51 am »
class Example1 doesn't seem to have any public members or methods nor constructor. It doesn't look like a class at all really; it looks more like a function.
Are you really intrested in class members that are not involved in this case? All my algorithms of moving things on the screen, getting events etc.?
No, but I am interested in how the Example1 class in constructed and how its copy constructor is implemented.
I'm not sure why you included code in that class that is not within a method of any sort.

This is a classic example of why a minimal and complete example is suggested. It often ends with requiring one in the end anyway,
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #10 on: October 23, 2015, 01:17:58 am »
I think I don't understand you a bit. Sorry, I'm not so good in english. But I think I understand that you want to see the whole code, don't you? The other thing is, you suggest that I must have an initial list and an constructor that pushes the texture it gets into the texture the class own. Is it really needed? I do it like this:
class Base : public Drawable, public Transformable
{
public:
        Texture texture;
        Sprite sprite;
        void draw(sf::RenderTarget& target, sf::RenderStates states) const;
};

class Example1 : public Base   // Basicly I get texture and sprite from 'Base' class, so I can manipulate them
{
    texture.loadFromFile(//file directory);
    sprite.setTexture(texture);
}
 

This is exactly how I load and texture and connect it to sprite. Is THIS the problem I have? If I changed it, would it start displaying things properly?

Sorry 4 my english

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Overriding sf::Drawable::draw
« Reply #11 on: October 23, 2015, 02:28:34 am »
I think my question is, when does the following code (inside the Example1 class) get executed?
    texture.loadFromFile(//file directory);
    sprite.setTexture(texture);
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #12 on: October 23, 2015, 02:42:19 pm »
Oh, now I see I made another mistake. It schould be in method 'do_things()', where those two lines and many others are executed, but only those two are related to texture and sprite. I'm really sorry, now I understand what were you talking about. But I think it doesn't change much as in my code it is in a method and still doesn't work :(

EDIT:

I was searching solution whole afternoon, I've changed something and then I found some code that wroks and, in my opinion, is completly IDENTICAL to mine (I mean to those which I wrote today) but mine still displays only white shapes of sprites. Look at this:


My code:
Base.h
class Base : public Drawable, Transformable
{
public:
   void set_up();
   Texture texture;
   Sprite sprite;
private:
   void draw(RenderTarget &target, RenderStates states) const;
};
 
Base.cpp
void Base::set_up()
{
   texture.loadFromFile(/*file directory*/);
   sprite.setTexture(texture);
}

void Base::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        states.transform *= getTransform();
        states.texture = NULL;
        target.draw(sprite, states);
}
 
Example.h
class Example
{
private:
        vector<Base> base_objects;
        void show(RenderWindow & win);
public:
        void do_things();
};
 
Example.cpp
void Example::do_things()
{
        for (int i = 0; i < 10; i++)
        {
                Base m;
                base_objects.push_back(m);
        }
}

void Example::show(RenderWindow & win)
{
        win.clear();
        win.draw(base_objects[0]);
        win.display();
}
 

Code identical to mine:
Base.h https://github.com/sheadovas/Kurs_SFML/blob/master/Lekcja%207/Bullet.h
Base.cpp https://github.com/sheadovas/Kurs_SFML/blob/master/Lekcja%207/Bullet.cpp
Example.h https://github.com/sheadovas/Kurs_SFML/blob/master/Lekcja%207/Engine.h
Example.cpp https://github.com/sheadovas/Kurs_SFML/blob/master/Lekcja%207/Engine.cpp

Can you tell me, where is the difference between those two, because I'm pretty sure I did my best to display those sprites properly. As I already said I see only white shapes of my sprites :(

Sorry for long post, much code and bad english!
« Last Edit: October 23, 2015, 08:12:40 pm by Skorpion »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Overriding sf::Drawable::draw
« Reply #13 on: October 23, 2015, 09:07:12 pm »
Quote
Can you tell me, where is the difference between those two
You're copying the Base instances multiple times, but the Base class doesn't handle copy properly. The other code doesn't copy anything, as far as I can tell.
Laurent Gomila - SFML developer

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: Overriding sf::Drawable::draw
« Reply #14 on: October 23, 2015, 11:20:30 pm »
Can you tell me what exactly should I do (how to write it properly)? I don't understand why is my Base class not handling with all those objects created and pushed into vector correctly. I'm not very skilled programer.

EDIT:

Ok, I've studied virtual methods and found all I knew about them wasn't true so I've learned how to handle them properly, how to override them and make them doing what I want them to do, but I met another problem and maybe it is unable to do it in a way I want to do it, but if it is possible to do, please help me with following:

That's my code now:
Board.h
class Board : public Drawable, Transformable
{
public:
        bool set_up(int nrOfBoard, int level);  // that method sets all sprites and loads
                                                                        // from files coordinates of everything
private:
        Texture texture;        // texture of board
        Sprite background;      // sprite of board
        struct adds            
        {
                Vector2f coordinates;          
                Sprite add;                    
        };
        struct things
        {
                Vector2f coordinates;
                Sprite thing;
        };
        struct oneBoard
        {
                vector<adds> add_s;            
                vector<things> thing_s;
        };
        vector<oneBoard> map_of_all_boards;    

        virtual void draw(RenderTarget &target, RenderStates states) const;
};
 
Board.cpp
void Board::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        states.transform *= getTransform();
        states.texture = NULL;
        target.draw(background);
        for (int i = 0; i < map_of_all_boards[0].add_s.size(); i++)
                target.draw(map_of_all_boards[0].add_s[i].add, states);
        for (int i = 0; i < map_of_all_boards[0].thing_s.size(); i++)
                target.draw(map_of_all_boards[0].thing_s[i].thing, states);
}
 

As you can see I display 'map_of_all_boards[0]', the very first thing in my vector. I would like to change it and display those one which I want by changing:
virtual void draw(RenderTarget &target, RenderStates states) const;
 
in something like this:
virtual void draw(RenderTarget &target, RenderStates states, int board_number) const;
 
but I keep getting error:
error C2664: 'void sf::RenderTarget::draw(const sf::Vertex *,unsigned int,sf::PrimitiveType,const sf::RenderStates &)' : cannot convert argument 1 from 'int' to 'const sf::Drawable &'
Reason: cannot convert from 'int' to 'const sf::Drawable'
while I try to use it as following:
window.draw(Boards, 0);     // Boards is an object of class Board
 
I understand why I get it. I only ask you now to advise me how can I display one element of my vector, how can I pass the information of which element method should pick to my overrided draw?

Any help welcome! Please, I need it fast!

Sorry for my english!
« Last Edit: October 24, 2015, 03:27:37 pm by Skorpion »

 

anything