1

I have a class called "Entity," with two child classes: "Creature" and "Item." (I'm making a game.) Creature has two functions called "Attack," one for attacking Creatures, and one for attacking Items. So far, everything works well.

Now I'm working on the shooting bit, so I have a function called SelectTarget(). It takes all of the Entities (both Creatures and Items) in the player's view that the player can shoot and lets the player choose one.

So here lies the problem: SelectTarget() returns an Entity, but I need some code to figure out whether that Entity is a Creature or an Item, and process it appropriately.

Since this question looks kind of empty without any code, and I'm not 100% sure my explanation is good enough, here's where I'm at:

if (Input.Check(Key.Fire)) {
    Entity target = Game.State.SelectTarget.Run();
    this.Draw();
    if (target != null) {     
        //Player.Attack(target);
        // This won't work, because I have:
        //   Player.Attack((Creature)Target)
        //   Player.Attack((Item)Target)
        // but nothing for Entity, the parent class to Creature and Item.
        return true;
    }
}

(If the way the game is laid out seems weird, it's a roguelike.)

1
  • 1
    FYI what you are looking for is usually called "double virtual dispatch", and the canonical example of why it is useful is the "two things collide in a game and the right method needs to be called to sort it all out based on both their runtime types". C# is a single-virtual dispatch language; the standard pattern for implementing double dispatch in a single dispatch language is the Visitor Pattern, as SLaks noted. Commented Apr 23, 2010 at 22:39

3 Answers 3

9

You're looking for the Visitor pattern.

Sign up to request clarification or add additional context in comments.

1 Comment

So an Entity would have a method GetAttackedBy(Player) which invokes the right overload of Player.Attack? Weird, but +1.
9

What about introducting an interface IAttackable that both Creature and Item implement. Player.Attack would have the new signature Player.Attack(IAttackable target). Every object implementing IAttackable could get methods for substracting health, or retrieving defense values (for calculation of healthpoints to be reducted), and so on...

1 Comment

Ah, could've done this too... I'm new-ish to C#, and am still working out interfaces. Actually, this example cleared things up quite a bit, thanks!
3

try something like:

if(target is Creature)
      player.Attack(target as Creature);
else if(target is Item)
      player.Attack(target as Item);

7 Comments

True, could've checked for nulls instead
Thanks! I had no idea "is" and "as" even existed. Neat feature, and thanks for the quick reply!
This sounds like a problem for interfaces - always think twice before you implement a if/else chain or switch - there is almost always a better OOP approach
This works of course, however I think thats not a very desirable design. That is one of those cases where interfaces come in handy, instead of doing unnecessary things like checking and casting and handle special cases. Did you take a look at my answer?
Depending on how many different types of entites you intend on having, this code block could end up huge... I would have went for an IAttackable interface as suggested by @Philip
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.