RPG Items management

Started by
9 comments, last by Firnael 11 years, 7 months ago
Hi,

I'm wondering how should items should be handled in a rpg-type game, knowing that the player could find a lot of different items in his quest.
Should I create a class for each item of the game, with abstract classes to separate each different types of items, or should I simply store everything in an XML-like file and import items from it.

After this I would like to implement an inventory class, with item slots, stackable items, drag and drops. Because of this, I need the items to have at least an unique identifier which I could retrieve easily.

What do you think ?

Thks
Advertisement
The XML loading approach is definitely the better one out of the two that you've suggested. Making different types of items through inheritance is a clunky use of OOP and just a code maintenance nightmare waiting to happen. It's better to have one Item class and apply the qualities that distinguish it from other items as member variables concerning its properties (the item ID, how many attack points it gives to your player, etc). You would create instances of the Item class with the data loaded from the XML file.

New game in progress: Project SeedWorld

My development blog: Electronic Meteor

You want to be data-driven, rather than creating concrete sub-classes for every item. Maintaining that many classes is headache enough, but inevitably you'll fall into the "solution" of creating deep class hierarchies to re-use code, and this is an abuse of object oriented design.

What you probably want is a very tight, shallow group of classes that represent different objects by constructing them with different attributes or scripts. For example, most any kind of consumable item that has an effect can be represented by one class that calls into a different script. A loaf of bread that restores 10HP? A Tincture that refills mana? A cure-all that removes any negative status effect? Check, check, and check again -- 3 instances of the same class calling into a different "script".

Here, a script could mean a "proper" scripting language like Lua or Python, but it could also mean function pointer, functor object, an "Action" class, or lambda (anonymous function), depending on the language you're using.

If you do use a full scripting language, be aware that any scripts that are user-accessible and stored in plain text can be modified to give an enterprising user a means to cheat, say by making the cheap health potion fully restore health, so you should take countermeasures for the final release if you care.

throw table_exception("(? ???)? ? ???");

What I've done for my game, that has worked perfectly so far, is have all of the items instances of s single item class. When you create the instance you pass a string which is what type of item it is (this would be your unique identifier, ex. weapon, potion, armor, shield, boots, helmet, etc), the name of the item (to load the appropriate image file), what 'level' it is, and it's position on the map. Keeping all the items in one class keeps my code my more clean than having a lot of different item classes.

I also have a stats generating function that generates random stats for each item depending on what level it is and what type of item it is, that way I don't have to hard code the stats for each one. You could also hard code the stats for which ever more specific items you wanted (ex. there is only one 'electric dagger' in the game with a damage of 30 and a required strength of 40, or whatever). You could implement something like that as well to ease the issue of hard coding each stat for each item.

You could easily play around with different stat generators, rare item generators, etc. It's actually pretty fun. I just finished the whole weapon/item and inventory system for my game. Customizing the organization of the items in your inventory by dragging them around each slot, equipping weapons/armor, using hp potions, dropping items, etc all becomes 100x more fun when you programmed it all by yourself. Good luck man! Message/Email me if you have any more specific questions. This is all still pretty fresh in my head, I've spent the last few days going at this.
Thanks guys, you're like a fountain of knowledge or whatever whould say someone how knows english better than me :P

I think the solution that best suits what I'm looking for is having just a few class representing items categories (Ravyne idea mostly), such as Consumable, Weapon, Armor, implementing a blank interface named Item. With this, I can have and Inventory class which is a container of "Item".

I'm not familiar with the script concept, I better understand the XML way (or JSON, or other, don't know what's best). My goal would be to use in the code only the item ID to manipulate items. For exemple, if I do something like inventory.addItem(48), it parses the file, look for the item with ID 48, retrieve its attributs and create an instance thanks to the good class.

Is it interesting to have just a generic Item class, or a few more specific ?
Should I use scripting language (I don't know anything about it, could be useful) or XML (or xml-like) ?

I'm doing it in Java btw.

Thks a lot
It depends on how you design your Inventory>Slot>Item system, but I think that it's generally easier to just have one class for every item in the game. I only have 1 item class in my RPG, I differentiate each item with 1 variable class member and that variable is used to add a specific item to something (for example inventory.additem(48)). I then have another variable class member that determines the type of the item (Armor, potion etc.) which directly determines how the item operates when it's used.
I don't know if it's an optimal way to handle it, but my Inventory>Slot>Item system is designed so that the inventory holds slots and the slots holds the items, this design works for my game at least.
Ok so if I got this right, you must have something like a huge switch are something similar which contains your logic for your item class ?
For example, you create a new instance of the Item class with the id 48, you parse your data file to collect informations related to this item, including his type. You see that ID 48 is the number for Health Potion. Inside your Item class logic, you're able to tell that "if I call the useItem() method with this instance, I'll drink the item because the type is Potion" ?

For now I have an Inventory class which possess an arraylist of InventorySlot. This class has an arraylist of Item, and keeps the item ID and the stack limit of the item.
You can have an inventory, inside it you have slots. Inside each slots you can have at least one item, and multiple items if they are stackable, with a stack limit to prevent stacking to infinity and beyond.
Let's say that you have 2 integer variable class members, one is called 'ItemID' and the other one is called 'ItemCategory'. ItemID is the identity and has a unique number to any other item type, this is the variable that you use if you want to spawn an item. ItemCategory is the keeps track of what operations the item can perform, if ItemCategory stands for armor you will equip the item, If ItemCategory stands for potion you will consume the item etc.
So, you spawn an item using ItemID, this will tell your program that it should add an item with the attributes of item type X. You must have set instructions for what the game should do depending on what item category it is, if the item is a piece of armor: Do this, if the item is a potion: Do that. You basically just have 1 if statement for each item category and then you write the behaviors of each individual category, for example if the category is 'Potion': add this amount of health to the player and then remove the potion from the inventory.

I have the Inventory>Slot>Item system set up in the way that the inventory's job is to hold the slots and keep track of when it should be shown on the screen, the item's job is to carry every bit of information about an item. The slots are the ones who are doing the actual work, they can delete items, add items, swap items between different slots, keep track of how to stack items and so on. It works really well.

I'm not sure if that's a good explanation of it, so let me know if I forgot something :)
Magical Pot has one way of doing it. It's a workable solution but not terribly elegant because you'll end up with a big switch statement somewhere that will be a huge pain to maintain.

I'm not super familiar with Java, I'm not a fan for a number of reasons, but based on my limited knowledge I would implement the specialization through a combination of class members on the item class, and a functor object to implement the logic of the item. (AFAIK, Java lacks anonymous functions / lambdas, which would have been preferable). When you construct an instance of the Item class, you assign it values and a function object (functor) that gives it its behavior. In this way, you can have a variety of items without introducing unnecessary inheritance, and without having to maintain half a dozen different, brittle switch statements.

This is actually a good example of why I'm no fan of Java -- simple things are needlessly wordy. Any language with anonymous functions make this incredibly trivial to implement, and looks as elegant as it is. In java, even functionally elegant solutions sometimes look ugly.

There are probably other good design patterns that could be applied, and perhaps ones that are more suited to Java's style. As I am no expert on Java, take everything here with a grain of salt.

throw table_exception("(? ???)? ? ???");

In C#, adding in the functions can be simply done by the way of delegates. The Item class will have at least one delegate with which to act upon the player character, with a parameter for the character or character data to perform a certain behavior with. You define these behaviors with functions using the character data. Instead of choosing what to do based on a switch statement, you pass to it the appropriate function to be used by the delegate

New game in progress: Project SeedWorld

My development blog: Electronic Meteor

This topic is closed to new replies.

Advertisement