views:

99

answers:

3

I'm developing a game. I want to have game entities each have their own Damage() function. When called, they will calculate how much damage they want to do:

public class CombatantGameModel : GameObjectModel
{
    public int Health { get; set; }

    /// <summary>
    /// If the attack hits, how much damage does it do?
    /// </summary>
    /// <param name="randomSample">A random value from [0 .. 1]. Use to introduce randomness in the attack's damage.</param>
    /// <returns>The amount of damage the attack does</returns>
    public delegate int Damage(float randomSample);

    public CombatantGameModel(GameObjectController controller) : base(controller) {}
}

public class CombatantGameObject : GameObjectController
{
    private new readonly CombatantGameModel model;
    public new virtual CombatantGameModel Model
    {
        get { return model; }
    }

    public CombatantGameObject()
    {
        model = new CombatantGameModel(this);
    }
}

However, when I try to call that method, I get a compiler error:

    /// <summary>
    /// Calculates the results of an attack, and directly updates the GameObjects involved.
    /// </summary>
    /// <param name="attacker">The aggressor GameObject</param>
    /// <param name="victim">The GameObject under assault</param>
    public void ComputeAttackUpdate(CombatantGameObject attacker, CombatantGameObject victim)
    {
        if (worldQuery.IsColliding(attacker, victim, false))
        {
            victim.Model.Health -= attacker.Model.Damage((float) rand.NextDouble()); // error here
            Debug.WriteLine(String.Format("{0} hits {1} for {2} damage", attacker, victim, attackTraits.Damage));
        }
    }

The error is:

'Damage': cannot reference a type through an expression; try 'HWAlphaRelease.GameObject.CombatantGameModel.Damage' instead

What am I doing wrong?

+2  A: 

You need to associate a function with that delegate before you can invoke it.

You don't need a delegate here - with the code you have, you are better off having your Damage function as either an implementation of an interface, or have it declared as abstract (or virtual) in the base GameObjectModel class so that the derived classes can (or have to) override it.

slugster
+1 Don't need a delegate here, I agree.
Will Marcouiller
It depends. If you want the calculation to be extremely flexible and interchangable at runtime, a delegate is often a simpler, more straightforward option.
rh
+1  A: 

You are actually declaring a nested delegate type named Damage, not an instance of that type. Think of it as the difference between a class an an instance of a class.

To actually use your delegate, you must declare a field, property or event to hold it.

For example:

// note that the delegate can be declared either in a class or outside of it.
public delegate int Damage(float randomSample);

public class CombatantGameModel /* ... */
{
    /* ... */

    public Damage DamageCalculator { get; set; }
}
rh
A: 

Perhaps a little more explanation about delegates shall guide you.

Will Marcouiller