Home > Game Development > Game Items composed of Visitors

Game Items composed of Visitors

I recently made a response on gamedev.net forums regarding how Items should be designed. I came up with an idea of using the Visitor Pattern to allow for any game entity to be altered by any sort of Item without creating coupling between the entity and Item. Here is my response:

I started typing up a response and realized that perhaps the Visitor Pattern could be of some interesting use in this situation. By using this method, you would be able to create all sorts of visitors; visitors that alter any entity’s HP, visitors that change the state of any entity, visitors that even create a helper character or make the player fly.

The idea of the visitor pattern is that anything (any class) that would like to have the ability to be visited by a visitor simply includes a single method:

void acceptVisitor(Visitor v){ v.visit(this); }

The class should also provide an interface (not Java interface, but setter/getter methods) that the visitor would use to do whatever the visitor wants with the object. This removes coupling between the character and the item (if the item were a visitor), and allows for any new visitors to be added without having to touch the character class (or any class with the acceptVisitor() method).

Now, like I’ve said, I just thought of this idea, so I’ll lay down some example code and I’ll probably be able to determine from that whether or not it is a viable option. So, if you don’t understand the code I’m about to write, check out the Visitor Pattern and come back, but you should be able to see the idea; it’s very simple.

// Perhaps every character (player, enemy, NPC) in your game has a health
// and an (x, y) position
public class Character {
private int health;
private int x_pos;
private int y_pos;

// Constructor
public Character(...){...}

// Visitor method
public void acceptVisitor(Visitor v){
v.visit(this);
}

// Interface (getter/setter methods)
public int getHealth(){ return health; }
public int getXPos()  { return x_pos;  }
public int getYPos()  { return y_pos;  }

public void setHealth(int hp){ health = hp; }
}

Now, you have a Character class (while simple, gets the idea across) that can accept any Visitor. You can create all sorts of visitors (although there wouldn’t be much they could do since the Character only has a health and (x, y) position) and you can apply them (visit) with any Character without having to touch the Character class again.

Now we need to make a Visitor. One issue with the Visitor pattern is that every implementation of the Visitor interface (Java interface)(or abstract class) must provide definitions for each method, even if they don’t care about those methods. We won’t run into that problem in this example, but if you use the pattern in the future you’ll soon see this.

So, here’s the basic Visitor interface

public interface Visitor {
public void visit(Character c);
}

Remember, our Item‘s will be visitors to Characters, so each Item must implement this Visitor interface and define the method. This is where you can make whatever you want, but to show you the possibilities I’ll make a visitor that alters a Characters health and a visitor that creates a helper NPC.

// This could be a HealthPotion, or perhaps an object HealthPotion could contain
// a HealthVisitor? Something to consider
public class HealthVisitor implements Visitor {
private int amount;

// Constructor
public HealthVisitor(int amount){
this.amount = amount;
}

public void visit(Character c){
c.setHealth( c.getHealth() + amount );
}
}

public class CreateSidekickVisitor implements Visitor {
// Constructor
public CreateSidekickVisitor(){}

public void visit(Character c){
int x = c.getXPos() + 5;
int y = c.getYPos() + 5;

// Some NPC class, for example Sidekick, created right next to the Character
Character sidekick = new Sidekick(x, y);
}
}

I can see that you would probably want to create an Item class to not only provide the necessary variables for the visitors, but to encapsulate and hide the visitation methods. The Item class would have the abstract method use(), similar to your action() method. Then, the concrete implementations of the Item would invoke their own visitors on whatever Character the item is set to be used on. It could look like this:

public interface Item {
public void use(Character c);
}

public HealthPotion implements Item {
private Visitor healthVisitor;
private int     amount;

// Constructor
public HealthPotion(int amount){
// Create the HealthVisitor and provide it with the necessary information
healthVisitor = new HealthVisitor(amount);
this.amount   = amount;
}

// Define use()
public void use(Character c){
c.acceptVisitor(healthVisitor);
}
}

Now to use the Item, simply call the use() method

// Somewhere in your game
Item healthPotion = new HealthPotion(10); // a HealthPotion that restore 10 HP

// Assuming your have an inventory system, and that healthPotion is in your
// Characters inventory, this method call would be made from within your Character class
healthPotion.use(this); // if this method is in your Character class, 'this' would be your Character

After writing all this, it seems to be an interesting idea for Item‘s. Although this limited example may not show the flexibility in a system like this, it’s easy to see what is possible. For example, you could have an Item have multiple visitors, and when you use the item it could boost a characters health (HealthVisitor), give them a sidekick (CreateSidekickVisitor), and enhance their current weapon with fire (EnchantWeaponWithFireVisitor)(using the Decorator pattern on their current weapon)…and all from a single use() invoked on a single Item.

Advertisements
Categories: Game Development Tags:
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: