![]()
For the past two months or so, I’ve been hard at work on a game that I hope to unleash upon the world next month. Truth be told, I’m a bit nervous since I’ve been getting more and more ambitious as I develop. That’s something they tell you never to do. Choose a scope and stick with it, they say. It’s great advice, but I have so far failed to follow it.
I’ve also recently become involved with GaDeMo, which is kinda like NaNoWriMo for games. Right now it’s just a few of us from the Chicago Experimental Game Meetup, but I’m guessing it’ll grow. Anyway, working on two games at once naturally makes you think a bit differently. You build things a bit more generically because you want to cram it into two different projects simultaneously. At least I do.
All the GaDeMo stuff will eventually be open-sourced, but I figured I’d get a head start on it here and on the GaDeMo blog. I’ve published this over there already, but why not put it here too? Surely someone here will find this useful as well.
This is a stats system for RPG-like tracking of character or item characteristics. It’s half a dozen simple classes, but it’s built to be expanded in the future. Here’s an example use. Say I’ve got a party of characters. Programmatically speaking, each one is probably an instance of some kind of Character class, and each one will have a variety of stats. One solution would be to extend the Character class in various directions and just add your stats as properties of those descendant classes. Of course, then you have a lot of classes that do nearly the same thing, and you have nothing reusable for future games.
A better solution would be to have some sort of object that each Character could instantiate, which would then hold all that Character’s stats. You could do this with a generic Object if you wanted; however, then all manipulation of stats would have to be done either in the Character or in some external class that has access to the Character’s stats. Then you’ve got logic spread all over the place, which is again not a good solution.
But what if this stats object could take care of stat management too? For example:
var stats:Stats = new Stats(); stats.addStat( new Stat( StandardStats.HP, 0, 100 ) );
This creates a stats object, and then adds a stat called HP with a lower limit of 0 and an upper limit of 100. Now, anytime you want to see how many hit points this character has, you can call:
stats.getStat( StandardStats.HP );
Okay, that’s pretty simple stuff. It’s one step up from a generic object. But in your typical RPG, you’ll notice that pretty much everything affects your stats. Most of the items in your inventory probably affect them one way or another, battle affects them, spells affect them, the list goes on. Say, for example, our Character has armor that adds 10% to his HP, and a sword that adds +2 HP.
stats.getStat( StandardStats.HP ).addAffector( new AdditionAffector( "Sword of Justice +2 HP", 2 ) ); stats.getStat( StandardStats.HP ).addAffector( new MultiplierAffector( "Armor of Punctuality +10%", 0.1 ) );
Now there are two ways to check your stat.
stats.getStat( StandardStats.HP ).baseValue // before Affectors stats.getStat( StandardStats.HP ).totalValue // after Affectors
This gives you the freedom to specify how items affect stats. Perhaps a certain curse ignores all Affectors. Maybe an item does something randomly using a base stat instead of a total stat. Whatever. It’s up to the the developer.
Now obviously this is a ridiculously simple implementation. I imagine it will grow quite a bit as I develop these two games, and probably future games as well. The next steps, I think, would involve integrating an Inventory system and maybe a Skills system of some sort. The end dream would be to just add an item or skill or whatever you want and the stats just kinda take care of themselves. A system like this, really fleshed out, could save a game developer a lot of time.
Looks promising - can’t wait to see how character classes get folded in.
That’s a good start. I like it.
Another idea is to add groups–I’m thinking in terms of damage here. Like, if you have a sword that does +20% fire damage and gauntlets that add +3 fire damage, then when you attack something, you’d do stats.getGroupTotal( FIRE ) to get the total from everything in the group. Or if you attack a water creature, you could ignore the FIRE group.
@majman: Yeah, I’m still thinking about how that’s going to work.
@benjamin: That’s a good idea- another thing to think about. That concept could easily be adapted to other types of games as well.
Hi
nice post and it is a very interesting topic for Game Developer!! Thx for sharing your thoughts
Other thing what benjamin have already mentioned, would be very simple to use and nice. How do you implemented the Affector Functionality. Because I am working also on a concept for a Game Engine and I solved some of this issues with the decorator pattern. It encapsulate in a very good way some special responisibilities of your code. Maybe you have already used this pattern, then forget my last words otherwise maybe it could help you…
You can take a look at the source if you want. My solution is a simplified Command pattern. Each Affector is really just an encapsulated method in its own class. They are queued when added to a stat (and may be given priority in that queue), and then executed in sequence on the stat’s value before its final value is returned.
I figured this would be a good way to open the system up to expansion in the future. To add a custom Affector, you just have to extend the StatAffector class and implement the affect() method.
Love the idea! Been meaning to do something similar for a long time. Really looking forward to see this system when its done!