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

Author Topic: Access problem / Entity Manager  (Read 4046 times)

0 Members and 1 Guest are viewing this topic.

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Access problem / Entity Manager
« on: September 01, 2013, 07:35:32 pm »
I created an entity-basic class and the entities are managed by an entity-manager. I also created an asteroid class, which inherits from the entity class. The manager adds the entities to a list and calls their functions:

class EntityManager
{
public:
        EntityManager(sf::RenderWindow *rw,sf::Event *ev);
        ~EntityManager();

        void Render();
        void Update(float frametime);
        void HandleEvents();

        void AddEntity(Entity* entity);
        void KillEntity(std::string id);
        Entity GetEntity(std::string id);

private:
        std::list<Entity> mEntityList;
        std::list<Entity>::iterator mEntityIt;

        sf::RenderWindow *mRenderWindow;
        sf::Event *mEvent;
};

E.g. the render function:

void EntityManager::Render()
{
        for(mEntityIt = mEntityList.begin(); mEntityIt != mEntityList.end(); mEntityIt++)
        {      
                mEntityIt->Render(mRenderWindow);
        }
}

I declared the functions of the basic class as virtual functions and overwrote them at the asteroid class. The problem is that the manager only accesses the functions of the basic entity class, but not the functions of the asteroid class.

class Entity
{
public:

        Entity(std::string id);
        ~Entity();

        virtual void Render (sf::RenderWindow *rw);
        virtual void Update (float frametime);
        virtual void HandleEvents (sf::Event *ev);

        sf::Sprite*  GetSprite()   {return mSprite;};
        sf::Texture* GetTexture()  {return mTexture;};
        std::string  GetID()       {return mID;};
        bool         GetAlive()    {return mIsAlive;};

        void SetID(std::string id) {mID = id;};

private:

        sf::Texture *mTexture;
        sf::Sprite  *mSprite;  
        std::string mID;
        bool mIsAlive;

};

class Asteroid : public Entity
{
public:

        Asteroid(std::string id);

        void Render (sf::RenderWindow *rw);
        void Update (float frametime);
        void HandleEvents (sf::Event *ev);
       
        void UpdateMovement(float frametime);

private:

        float mSize;
        int mYPosition;
        int mRotation;
        int mSpeed;

};

Can I access the functions of the asteroid class by the entity-manager?
I hope I've explained my problem understandable, please ask if you need further information.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Access problem / Entity Manager
« Reply #1 on: September 01, 2013, 07:51:11 pm »
It sounds like you're just asking how to implement polymorphism (http://www.cplusplus.com/doc/tutorial/polymorphism/), but it looks like you've already done everything you need to make polymorphism happen (declare the functions virtual, call them via a base class pointer, etc), so I don't know what the problem could be.

Could you try posting some complete code?  Also, how do you know that only the base class functions are getting called?

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Access problem / Entity Manager
« Reply #2 on: September 01, 2013, 08:02:39 pm »
Both classes (entity, asteroid) have their own render, update and handleevent function (the entity functions are virtual). The window only renders the entities when I call the draw function of the window in the entity-render-function:

#include "Entity.hpp"

Entity::Entity(std::string id)
{
        mTexture = new sf::Texture;
        mSprite  = new sf::Sprite;
        SetID(id);
}

Entity::~Entity()
{
}

void Entity::Render(sf::RenderWindow *rw) //virtual
{
        rw->draw(*this->GetSprite()); //works fine
}

void Entity::Update(float frametime) //virtual
{
}

void Entity::HandleEvents(sf::Event *ev) //virtual
{
}
 

#include "Asteroid.hpp"

Asteroid::Asteroid(std::string id) : Entity(id)
{
        //asteroid construct stuff
}

void Asteroid::Render(sf::RenderWindow *rw)
{
    rw->draw(*this->GetSprite()); //doesn't work
}

void Asteroid::Update(float frametime)
{      
}

void Asteroid::HandleEvents(sf::Event *ev)
{
}

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Access problem / Entity Manager
« Reply #3 on: September 01, 2013, 08:11:54 pm »
Why *this->GetSprite() instead of just GetSprite()?

Also, "complete" code means complete in the sense that we can compile and test it ourselves.  Without that all we can do is guess.

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Access problem / Entity Manager
« Reply #4 on: September 01, 2013, 08:27:31 pm »
Just GetSprite() creates an error, but this is not the actual problem. The problem is that the entity manager only calls the entity functions but not the asteroid funtions (render, update, handleevents).

I think the cause is that the manager just puts entities in its list and doesn't even know that the asteroid class inherits from it:

void EntityManager::AddEntity(Entity *entity)
{
        bool mHit = false;

        for(mEntityIt = mEntityList.begin(); mEntityIt != mEntityList.end(); mEntityIt++)
        {
                if(mEntityIt->GetID() == entity->GetID())
                {
                        std::cout << "Entity with ID: " << mEntityIt->GetID() << " already exists" << std::endl;
                        mHit = true;
                }
        }

        if(mHit == false)
        {
                mEntityList.push_back(*entity);
        }
}

This just calls the entity but not the asteroid render function:

void EntityManager::Render()
{
        for(mEntityIt = mEntityList.begin(); mEntityIt != mEntityList.end(); mEntityIt++)
        {      
                mEntityIt->Render(mRenderWindow);
        }
}

I thought this would also call the asteroid functions, since they inherit from the entity class.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Access problem / Entity Manager
« Reply #5 on: September 01, 2013, 08:32:41 pm »
Well, yes, what I'm saying is it really looks like that *should* work (the whole point of polymorphism is that a class like EntityManager doesn't need to know about all the derived classes of Entity to call their functions) so there's not a lot else we can do for you until you post complete code and we can test it to find out what's wrong.  Re-posting snippets we've already seen doesn't tell us anything new.

And what's the error you get from using just GetSprite()?  There really shouldn't be a difference there.

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Access problem / Entity Manager
« Reply #6 on: September 01, 2013, 08:49:52 pm »
okay here is the whole project:

https://www.dropbox.com/s/ivi4c1pv2fhqd6s/loloid-attack.zip

You need to know that i created three test-asteroids (ast1,ast2,ast3) at the game class and call their update function to evade the access problem.

Thank you in anticipation!

DarkYoung

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Access problem / Entity Manager
« Reply #7 on: September 01, 2013, 11:49:51 pm »
You should use pointers in list not objects:

std::list<Entity*> mEntityList;

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Access problem / Entity Manager
« Reply #8 on: September 02, 2013, 07:14:28 am »
Quote
You should use pointers in list not objects:

okay i tried that but now I get the errors C2039 and C2839 when I try to call the functions with the iterator:

mEntityIt->Render(mRenderWindow);
  :-\

The compiler says that he needs the type "pointer to class".

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Access problem / Entity Manager
« Reply #9 on: September 02, 2013, 07:44:15 am »
You should go review how pointers and iterators work.

mEntityIt is an iterator (ie a smart pointer) to an element of the list.  The list now contains pointers to entities.  So when you dereference the iterator, you get a pointer to an entity, not an entity.  So of course the call doesn't work the same way.  Modify it so the iterator gets dereferenced twice before the call and it should work.

arkus

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Access problem / Entity Manager
« Reply #10 on: September 02, 2013, 04:24:58 pm »
Quote
Modify it so the iterator gets dereferenced twice before the call and it should work.

I hadn't been aware that an iterator is like a pointer. It works fine now, thank you for helping!  :)