Expanding Inventory

This is a discussion on Expanding Inventory within the Game Programming forums, part of the General Programming Boards category; Ok, I am making an RPG type game, and want to have an inventory that expands when a new character ...

  1. #1
    For Narnia! Sentral's Avatar
    Join Date
    May 2005
    Location
    Narnia
    Posts
    719

    Angry Expanding Inventory

    Ok, I am making an RPG type game, and want to have an inventory that expands when a new character level is reached. For example, at level 1 you start with 5 inventory slots, then when you get to level 2, 6 inventory slots are now available, and so on. I don't think a 1D array will work, or even a 2D array. So now I'm thinking I will need to use vectors or something that can easily change in size. But can you specify how many 'slots' you want in a vector like you can in arrays? I'm getting a little confused on what method to use!

  2. #2
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    I'm pretty sure std::vector<>'s can be given a fixed size or something similar, but I'm no expert on the STL, so I also want to know the answer to that.

    It wouldn't be hard to write a custom container yourself, would it? (Failing all alternatives, of course)
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  3. #3
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    well std::vector is only increased in size IF you use .pushback(); right? I just made a custom class container for my RPG inventory

  4. #4
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    You can set a starting size for a vector and/or increase it's size by an amount later.

    std::vector::reserve(size_type Count);

  5. #5
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Neat!
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  6. #6
    Registered User
    Join Date
    Dec 2005
    Posts
    24
    I realise I may be making an unknown number of incorrect assumptions here, but assuming that the inventory holds objects of type Item and that there is a ceiling to the max inventory size that is known at compile time (eg the max inventory size won't change for reasons other than a change in level, assuming level has a ceiling as well), wouldn't it be simpler to create an array of the maximum inventory size and a variable to hold the current inventory size (CUR_INV_SIZE), then any attempt to access the inventory could be compared with CUR_INV_SIZE to ensure the request is in accepted bounds. The only problem I can see is that removing an object from the somewhere other than the end of the current inventory might require the other array elements to be shifted to fill the gap, although that could probably be done with a little extra coding, or even just mark the element as empty for the next time an item is acquired.

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    C++ people like to overcomplicate things just because they can. I'll agree with ruthgrin here, there's no need to overcomplicate, unless you're just bored.
    Code:
    class inventory {
        ...
        Object inv[ MAX_INV_SIZE ];
        size_t top;
        ...
        bool add( Object *o, size_t limit )
        {
            if( limit < sizeof inv / sizeof( inv[0] ) && top < limit )
            {
                inv[ top++ ] = o; // You did overload your operator right? You love that stuff.
                return true;
            }
            return false;
        }
    };
    Now I'm sure you've got some overly complicated way you can do this, but I don't use C++, so this is what you get.


    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,062
    I don't see the need to create an inventory class, at all. A vector of item objects (or pointers to item objects) is all you need. Just do as Bubba said and check against the capacity in your addItem function
    Code:
    /* Inside your player class */
    std::vector<rpgItem*> inventory;
    
    /* Inside your constructor and presumably your function for gaining a level */
    inventory.reserve(pLevel + 5);
    Code:
    bool PLAYER_BASE::addItem(const rpgItem *newItem) {
           if(inventory.size() < inventory.capacity()) {
              inventory.push_back(newItem);
              return true;
           }
           else return false;
    }
    At that point, everytime you try to add an item if you get true, you just go your merry way, if you get false you notify the user that their is no more space in the inventory.

    STL may be slightly slower than arrays in some cases, but it's almost always simpler. That's the whole point of it.
    Last edited by SlyMaelstrom; 08-23-2006 at 12:50 AM.
    Sent from my iPadŽ

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I suppose it just depends on how OO they want it. If they generalize it enough, they should just make a class of some form, vector or something of your creation, whatever, that handles all "collections of objects".

    In any event, their player should probably have some "get" function, which just checks to see if they have enough room to pick the object up.

    I never took to templates for some reason. Anyway, part of it is I just like to write my own stuff.


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,475
    If you are going to use vectors, remeber to use iterators to move through the constainer

    Code:
    example
    
    std::vector < std::string >::const_iterator myIterator;
    std::vector < std::string >::iterator iter;
    
    // move through sequence:
    
    for ( iter = blah.begin(); iter != blah.end(); ++iter )
    {
        std::cout << *iter << std::endl;
    }

  11. #11
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Actually you don't have to use iterators every time you want to access a vector. Certain functions like erase() require iterators, but it is also perfectly valid to access vector elements by using array subscripts. This also works for maps and lists.

    Array approach
    If you are going to limit your inventory to a set number of items then you could use a simple array. However since your player can effectively remove any item at any place in their inventory you will have to re-sort the array after they are done removing items or you could just show blank spots and allow the user to move items around inside their inventory screen.

    Inventory capacity approach
    Some games allow for a maximum inventory size based on the size of the objects the player is holding. This means that every usable object in the game will have a size and every container that can hold objects has a max size as well as an object size. This would best be approached using a linked list to maintain a simple list of what was in the inventory. Whether you use STL lists or your own is purely up to you.

    King's Quest carry everything regardless of space approach
    This is exactly what is says. The player could carry a house if the house was usable and 'take'able. This approach would be best served by using an STL vector so you could insert and remove objects at will. In my terrain system I'm using well over 12000 trees in a vector and it is fast enough to still maintain over 350 frames per second. STL is not a turtle and the power it gives you is well worth it. Personally, I love STL and use it as much as I can. It's fast, robust, stable, and implements nitty gritty stuff that I don't want to or don't have time to.

    Very simple resource based approach
    Another approach and one I'm fond of is simply storing object ID's in the list. There is no need to actually store an object inside your inventory class. Rather you would grab the inventory item from the master resource list from the resource cache or resource manager. This would mean that you could guarantee that your system would only have 1 instance of the object, 1 place to allocate memory for it, and 1 place to de-allocate or cleanup the object. It requires a few more function calls but nothing too horrible. This method fits very well into a resource cache design for a game where resources are precious and effective management of them is critical. This can also be used to place objects in a room. Each room could have a vector of objects or each object could have a room variable that stated what room it was in. Everything should be assigned an ID and you use those ID's to access the master list.
    The basic idea is that the resource manager is king and no one but no one gains access to resources unless he allows it. And when he does allow it, he never sends the actual resource to the object requesting it. This prevents objects from accidentally or purposely deleting or freeing the resource. The manager allocates and de-allocates and may or may not use a custom memory manager.

    There are about a hundred more approaches to the problem but these should give you some ideas. The most important thing is that whatever you choose it must work well, fast, stable, and with your game engine instead of against it. If you find that you are constantly fighting the system to get it to work, a re-design is needed.

    Code:
    class CResourceMgr 
    {
      std::map<CResource *,DWORD> m_mapResources;
    
      public:
        DWORD Add(CResource *pRes,BOOL &bResult);
        bool Remove(DWORD dwResID);
    
    };
    
    class CResource {};
    class CAIObject:public CResource {};
    class CRoom::public CResource{};
    class CInvetoryItem::public CResource {};
    With this kind of system you can add any class that is derived from CResource to the vector in CResourceMgr. This allows you to have a universal resource manager for many different types of objects. You can also make the CResourceMgr class a template for more functionality (and more headaches) but I rarely see a need for it.

    As a last note remember to always design your objects with the capability of instantiating themselves from disk and also writing themselves back to disk. If you design like this in advance, you will save yourself the headache later of trying to save/load data in the game.
    Last edited by VirtualAce; 08-23-2006 at 05:02 AM.

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I was going to mention the 'objectID' method that you pointed out. The only real downside to that is if you allow your objects to be modified. If you do this, so they're not exact copies of the origional, then you'll have to keep that information some place too.

    You could have an inventory just be a list of pointers to objects. An array would work here, or whatever. If it's NULL, you can use that spot. Or, if your list is less than the number allowed. Either way. If it isn't NULL, then it's pointing to an instance.

    You could store all "modifications" as a list under the origional "template". If it is unmodified, you point right to the template. Otherwise, you point to the modified version. Shrug. Store a counter on the template (original) and increment it any time you allocate one of that object. Decrement when it is destroyed.

    If you don't allow modifications, then just use a list of object ID numbers. Or just pointers to your static item list.

    [edit]
    All you C++ freaks are probably confused by my use of the word "template". I don't mean it in a C++ way, rather as the original version of the object. DIKU muds were my introduction to C (the reason I actually got around to teaching myself the language), and they use the concept of templated objects and object instances. The templated object is the version loaded from disk. Instanced objects had more values, and were based from the templated version.
    [/edit]


    Quzah.
    Last edited by quzah; 08-23-2006 at 05:32 AM.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linked Lists and an Inventory Program
    By marQade in forum C++ Programming
    Replies: 2
    Last Post: 05-12-2008, 09:18 PM
  2. inventory system
    By linucksrox in forum Game Programming
    Replies: 0
    Last Post: 04-19-2006, 01:19 PM
  3. Replies: 26
    Last Post: 06-15-2005, 02:38 PM
  4. Code: An auto expanding array (or how to use gets() safely).
    By anonytmouse in forum Windows Programming
    Replies: 0
    Last Post: 08-10-2004, 12:13 AM
  5. need help with an inventory program
    By lackerson191 in forum C++ Programming
    Replies: 3
    Last Post: 09-10-2001, 09:32 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21