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

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

0 Members and 3 Guests are viewing this topic.

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #30 on: November 23, 2014, 12:38:15 am »
I wasnt suggesting it as a fix, more because the pointer should never be null, so shouldnt be a pointer but a reference, but since you cant store references in containers, I suggested to use std::reference_wrapper.

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #31 on: November 23, 2014, 04:21:56 am »
Everything works great and as expected,
And since I had an array filled with anim classes anyway there where no reason to use
the block scope and temporary instantiation of the anim class.



const uint32_t MAX_ANIM_ARRAY =20;

class Scene {

 public:
        std::vector<DrawableCLASS*> DrawVec;
        std::array<AnimCLASS, MAX_ANIM_ARRAY> DrawAnimArray;
        void Define(int SN);
        void Setup()  {
               for (auto& item : DrawVec)
                item->Init();
        }
        void Render(sf::RenderWindow &window) {
            for (auto& item : DrawVec)
                item->Render(window);
        }
}

Scene::Define(int sn) {
         uint32_t index=0;
       
   if(sn==Scene_Intro) {

        // - layer 0
        DrawAnimArray[index].Define("Background", 0, true, true, 1,"textures/Art01", 0,0, 1.0f,1.0f,0);
        DrawVec.push_back(&DrawAnimArray[index]);
        index++;

        // - layer 1
        DrawAnimArray[index].Define("Forground", 0, true, true, 1,"textures/Art02", 0,0, 1.0f,1.0f,0);
        DrawVec.push_back(&DrawAnimArray[index]);
        index++;

        // - layer 2
        DrawAnimArray[index].Define("Actor sprite", 0, true, true, 1,"textures/Actor02", 0,0, 1.0f,1.0f,0);
        DrawAnimArray[index].SetClickPoint(true, true, "Dynamic", "ActorName", "ACTOR_YES"  ,0 , "Cursor_Green", 748,380, 48, 72);
        DrawVec.push_back(&DrawAnimArray[index]);
        index++;
   
     if(index> MAX_ANIM_ARRAY) throw std::Kitchen::Sink;
    }
};
 

I played with the refrence wrapper and got it to work by going though an extra function to un-wrap before it could be rendered, so if I really wanted to get rid of  std::vector<DrawableCLASS*> DrawVec; I could use that.
« Last Edit: November 23, 2014, 04:42:15 am by Rasmussen »

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #32 on: November 26, 2014, 10:24:25 pm »
Anyway, I've now gone away from static instantiation of the Anim class to dynamic storing them in a vector.
and then the DrawAbleVector get a reference too that. To get that to work I had to use vector.reserve()
without it after the 2nd. push the vector resized and chanced memory location and the ref was invalid.


reserve() should only be a performance optimization; relying on it for correct behavior like this means you're misusing std::vector.  In this case, you appear to be assuming your std::vector will never exceed a certain fixed size, so you might as well use a std::array (or raw array) to actually enforce a fixed size if that's what you want.  Or use a node-based container like std::list or std::map if you want variable size and stable references.  Or use only one container to store all your drawable objects so this reference validation issue can't even come up.  Or have two containers that are mutually exclusive (one for animations and one for the other drawables) so one doesn't have to find a way to reference the other.  Any of these would probably be an improvement.

Reading in The C++ Programming Language  page 898 STL containers - size and capacity:
Quote
When changing the size or capacity, the elements may be moved to new storage location.
That implies that iterators(and pointers and references) to elements may become invalid(i.e. points to the old element location.
[..]
It is tempting to assume that reserve() improves performance, but the standard growth strategies for vector are
so effective that performance is rarely a good reason to use reserve().
Instead, see reserve() as a way of increasing the predictability of performance and for
avoiding invalidation of iterators.


In C++ for game programmers page 206:
There is directly instructions to use vector.reserve() to avoid relocation and invalidation of pointer and references.

So I'm considering going back to using a vector since reserve() does not change to value reported by
.size() where a std::array[20] report a size of 20 no matter if I actually use 20 or not.
« Last Edit: November 26, 2014, 10:28:05 pm by Rasmussen »

Rasmussen

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: vector with multiple classes | Drawing order
« Reply #33 on: November 28, 2014, 09:25:54 pm »
I've now got std::map to work as a reference holder, by looking at the use of map in the sfml book code
resourceholder, with I allready use in my menu and map classes.

And I've placed the instantiation of Animclass map & Drawable vector
in the scene change loop so they destroy by them self.

As has be suggested.

The structure now look like this.

        file:Define_Intro.cpp
       
        // - layer 0
        { AnimCLASS tmp("Background", 0, true, true, 1,0, "textures/Art01", 0,0, 1,1);
        AnimMap.insert(std::make_pair(id, tmp));
        auto found = AnimMap.find(id);
        DrawVec.push_back(&found->second); id++}


void SceneCLASS::SetUp(AudioCLASS &audio, MouseCLASS &mouse, int SN
       , std::vector<DrawableCLASS*> &DrawVec, std::map<int,AnimCLASS> &AnimMap )
{
        int id = 0;
        if (SN==Intro){ #include "Define_Intro.cpp" }
        //
        //
        for (auto& item : DrawVec) {
                item->Init();
                if(item->GetClickPoint().Enable) {
                // push Dynamic clickpoints
                    CPSceneVec.push_back(item->GetClickPoint() );
                }
        }

};



void GameCLASS::Start()
{       bool exit_loop = false; int SceneNumber = 0;
        do{
            if( SCENE.NextScene == SceneNumber)
            {
                std::map<int,AnimCLASS> AnimMap;
                std::vector <DrawableCLASS*> DrawableVec;
                SCENE.SetUp(Audio,Mouse,SceneNumber,DrawableVec, AnimMap);
                Run(DrawableVec, SceneNumber);
            }
        SceneNumber++;
        if(SceneNumber>=NumberofScenes) SceneNumber=0;
        if(SCENE.NextScene == 99) exit_loop=true;
        }while(!exit_loop);
};

int main()
{
    GameCLASS GAME;
    GAME.SetUp();
    GAME.Start();
    return 0;
}

 

« Last Edit: November 28, 2014, 09:46:50 pm by Rasmussen »