Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am in the planning phase of a small RPG style game.

The character will have have a set of attributes, like strength, agility, etc which are represented as integers. The character also will have a set of attacks represented as an attack class.

On each attack I want it to do damage based on the characters attributes, eg: the attack "sword slash" will do 10 dmg + the value of the characters strength.

The way I was thinking to do this is to have an abstract attack class, which has an abstract Attack method, and for each attack I create one class that implements the Attack method.

public class SwordSlash:Attack
{
    public void Attack(Character attacker, Character defender)
    {
        defender.DoDamage(10 + attacker.Strength);
    }
}

I see that this will make it a nightmare to maintain.

Does anyone have an idea of how I can accomplish this in a nicer way?

What I think is the main problem is how to input the correct attribute, based on the attack.

share|improve this question
add comment

3 Answers

up vote 27 down vote accepted

You should probably go for a data-driven design here.

Make a generic Attack class which contains the parameters you want to work with - base damage, which stats affects the damage, a set of potential status effects... stuff like that:

public enum AttackStat
{
  Strength,
  Agility,
  Intellect
  // etc.
}

public class Attack
{    
  private int baseDamage;
  private AttackStat stat;
  private double damageMultiplier;
  // ...and so on

  public void Attack(Character attacker, Character defender)
  {
    defender.DoDamage(baseDamage + attacker.GetStatValue(stat) * damageMultiplier);
  }    
}

// Put a method on Character to fetch the appropriate value given an AttackStat:
public int GetStatValue(AttackStat s)
{
  switch(s)
  {
    case AttackStat.Strength:
      return strength;
    case AttackStat.Agility:
      return agility;
    // etc.
  }
}

Then, place your attacks in a file, e.g. an XML file, and load the data from there:

<Attacks>
  <Attack name="Sword Slash" damage="10" stat="Strength" multiplier="1" />
  <!-- More attacks here -->
</Attacks>

You could even extend this to draw values from multiple stats, say, a Fireball where the damage is calculated from both an Intellect and a Fire stat:

<Attack name="Fireball" damage="20">
  <StatModifier stat="Intellect" multiplier="0.4" />
  <StatModifier stat="Fire" multiplier="0.8" />
</Attack>

If you don't want to use the same basic damage formula for everything (e.g. calculate magic damage differently from physical damage), create subclasses of Attack for each formula you need and override Attack, and specify which type you want in your XML file.

share|improve this answer
    
+1, but I would even replace GetStatValue with a lookup table of some sort to avoid maintaining that switch statement. –  user744 Nov 16 '10 at 11:41
    
The problem with this method is that you can only have generic data-driven attacks - you can't have anything that uses special logic. You will end up with a very generic set of items (as you get in warcraft –  Iain Nov 16 '10 at 12:28
1  
@Iain: That is very easily solved by simply adding more data to allow this. E.g., you might have a SpecialAttack subclass which does more things, or calculates damage in an entirely different way. It's just a matter of identifying the behavior you need, and then expressing that as data. –  Michael Madsen Nov 16 '10 at 13:13
2  
@Iain: In addition to just adding more fields, you can also solve that by some of the data fields being expressions or code blocks in e.g. Lua. Good use of orthogonal components also makes more interesting results. –  user744 Nov 16 '10 at 13:44
    
+1 for the general idea of being data-driven. I don't agree with suggesting xml. There are better formats out there - yaml, json or a plain .lua file if you are embedding Lua. –  egarcia Jan 7 '11 at 15:42
show 1 more comment

You want to read Aggregate Objects via Components and Game Object Construction Rabbit Hole, from the Replica Island blog.

share|improve this answer
add comment

I would have a weapon class that has an attack method which you override with the behaviour you want. You can then also handle how the weapon looks in game, in inventory, how much it sells for etc in the same class.

share|improve this answer
5  
-1, not only is this not data-driven, it's deep hierarchy rather than component-driven. It's the worst possible solution. –  user744 Nov 16 '10 at 13:44
3  
Just because this particular method isn't data-driven doesn't make it a bad choice and the hierarchy wouldn't be that deep anyways. It is simple but still powerful (the UnrealEngine is a perfect example of this) if done correctly (ie. no hard-coded values). Sure it has its downsides, but further down the development cycle of a data-driven system I'm sure its downsides are show. I think your basic OOP design is still a valid solution in this and if he wants on the fly editing of default values, it can be implemented on top of a hierarchy system just as easily. –  Dalin Seivewright Nov 17 '10 at 3:10
5  
Not everything has to be data-driven - it depends on the scale of the game. It's probably a bit arrogant to think that my answer is "wrong", but thank you for your honesty. I think this is just a clash of styles between what works for me, making Flash games every day, and your more traditional model of development. I can tell you my approach is much faster to implement and you have better compile-time checking. Your comment re. Lua assumes the asker is working on a platform that would support that. –  Iain Nov 17 '10 at 11:07
2  
Being an RPG game, it's probably pretty impractical to implement every item like that. –  Vaughan Hilts Oct 10 '12 at 6:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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