5
\$\begingroup\$

I am working on a game with an inventory system, but am trying to figure out the best way of doing it. I have read the post about adding WorldItems or InventoryItems to a list, which is fair enough and I figured that out myself anyway.

However, perhaps I add two SwordItems to this list (for example). I want the game to show that I have quantity 2 of these, not two individual items. What is the best way to achieve this with a List based inventory structure. I think I saw a GroupBy method, where I could GroupBy item type Sword. Is this a good way to achieve this? Or can you suggest a better alternative?

\$\endgroup\$
6
\$\begingroup\$

Build your inventory as a list of item stacks, and not items. Individual items (or items that cannot be stacked) are simply a stack of one. For example:

class ItemStack {
  Item item;
  int count;

  // ...public methods here...
}

This allows you to treat your inventory as a simple homogeneous List<ItemStack> or similar, and also allows you the flexibility to support multiple stacks of a particular item -- for example, you can support splitting a stack of items in this system, whereas in one where you tried to GroupBy() might get pretty cumbersome.

It will require a little more work on your part to deal with consumption of items or their removal from the stack, but it's not that big of a deal.

\$\endgroup\$
  • 1
    \$\begingroup\$ And this depends on the nature of the items as well. If, for example, your weapons have a durability value, then the ItemStack doesn't work, as the durability value would be lost, and instead the item with durability has to stand on its own, or have a max stack of 1. \$\endgroup\$ – PlayDeezGames Aug 15 '12 at 18:45
  • 1
    \$\begingroup\$ That's a very good point, if items have per-instance statistics (like durability) that you want preserved when the item stacks then you'll either need a more complex ItemStack implementation than what I showed (maybe with a List<Item>) or make sure you only stack things when items share all their per-instance properties, which can be tricky if you have a lot of external ways (like scripts) that item state can be modified. \$\endgroup\$ – user1430 Aug 15 '12 at 18:54
  • \$\begingroup\$ Good suggestion. I think the list idea within item stack is also good, as it would contain the same item types ie an Item stack with a list of type List<Sword> - as opposed to perhaps having a List<List<Item>> list of item lists which would need to be an item interface or a base class, making it more complex and needing casting to specific objects. \$\endgroup\$ – Davos555 Aug 16 '12 at 11:48
3
\$\begingroup\$

The method you are suggesting isn't optimal, but it will work. However, every access to the inventory, it will try to tally up the counts. If you store your counts directly, no extra counting has to be done. Use something like a System.Collections.Specialized.OrderedDictionary where the keys are your item IDs (for example, all identical items of a specific type would have the same item ID) and the values are the counts.

\$\endgroup\$
1
\$\begingroup\$

Ok after digging around with various ways to do this, I think I have another solution.

Using an arraylist to hold all the items, you can add any item type. To get the count of a certain type of item (class) you can use generics.

For example:

private ArrayList inventory = new ArrayList();

public int getInventoryQuantity<T>()   
{ return inventory.OfType<T>().Count<T>(); }

There you can just pass in the type of object you want to get the count of and it will return the in value.

Of course you can add other methods to return say all of the required items as a collectable if you wanted too, without having to nest lists etc.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.