SFML community forums

Help => Graphics => Topic started by: blue_deref on January 04, 2014, 02:00:32 am

Title: Calling draw(...) on instance of class implementing Drawable
Post by: blue_deref on January 04, 2014, 02:00:32 am
I noticed sf::Drawable's draw(...) method is protected. Why is that? (I'm not the best C++ programmer, so pardon me if the answer's rather obvious.)


As a followup question, what is the best way to call this method from outside my implementing class, StateMenu?

Here's my parent interface:
// a state the game can be in (menu, playing, credits).
class State : public EventHandler, public sf::Drawable {
public:
        virtual void update(const sf::Time &delta) = 0;
};

Here's an implementer of that interface:
// the title menu of the game.
class StateMenu : public State {
public:
        bool handleEvent(sf::Event &event);
        void update(const sf::Time &delta);
        void draw(sf::RenderTarget &target, sf::RenderStates states) const;
       
private:
        sf::Time mTimeElapsed;
};

And here's some snippets from main.cpp:
sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), TITLE,
                                                sf::Style::Titlebar | sf::Style::Close);
State *state;

void render() {
        window.clear(sf::Color::Black);
        state->draw(window, sf::RenderStates::Default);
        window.display();
}

int main() {
        ...
        state = new StateMenu;
        ...
        while (window.isOpen()) {
                ...
                render();
        }
        return 0;
}

Sorry if I posted too much code, and thanks in advance for any and all help!
Title: Re: Calling draw(...) on instance of class implementing Drawable
Post by: blue_deref on January 04, 2014, 02:19:09 am
Nevermind, all. Found the problem shortly after. If I declare draw(...) public in State, I can call it from main.
class State : public EventHandler, public sf::Drawable {
public:
        virtual void update(const sf::Time &delta) = 0;
        virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const = 0;
};
I am under the assumption that this is because my State pointer in main.cpp is of type State and not of type StateMenu.

Still curious why the protected access control modifier was chosen, if anyone might indulge me.  :)
Title: Re: Calling draw(...) on instance of class implementing Drawable
Post by: Omega on January 04, 2014, 03:25:48 am
It's protected because it's an internal method. Classes that inherit protected members are guaranteed to have direct internal access to those members, unlike private members which are encapsulated out of reach of inherited classes. You really don't need to access this method outside of the object. sf::RenderTargets (i.e., sf::RenderWindow) are friend classes to sf::Drawable so they can access this internal draw() method. All you have to do is define it, keep it protected, and instead use your window's draw() method with your Status object as a parameter.
Title: Re: Calling draw(...) on instance of class implementing Drawable
Post by: Nexus on January 04, 2014, 10:07:57 am
As stated, don't call draw() directly -- it is invoked by the render targets.

Instead of
object.draw(target, states);
use
target.draw(object); // or
target.draw(object, states);
Title: Re: Calling draw(...) on instance of class implementing Drawable
Post by: blue_deref on January 04, 2014, 10:58:23 am
Ahhh, I was tired today. I forgot that's why one would implement sf::Drawable in the first place.
This bit of code in main:
state->draw(window, sf::RenderStates::Default);
was an artifact of my previous drawing system.

Appreciate the efforts, Omega/Nexus.