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

Author Topic: Needing help with object manager.  (Read 4741 times)

0 Members and 1 Guest are viewing this topic.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Needing help with object manager.
« on: October 28, 2012, 09:45:59 pm »
The first one here is a version of Serapth's Game From Scratch tutorial.


Would be nice to put in std::unique_ptr but unsure how to an where.

GameObjectManager.h
#pragma once
#include "VisibleGameObject.h"
//#include "SFML/Graphics.hpp"


class GameObjectManager
{
public:
        GameObjectManager();
        ~GameObjectManager();

        void Add(std::string name, VisibleGameObject* gameObject);
        void Remove(std::string name);
        unsigned int GetObjectCount();
        VisibleGameObject* Get(std::string name);

        void DrawAll(sf::RenderWindow& renderWindow);
        void UpdateAll();

private:
        std::map<std::string, VisibleGameObject*> _gameObjects;

        struct GameObjectDeallocator
        {
                void operator()(const std::pair<std::string,VisibleGameObject*> & p) const
                {
                        delete p.second;
                }
        };
};
 


GameObjectManager.cpp
#include "stdafx.h"
#include "GameObjectManager.h"
#include "Game.h"
#include <memory>

GameObjectManager::GameObjectManager()
{
}

GameObjectManager::~GameObjectManager()
{
        std::for_each(_gameObjects.begin(),_gameObjects.end(),GameObjectDeallocator());
}

void GameObjectManager::Add(std::string name, VisibleGameObject* gameObject)
{
        _gameObjects.insert(std::pair<std::string,VisibleGameObject*>(name,gameObject));
}

void GameObjectManager::Remove(std::string name)
{
        std::map<std::string, VisibleGameObject*>::iterator results = _gameObjects.find(name);
        if(results != _gameObjects.end() )
        {
                delete results->second;
                //std::unique_ptr<VisibleGameObject*> temp(results->second); //Have no clue how to use this for here???????
                _gameObjects.erase(results);
        }
}

VisibleGameObject* GameObjectManager::Get(std::string name)
{
        std::map<std::string, VisibleGameObject*>::const_iterator results = _gameObjects.find(name);
        if(results == _gameObjects.end() )
        {
                return NULL;
        }
        else
        {
                return results->second;
        }
}

unsigned int GameObjectManager::GetObjectCount()
{
        return _gameObjects.size();
}


void GameObjectManager::DrawAll(sf::RenderWindow& renderWindow)
{

        std::map<std::string,VisibleGameObject*>::iterator itr = _gameObjects.begin();
        while(itr != _gameObjects.end())
        {
                itr->second->Draw(renderWindow);
                itr++;
        }
}

void GameObjectManager::UpdateAll()
{
        std::map<std::string,VisibleGameObject*>::iterator itr = _gameObjects.begin();
        float timeDelta = Game::GetWindow().GetFrameTime();

        while(itr != _gameObjects.end())
        {
                itr->second->Update(timeDelta);
                itr++;
        }
       
}
 

Meanwhile this next one is something I was working on but couldn't get some annoying error to go away in.
Was trying to see if vector was any better but I'm having issues scanning through the list and getting things by anything other than a number.
BaseObjectManager.h
#pragma once
#include <vector>
#include <string>
#include "BlankSprite.h"


class BaseObjectManager
{
public:
        BaseObjectManager();
        ~BaseObjectManager();

        //void AddSprite(BlankSprite &s);
        void AddSprite(BlankSprite *s);
        //void AddSprite(BlankSprite s);

        //void RemoveSprite(BlankSprite &s);
        void RemoveSprite(BlankSprite *s);
        void RemoveSprite(std::string name);
        void RemoveSprite(int element);
        void RemoveDeadSprites();
        void ClearAllSprites();
       
        BlankSprite *getSpriteByPtr(std::string name);
        BlankSprite &getSpriteByRef(std::string name);
        BlankSprite getSpriteCopy(std::string name);

        unsigned int getSpriteListSize();

protected:

private:
        std::vector<BlankSprite*> spriteList;
        //std::vector<std::unique_ptr<BlankSprite*>> spriteList;

};
 

BaseObjectManager.cpp
#include "StdAfx.h"
#include "BaseObjectManager.h"
#include <iostream>

BaseObjectManager::BaseObjectManager()
{
}


BaseObjectManager::~BaseObjectManager()
{

}

/*void BaseObjectManager::AddSprite(BlankSprite &s)
{
        spriteList.push_back(s);
}*/

void BaseObjectManager::AddSprite(BlankSprite *s)
{
        spriteList.push_back(s);
}
/*void BaseObjectManager::AddSprite(BlankSprite s)
{
        spriteList.push_back(s);
}*/


/*void BaseObjectManager::RemoveSprite(BlankSprite &s)
{

}*/

void BaseObjectManager::RemoveSprite(BlankSprite *s)
{
        //meant to remove a sprite by its pointer
}
void BaseObjectManager::RemoveSprite(std::string name)
{
        //meant to remove a sprite by its name
        std::vector<BlankSprite*>::iterator scanList;
        unsigned int i = 0;
        for(scanList = spriteList.begin(); scanList != spriteList.end(); scanList++)
        {
                //BlankSprite hold = spriteList.at( std::distance(spriteList.begin(),scanList));
                if(i < (spriteList.size() -1))
                {
                        if(spriteList.at(i)->getName().compare(name) == 0)
                        {
                                spriteList.erase(spriteList.begin() + i);
                        }
                        else
                        {
                                std::cout << "No sprite with this name exists!" << std::endl;
                        }
                }
                i++;
        }
       
}
void BaseObjectManager::RemoveSprite(int element)
{
        spriteList.erase(spriteList.begin() + element);
}
void BaseObjectManager::ClearAllSprites()
{
        spriteList.clear();
}
void BaseObjectManager::RemoveDeadSprites()
{
        std::vector<BlankSprite*>::iterator scanList;
        unsigned int i = 0;
        for(scanList = spriteList.begin(); scanList != spriteList.end(); scanList++)
        {
                //BlankSprite hold = spriteList.at( std::distance(spriteList.begin(),scanList));
                if(i < (spriteList.size() -1))
                {
                        if(spriteList.at(i)->getDead() == true)
                        {
                                spriteList.erase(spriteList.begin() + i);
                                //spriteList.pop_back(spriteList.at(i));
                        }
                        else
                        {
                                //std::cout << "No sprite with this name exists!" << std::endl;
                                continue;
                        }
                }
                i++;
        }
}

BlankSprite *BaseObjectManager::getSpriteByPtr(std::string name)
{
       
        std::vector<BlankSprite*>::iterator scanList;
        unsigned int i = 0;
        for(scanList = spriteList.begin(); scanList != spriteList.end(); scanList++ )
        {
                //BlankSprite hold = spriteList.at( std::distance(spriteList.begin(),scanList));
                if(i < (spriteList.size() -1) )
                {
                        if(spriteList.at(i)->getName().compare(name) == 0)
                        {
                                return spriteList.at(i);
                        }
                        else
                        {
                                //std::cout << "No sprite with this name exists!" << std::endl;
                                //return nullptr;
                                continue;
                        }
                }
                i++;


        }
}
/*
BlankSprite &BaseObjectManager::getSpriteByRef(std::string name)
{

}
BlankSprite BaseObjectManager::getSpriteCopy(std::string name)
{

}*/

unsigned int BaseObjectManager::getSpriteListSize()
{
        return spriteList.size();
}
 

I keep getting some annoying excpetion error anytime I try to use the methods meant for targeting a specific sprite/object. 

Any ideas?  I know I'm missing something but can't pin down what.
I have many ideas but need the help of others to find way to make use of them.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Needing help with object manager.
« Reply #1 on: October 28, 2012, 11:04:47 pm »
You know that's quite a bit of code, not sure if many will take their time to go through it step by step to understand it... ;)

Also you should be more clear on the error you get, "Some annoying exception error" just doesn't cut it.
Describe the error in detail, look at the call stack and debug it.

std::unique_ptr can only be used if the object is really unique, if it should be possible to have multiple copies of an object, then you might want to take a look at std::shared_ptr, but be warned, if you use the shared_ptr wrong it can have a noticeable impact on the performance... ;)

As for the usage of std::unique_ptr, simple use it instead of a raw pointer but whenever it changes the ownership you use std::move() instead of a simple assignment.
I used them in my SmallGameEngine, maybe you want to take a look at it to understand it better (although I'm not sure if it's the simplest example...).
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #2 on: October 28, 2012, 11:44:45 pm »
lol forgot to post the error. and yes it is rather annoying since normally I'm good at debugging things without much help.

This is from the second set of files.  My search codes seem to have some unknown issue and I'm stumped.
First-chance exception at 0x002ee7f8 in ObjectManagementTests.exe: 0xC0000005: Access violation reading location 0x0000000c.
Unhandled exception at 0x002ee7f8 in ObjectManagementTests.exe: 0xC0000005: Access violation reading location 0x0000000c.
 

No clue why it's giving me this error since as far as I know I've caught everything.  Only seems to happen when I search for a sprite name that isn't on the list. and for some reason I can't pin down what's causing it.
I know where it is but don't understand why it is. ???

I have many ideas but need the help of others to find way to make use of them.

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Needing help with object manager.
« Reply #3 on: October 29, 2012, 12:11:29 am »
I don't know if this is what's causing your problem or not, but the implementation of BaseObjectManger::RemoveDeadSprites is not correct.  You're looping on an iterator that becomes invalid after the first erase call.  And I don't know, in several functions, why you're mixing iterators and indexes.   Use whichever is one is most suited to the purpose, but I would avoid mixing them in the same loop. 

Here's a straightforward (untested)  implementation:

void BaseObjectManager::RemoveDeadSprites()
{
    typedef std::vector<BlankSprite*> vec_t ;

    vec_t::iterator current = spriteList.begin() ;

    while ( current != spriteList.end() )
    {
        if ( current->getDead() )
            current = spriteList.erase(current) ;
        else
            ++current ;
    }
}

It could be optimized if the order of elements in the vector isn't important.

[Edit:  Same issue in BaseObjectManager::RemoveSprite(std::string) since you don't exit the loop when you've found the one you want to remove.]
« Last Edit: October 29, 2012, 12:19:10 am by cire »

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #4 on: October 29, 2012, 12:19:27 am »
I don't know if this is what's causing your problem or not, but the implementation of BaseObjectManger::RemoveDeadSprites is not correct.  You're looping on an iterator that becomes invalid after the first erase call.  And I don't know, in several functions, why you're mixing iterators and indexes.   Use whichever is one is most suited to the purpose, but I would avoid mixing them in the same loop. 

Here's a straightforward (untested)  implementation:

void BaseObjectManager::RemoveDeadSprites()
{
    typedef std::vector<BlankSprite*> vec_t ;

    vec_t::iterator current = spriteList.begin() ;

    while ( current != spriteList.end() )
    {
        if ( current->getDead() )
            current = spriteList.erase(current) ;
        else
            ++current ;
    }
}

It could be optimized if the order of elements in the vector isn't important.

No the order isn't important and thanks for the advice of not mixing them that way.  I've been in other programming languages so my C++ is a bit rusty.  Also in this case the if doesn't need an else since I'm going to have to up the count anyways since I'm in a loop.  From the looks of it I've done the same wrong thing 3 times in a row and didn't even notice. lol guess that's what I get for not keeping up on my C++. :)

Now to see if I can fix the problem in all 3 and keep it fixed.
I have many ideas but need the help of others to find way to make use of them.

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Needing help with object manager.
« Reply #5 on: October 29, 2012, 12:22:47 am »
Quote
Also in this case the if doesn't need an else since I'm going to have to up the count anyways since I'm in a loop.

Actually, in this case you do need an else and to not increment the iterator.  Maybe you should look up what erase does and what it returns.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #6 on: October 29, 2012, 01:18:30 am »
lol completely forgot it shifts them.  Meatime the iterator doesn't have anything to point to the sprites without getting creative with it.


void BaseObjectManager::RemoveDeadSprites()
{
       
        std::vector<BlankSprite*>::iterator current = spriteList.begin() ;

    while ( current != spriteList.end() )
    {
        if ( (*current)->getDead() ) // this contraption due to C++ pointer/reference system makes me remember why I switched to java but it works.
            current = spriteList.erase(current) ;
        else
            current++;
    }


}
 
and yes the code works although this is visual studio we're talking about here so you can never tell. :) Code::Blocks testing solves this mystery.
Starting to find all my good sources again just looking for topics on this.  Still missing a few though.

I have many ideas but need the help of others to find way to make use of them.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #7 on: October 29, 2012, 02:28:02 am »
seems the same trick don't work twice.



BlankSprite *BaseObjectManager::getSpriteByPtr(std::string name)
{
        //BlankSprite *sptr = new BlankSprite();

        std::vector<BlankSprite*>::iterator current = spriteList.begin() ;
       
    while ( current != spriteList.end() )
    {
        if ( (*current)->getName().compare(name) == 0 )
                {
           
                        //return (*current);
                        //return sptr;
                }
        else
                {
            current++;
                        std::cout << "No sprite with this name exists!" << std::endl;
                }
    }


        //delete *current;
}
 

This error pops up the second the method exits.  What I'm trying to do is get a pointer to the sprite in the main vector list and be able to use it like in the first object manager.
First-chance exception at 0x003093ca in ObjectManagementTests.exe: 0xC0000005: Access violation reading location 0x0000000c.
Unhandled exception at 0x003093ca in ObjectManagementTests.exe: 0xC0000005: Access violation reading location 0x0000000c.
The program '[104832] ObjectManagementTests.exe: Native' has exited with code -1073741819 (0xc0000005).
 

Here's an example of the first manager's get method in the first post.
PlayerPaddle* player1 = dynamic_cast<PlayerPaddle*>(Game::GetGameObjectManager().Get("Paddle1"));
 

Been trying to get the one I'm working on to do the same thing but for some odd reason it isn't liking me.
I have many ideas but need the help of others to find way to make use of them.

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Needing help with object manager.
« Reply #8 on: October 29, 2012, 02:38:09 am »
The whole purpose of using a std::vector is the use of brackets for easy work arounds, why use an iterator for it? Also, I once experienced weird errors when using an iterator with a std::vector, it was quite a while ago so I don't really remember, but I think the errors were similar.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #9 on: October 29, 2012, 02:59:53 am »
The whole purpose of using a std::vector is the use of brackets for easy work arounds, why use an iterator for it? Also, I once experienced weird errors when using an iterator with a std::vector, it was quite a while ago so I don't really remember, but I think the errors were similar.

Guess I'll ditch the iterator from the get method and see what explodes.
Seeing as I'm as stumped as I can be right now and I think I just ran into a reason for making my own way of searching lists and arrays of any kind and being able to use what comes out of them.

Seems in one case as long as I don't try to use the object for anything the iterator work fine but when I do....(BOOM!).. IDE goes haywire.
So with the iterator I can get their information but can't do anything with them. or so it seems at least. ???
« Last Edit: October 29, 2012, 03:08:56 am by StormWingDelta »
I have many ideas but need the help of others to find way to make use of them.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #10 on: October 29, 2012, 03:16:11 am »
Even with just this I'm still getting that error.

        for(int i = 0; i != spriteList.size(); i++)
        {
                if(spriteList.at(i)->getName().compare(name) == 0)
                {
                        return spriteList.at(i);
                }
                else
                {
                        return NULL;
                }
        }
 

Now I'm just plain annoyed.  No clue on my end what I'm doing that I shouldn't be. :(
I have many ideas but need the help of others to find way to make use of them.

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Needing help with object manager.
« Reply #11 on: October 29, 2012, 04:42:57 am »
Is there a possibility spriteList is empty when you enter this method?

If it is, you don't return anything.

In the version with the iterator, you had all of the returns commented out.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Needing help with object manager.
« Reply #12 on: October 29, 2012, 03:09:35 pm »
Yes I know the returns were commented out and yes I got an error for doing that and knew I would.  Meatime while messing with the thing I noticed that the only time I get the error is with the combination of searching for the name of the sprite and trying to return a pointer to it.


This right here for example works just fine.

void BaseObjectManager::testScaner()
{
        std::vector<BlankSprite*>::iterator current = spriteList.begin();
       
    while ( current != spriteList.end() )
    {
                (*current)->incPosition(10);
        if ( (*current)->getName().compare("HelpMe!") == 0 )
                {
            std::cout << "Sprite name exists!" << std::endl;
                }
        else
                {
                        std::cout << "Sprite Name: " << (*current)->getName() << " isn't " << "HelpMe!" << std::endl;
                }
                std::cout << "Name: " << (*current)->getName() << std::endl;
                std::cout << "Position: " << "X = " << (*current)->getPosX() << " , " << "Y = " << (*current)->getPosY() << std::endl;
                std::cout << "Size: " << (*current)->getSize() << std::endl;
                std::cout << "Live: " << (*current)->getDead() << std::endl;
                current++;
    }
}
 
Only seems to happen when I both search for a sprite that isn't on the list and try to return a pointer to it.  This is it shouldn't be trying to return anything if nothing is there to return to.

Guessing I have to somehow make sure that it can't return a pointer to a non-existent sprite.  Might add an else if with a continue in it so it will just move onto the next sprite on the list. Than the normal return null if nothing is there.
I have many ideas but need the help of others to find way to make use of them.