I pretty heavily data drive my games, I used to use Cas' resource system but now I've got
Rebirth which is an evolution of the same core ideas. It's kind of like a mix between a DI framework and an XML->Object loading system, with an emphasis on nice, minimal xml.
Here's a peek inside some of
Albion's xml to define a Dark Imp monster:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| <!-- Tag mappings --> <map name="BasicBrain" class="albion.brains.BasicBrainTemplate" /> <map name="CharacterClass" class="albion.character.CharacterClass" /> <!-- ... --> <decoder class="albion.character.Attributes" /> <!-- Items implement and Item interface --> <HealthVial name="healthVial.item" itemName="Health vial" image="HealthVial.image" hpGain="100" mpGain="0" /> <HealthVial name="manaVial.item" itemName="Mana vial" image="ManaVial.image" hpGain="0" mpGain="100" /> <GoldCoins name="goldCoins.item" image="SmallCoins.image" count="10" /> <BasicWeapon name="startingSword.item" itemName="Basic sword" image="ShortPlainSword.image" type="Bladed" attackPower="4" modifiers="bell2[-2, -2]" />
<!-- Character classes --> <CharacterClass name="warrior.class" className="Warrior" icon0="MeleeAttackCursor.image" icon1="DefendCursor.image" defaultAttributes="STR7 DEX6 CON5 INTEL3 WILL4 CHA5" equipableWeaponType="Bladed" hasMagic="false" magicScaleFactor="0.0" detectionSkillMultiplier="1.0" defaultInventory="startingSword.item, healthVial.item" defaultMaleNames="Bowie, Scythe, Vyse, Drachma, Ramirez, Higins, Minsc, Kurth, Bartok " defaultFemaleNames="Mazzy, Nalia, Josella, Petra, Rosalind, Miyako, Tifa, Scarlet" > <description> Warriors are skilled melee fighters trained to fight at the front of battle. They are comfortable with any non-ranged weapon and may even fight bare handed. As strong physical atheletes, a good warrior will have high strength and dexterity to deal damage and a high constitution in order to withstand it. Warriors may later specialise further and become skilled swordsmen, or become inspirational leaders, or focus on raw physical combat. </description> </CharacterClass> <!-- BasicBrain implements Brain interface --> <BasicBrain name="imp.brain" willFlee="true" hpFleeThreshold="0.25" />
<!-- Dark imp is a regular imp tinted towards dark blue/green --> <AvatarSheet name="darkImp.sheet" sheet="Enemies/Imp.png" face="" tint="rgb(50, 140, 200)" />
<!-- Spawn template for a dark imp --> <CharacterTemplate name="darkImp.character" characterName="Dark Imp" characterClass="warrior.class" attributes="STR1 DEX1 CON8 INTEL1 WILL1 CHA1" <!-- Custom decoder translates this into an Attributes object --> sheet="darkImp.sheet" brain="imp.brain"> <dropTable> <DropTable> <oneOf> <drop item="basicWeapon.drop" probability="1" /> <drop item="manaVial.item" probability="1" /> <drop item="goldCoins.item" probability="1" /> <drop item="" probability="2" /> </oneOf> </DropTable> </dropTable> </CharacterTemplate> |
There's very little code on the java side since almost all of that xml is automatically parsed via reflection. The important bits are:
1. Actual objects of the correct sub-type (like BasicBrain, or HealthVial) are created, but in game they're just handled via a Brain or Item interface. That's the DI side of things, and means that I can easily configure a SmartImp by swapping in a new brain without changing any of the code. I assume you're doing something similar to this with Spring.
2. All the top-level objects are named so they can be referenced in other objects. Ie. "warrior.class" is shared between most melee monsters and can be chosen by the player as a character class too.
3. Decoders mean it's dead easy to insert custom syntax into attribute and have them spit out objects (like the strength/dexterity/etc. attributes).
4. Not shown, but you can derive one definition from another. That means I can have superToughDarkImp.character derive from darkImp.character and only redefine it to have higher strength. Everything else gets automatically inherited.
5. The whole thing reloads and reparses automatically, so you can tweek the text/attributes/probabilities and see them reflected instantly in game without a restart. That's really, really handy when you're tweeking tiles and images.
It's really powerful when you get your head around it, as I can define whole new items/characters/behaviours/etc. with just new data, or insert new subtypes just by adding the class and references it in the xml. The core of the game stays entirely unaware of all of the subtypes and only has to deal with a few core interfaces.
Hope that's useful.
