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

Author Topic: vector with multiple classes | Drawing order  (Read 16282 times)

0 Members and 2 Guests are viewing this topic.

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
vector with multiple classes | Drawing order
« on: November 12, 2014, 06:05:59 pm »
Hi.

I know hardware level bits and bytes but the software part is lagging a bit.
I'm moving my little project from C/SDL to C++/SFML so I'm learning C++11 and SFML
at the same time and I'm stuck on this problem where I want a vector with multiple types,
to control the drawing order of the classes in the scene from the scene def section.

How can I create the classes so they fit inside a vector ?

I tried all last evening to fiddle with abstract base class and virtual function
but got stuck on compiler error (Function deleted) and lost the drive.

How can I do this?

class ANIMATION
{
        public:
                 void Init();
                 void Render(sf::RenderWindow *Window);
                 void FreeUp();

                void SetEnable(bool enable)         { Enable = enable;              };
                bool GetEnable()                    { return Enable;                };
                void SetVisible(bool visible)       { Visible = visible;            };
                 bool GetVisible()                   { return Visible;               };
                //-- member functions unique for animation class
                  void SetAnimationSpeed(int speed)   { AnimationSpeed = speed;             };

        private:
                std::vector <sf::Sprite> SpriteVec;
                std::vector <sf::Texture> TexVec;

}



class RAIN
{
         public:
                void Init();
                 void Render(sf::RenderWindow *Window);
                 void FreeUp();

                //-- member functions as above
                //-- member functions unique for Rain class
        private:
                 sf::Sprite  RainDropSprit1;
                sf::Sprite  RainDropSprit2;
                 sf::Sprite  RainDropSprit3;
                 sf::Texture RainDropTex1;
                sf::Texture RainDropTex2;
                  sf::Texture RainDropTex3;

}


class FOG
{
        public:
                  void Init();
                void Render(sf::RenderWindow *Window);
                  void FreeUp();

                 //-- member functions as above
                //-- member functions unique for Fog class
        private:
                 sf::Sprite  FogSprit1;
                sf::Texture FogTex1;
}


ANIMATION Anim;
RAIN      Rain;
FOG       Fog;

std::vector< ?  > Scene;

// Scene 1 Def
Scene.push_back(Anim);
Scene[0].SetEnable(true);
Scene[0].SetVisible(true);
Scene[0].SetAnimationSpeed(0.5);
Scene[0].Init();
Scene.push_back(Rain);
Scene[1].Init();
Scene.push_back(Fog);
Scene[2].Init();

// Scene 2 Def
Scene.push_back(Fog);
Scene[0].Init();
Scene.push_back(Anim);
Scene[1].Init();
...
...
sf::RenderWindow Window;
// main loop
loop{ !++;
 Scene [!] .Render(&Window);
}
 

« Last Edit: November 12, 2014, 07:00:15 pm by Laurent »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: vector with multiple classes | Drawing order
« Reply #1 on: November 12, 2014, 08:26:45 pm »
Obligatory: You're supposed to learn C++ before trying to use libraries like SFML that are written in C++.  It will save you a lot of future pain to read a proper C++ book cover to cover before trying anything non-trivial with SFML.

First off, you do not need Init() and FreeUp() methods.  In C++, every struct/class comes with a "constructor" and a "destructor" that are automatically called when objects are created and destroyed.  This is one of the best things about the language and it is absolutely mandatory that you understand them.

Anyway, without knowing the exact failing code and compiler error you were faced with, but it looks like you were trying to implement runtime polymorphism, so I can at least try to give you a hint with this:
class Drawable {
public:
   virtual void Render(sf::RenderWindow*) = 0;
}

class ANIMATION: public Drawable {
public:
   void Render(sf::RenderWindow*);
   // other methods
private:
   // data and private methods
}

// other Drawables

std::vector<Drawable*> Scene;

int main() {
   // ...
   ANIMATION a;
   Scene.push_back(&a);
   // ...
}
 
Of course you still need to read a proper C++ book that will tell you about polymorphism in great detail.

For instance, even that snippet makes the very strong assumption that all your drawables are created in main() and thus survive as long as you use the Scene vector.  You will have to learn how ownership works in C++ and figure out whether this is good enough or if you need smart pointers or something else.

It may also be the case that an inheritance hierarchy of classes using polymorphism is not the best design, but that's also something you'll have to figure out for yourself.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: vector with multiple classes | Drawing order
« Reply #2 on: November 12, 2014, 10:56:33 pm »
Simple answer: a std::vector can only contain elements of a single type.
Maybe what you want is a vector of pointers to base class objects, maybe you really want multiple vectors holding different types - hard to tell.
What's easy to tell is that you need to learn more C++.
« Last Edit: November 12, 2014, 11:01:32 pm by Jesper Juhl »

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #3 on: November 13, 2014, 06:46:10 pm »
Ok my post did not come out right I see.

"First off, you do not need Init() and FreeUp() methods."
Yes I do, I have a full page of code in those functions, the instance of the class lives for the
game duration and gets cleared at scene change. 

"In C++, every struct/class comes with a "constructor" and a "destructor"
I know.
The provided code was just sudo code to illustrate what I was trying to do.

"Obligatory: You're supposed to learn C++ before trying to use libraries like SFML that are written in C++."
I know but SFML is the driving force, SFML is the reason its worth for non pro-programmers to learn C++
It's a balance act between reading boring text and getting something on the screen for newcomers,
and attracting those seams to be an important subject in the all the videos from the speakers at GoingNative 2012,
CppCon 2014 and from Bjarne Stroustrup I've been watching lately while eating dinner.
btw. thanks to those videos I'm been removing all new and delete and naked pointers in my project.

"it looks like you were trying to implement runtime polymorphism, so I can at least try to give you a hint with this:"
Yes Thanks ! "runtime polymorphism" Something I will look up in my C++ books
btw I have Bjarne Stroustrup: The C++ Programming Language C++11 Edition
Charles River C++ for Game Programmers
SFML Game Development.
But need time to read them, I'm 35% into sfml game development, 5% into Game programmers and 0,001 % into The c++ programming language, it's more fun to program :-)

I tried last night to get your example to work but not without adding functions to Drawable class to mirror those in the animation and Rain class, -a super class.
So its clear that I need to read up on that subject before going down that road in my 'C with classes' project.

And from what your guys are saying I guess that looking into boost:Any/variant is not necessary,
just learn C++ and I can do what I wanted?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: vector with multiple classes | Drawing order
« Reply #4 on: November 13, 2014, 07:01:43 pm »
"First off, you do not need Init() and FreeUp() methods."
Yes I do, I have a full page of code in those functions, the instance of the class lives for the
game duration and gets cleared at scene change.
No you don't ;)

The reason why you currently need those methods is because you have a questionable design, not an inherent constraint in game logic. Why not tie the lifetime of your C++ objects to the lifetime of the actual game objects they're representing? What's the point of reusing instances? Hint: performance is not, because the major work is done in constructor/destructor or init/free methods. Which one of them you choose does not have a great influence on speed. Init/free methods may even lead to a slowdown, because all the variables are initialized to some unneeded default value just to be overwritten in the init function.

Apart from that, such methods are bad design, because you have no class invariants and cannot guarantee correct initialization and destruction. Instead, you rely on manual mechanisms (the user calling those functions) -- and this is exactly the same reason why new/delete should be avoided.

I know but SFML is the driving force, SFML is the reason its worth for non pro-programmers to learn C++
It's a balance act between reading boring text and getting something on the screen for newcomers
If you want to get quick results, then there are definitely more effective ways than learning C++. You've picked the most complex mainstream programming language, with pitfalls and unintuitive rules all over the place. It can be worth paying this price if you really exploit the freedom and the variety of paradigms C++ gives you, but it requires several years. That's not exaggerated, because learning the language is only one part; knowing modern idioms and how to apply and combine different techniques is at least as important, if not more. And this does not only require modern literature, but also experience in multiple projects.

I don't want to discourage you, but you must be aware that learning C++ is a long journey, not something you do by the way to get some games done.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #5 on: November 13, 2014, 10:19:23 pm »
Quote
" Why not tie the lifetime of your C++ objects to the lifetime of the actual game objects they're representing? What's the point of reusing instances?"

Good question, I'd had no reason to do that at this time, and the clear function is only stuff like string.clear() and vector.clear(). my scene switching loading time is focused on texture loading sprite creation stuff, witch seams
more important by a factor companied to string.clear 

But its true that what you are suggesting seams a more object oriented style.
 
Quote
If you want to get quick results, then there are definitely more effective ways than learning C++. You've picked the most complex mainstream programming language, with pitfalls and unintuitive rules all over the place. It can be worth paying this price if you really exploit the freedom and the variety of paradigms C++ gives you, but it requires several years. That's not exaggerated, because learning the language is only one part; knowing modern idioms and how to apply and combine different techniques is at least as important, if not more. And this does not only require modern literature, but also experience in multiple projects.

I don't want to discourage you, but you must be aware that learning C++ is a long journey, not something you do by the way to get some games done.

Properly all true but as I heard Bjarne Stroustrup say, don get lost in all the advanced features take what you will, when it subject is C > C++

So right now I'm in the C with classes and a few vectors, map, template, std::thread, place floating, looking for a container that can handle multiple types, so I can avoid inheritance/polymorphism witch I have no need for right now and find boring.   :-)

But off course if I have 20 classes and all of them have Set/GetEnable() and Set/GetVisible()
then having one class that take care of that would be really nice.
« Last Edit: November 13, 2014, 10:27:28 pm by Rasmussen »

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #6 on: November 14, 2014, 12:58:45 am »
I just got this working, and it is testing out great.

I see chapter one in C++ for Game programmers is
Inheritance - polymorph - virtual function ...
and says is very important to learn and for the rest of the book ,
I promise I will look into that soon.  ;D

Quote

class Drawable {
public:
   virtual void Render(sf::RenderWindow*) = 0;
    virtual ~Drawable(){};
};

class AnimCLASS : public Drawable {};
class CloudCLASS: public Drawable {};

int main()
{
    bool exit=false;
    sf::RenderWindow WINDOW(sf::VideoMode(800, 600), "SFML window");

    AnimCLASS Anim;
    Anim.SetEnable(true);
    Anim.SetVisible(true);
    Anim.SetImageFileName("textures/Art01");
    Anim.Init();

    CloudCLASS Clouds;
    Clouds.SetEnable(true);
    Clouds.SetVisible(true);
    Clouds.NumberOfClouds           = 120;
    Clouds.Xmin            = -8000;
    Clouds.Xmax            = 10000;
    Clouds.Ymin            = -6000;
    Clouds.Ymax            = 100;
    Clouds.Zval            = 1000;
    Clouds.Xpos            = 0;
    Clouds.Ypos            = -200;
    Clouds.Speed                 = 8;
    Clouds.Size            = 110;
    Clouds.SetColor(255,255,255,255);
    Clouds.Init();

    Drawable * DrawAnim;
    Drawable * DrawCloud;

    DrawAnim =  &Anim;
    DrawCloud = &Clouds;

    Drawable* SCN[2] = { DrawAnim, DrawCloud };

    do{
    SCN[0]->Render(&WINDOW);
    SCN[1]->Render(&WINDOW);
    WINDOW.display();
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { Clouds.Speed = 20;}
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { exit=true; }
    sf::sleep(sf::milliseconds(10));
    } while(!exit);
    return 0;
}

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #7 on: November 14, 2014, 01:52:47 am »
And made into using a vector, so now I have exactly what I was looking for.

Quote
int main()
{
    bool exit=false;
    sf::Event event;
    sf::RenderWindow WINDOW(sf::VideoMode(800, 600), "SFML window");

    std::vector<Drawable*> Scene;

    CloudCLASS Clouds;
    Drawable * DrawCloud;
    DrawCloud = &Clouds;
    Clouds.SetEnable(true);
    Clouds.SetVisible(true);
    Clouds.NumberOfClouds   = 120;
   Clouds.Xmin            = -8000;
   Clouds.Xmax            = 10000;
   Clouds.Ymin            = -6000;
   Clouds.Ymax            = 100;
   Clouds.Zval            = 1000;
   Clouds.Xpos            = 0;
   Clouds.Ypos            = -200;
   Clouds.Speed         = 8;
   Clouds.Size            = 110;
   Clouds.SetColor(255,255,255,255);
    Clouds.Init();
    Scene.push_back(DrawCloud);

    AnimCLASS Anim;
    Drawable * DrawAnim;
    DrawAnim =  &Anim;
    Anim.SetEnable(true);
    Anim.SetVisible(true);
    Anim.SetImageFileName("textures/menu");
    Anim.Init();
    Scene.push_back(DrawAnim);

    do{
        WINDOW.pollEvent(event);
        for(uint32_t i=0; i<Scene.size(); i++)
            Scene[!]->Render(&WINDOW);
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { Clouds.Speed = 20;}
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { exit=true; }
        WINDOW.display();
        sf::sleep(sf::milliseconds(10));
    } while(!exit);

    return 0;
}


Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #8 on: November 14, 2014, 06:23:30 pm »
CloudCLASS Clouds;
Drawable * DrawCloud;
DrawCloud = &Clouds;
Scene.push_back(DrawCloud);
You don't need to create a pointer in this case. Just do this:

CloudCLASS Clouds;
Scene.push_back(&Clouds);

do{
// ...
} while(!exit);
`do while` is considered bad style. You should consider using normal `while` instead.

WINDOW.pollEvent(event);
Why are you polling for events when you don't handle any events?

for(uint32_t i=0; i<Scene.size(); i++)
            Scene[!]->Render(&WINDOW);
You have put an exclamation mark instead of i in the subscript operator.

And in any case you should use range based for-loop when iterating all the elements of a container, like this:
for (auto& item : container) {
    // do something with item
}
« Last Edit: November 14, 2014, 06:28:32 pm by Mörkö »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: vector with multiple classes | Drawing order
« Reply #9 on: November 14, 2014, 06:34:01 pm »
`do while` is considered bad style.
Who says that and why? There are not many applications for do while, but in some cases it's the simplest approach, and rewriting to while would just complicate code unnecessarily.

Otherwise I agree. Rasmussen, you should also choose a naming convention and apply it consistently. I would especially avoid CAPS_LOCK style except for macros and maybe constants. And you should definitely read again the SFML tutorials about event handling. Don't mix realtime input with events.

And please use C++ code tags, not quotes.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #10 on: November 14, 2014, 08:14:28 pm »
CloudCLASS Clouds;
Drawable * DrawCloud;
DrawCloud = &Clouds;
Scene.push_back(DrawCloud);
You don't need to create a pointer in this case. Just do this:

CloudCLASS Clouds;
Scene.push_back(&Clouds);

Roger!, thanks.

Quote
do{
// ...
} while(!exit);
`do while` is considered bad style. You should consider using normal `while` instead.

Can't see why at the moment, but I keep it in mind.

Quote
WINDOW.pollEvent(event);
Why are you polling for events when you don't handle any events?

The window froze and got greyed out like style and the default windows 7 mouse cursor
chanced to rotating busy, without it in the testbench code, even while using sf::sleep.

Quote
for(uint32_t i=0; i<Scene.size(); i++)
            Scene[!]->Render(&WINDOW);
You have put an exclamation mark instead of i in the subscript operator.
And in any case you should use range based for-loop when iterating all the elements of a container, like this:
for (auto& item : container) {
    // do something with item
}

That was on purpose , "[ i ]" seam to vanish, I thought it was a forum BB code or something.

Thanks for the suggestions.

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #11 on: November 14, 2014, 08:44:18 pm »
Otherwise I agree. Rasmussen, you should also choose a naming convention and apply it consistently. I would especially avoid CAPS_LOCK style except for macros and maybe constants. And you should definitely read again the SFML tutorials about event handling. Don't mix realtime input with events.

And please use C++ code tags, not quotes.

I'm in the creative phase, I'll beautified the code on days when I'm not on fire so to speak.

"Don't mix" this:
 
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { exit=true; }
with this:
 
WINDOW.pollEvent(event);

?

In the real main loop the mouse uses the event.

Roger on the tags.

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #12 on: November 14, 2014, 08:49:23 pm »
do{
// ...
} while(!exit);
`do while` is considered bad style. You should consider using normal `while` instead.

do while is guaranteed to run at least once, even if the condition is always false. A standard while loop will not run at all if the condition is false.

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #13 on: November 14, 2014, 09:12:29 pm »
Mission accomplished, darn nice to go from this static drawing order and mess

void Render(sf::RenderWindow *window)
{            
            Layer_1_Anim.Render(window);
            WX.Rings.Render(window);
            Layer_2_Anim.Render(window);
            Layer_3_Anim.Render(window);
            WX.Fog.Render(window);
            Layer_4_Anim.Render(window);
            Particle.Render(window);
            Particle2.Render(window);
            WX.Render(window);
            WX.Cloud.Render(window);
            WX.RAIN.Render(window);
            FireAnim.Render(window);
            Text.Render(window);
            Layer_5_Anim.Render(window);
            Layer_6_Anim.Render(window);
            Layer_7_Anim.Render(window);
            Layer_8_Anim.Render(window);
 };
 

To this dynamic beauty..

void Render(sf::RenderWindow *window)
 {
        for (auto& item : DrawVec) {
                item->Render(window);
        }
}    
 

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #14 on: November 14, 2014, 09:36:14 pm »
Who says that and why? There are not many applications for do while, but in some cases it's the simplest approach, and rewriting to while would just complicate code unnecessarily.
Can you demonstrate one or more examples where do while is unequivocally the correct construct?

On a related note, there exists a lot of cases where goto would be "the simplest approach", but I'm not sure you would recommend its usage to people, especially beginners.

Even if you are able to make an argument for why there exists some scenarios where do while is logically the right choice, I will argue that people should stick to normal while anyway because of consistency and simplicity. while is more readable and and easier to reason about.
« Last Edit: November 14, 2014, 09:43:12 pm by Mörkö »