Code It Right, Be Resourceful

Under the covers for Null Op I was trying out a third library which I haven’t released. This library’s goal was to facilitate moving all of an object’s settings into an external resource. You see as I have been developing Shade I noticed several things:

  1. There are tons of hard coded special values
  2. There is lots of redundant code acting on different data
  3. Each object’s resources are hard coded

Obviously it’s no good to have all of the metadata hard coded into the program; it makes it hard for people besides the original author to make changes, it’s difficult to impossible to re-use behavior, and it’s hard for an artist to quickly start theming things. All this being the case I thought I would expand on a technique to move some of these settings out of your class definition.

Bundles, Factories, and Dependency Injection

I think the most obvious way to approach this problem is with some sort of map. For things such as images and sounds it makes sense to map strings to strings, and for settings such as speed and health it makes more sense to map from strings to numbers. So with that in mind I would suggest creating something like so:

class ResourceBundle {
    public String get(String key) { }
    public int getInt(String key) { }
    public float getFloat(String key) { }
}

The more challenging question is how do you deliver this bundle to your object? I believe the best answer is through a factory and dependency injection. Dependency injection is a fancy way to describe a pretty simple concept. Instead of making your objects figure out how to get their hands on a bundle some external object should manage that for them…

using dependency injection, the object simply provides a property that can hold a reference to that type of service; and when the object is created a reference to an implementation of that type of service will automatically be injected into that property by an external mechanism.

Not only does this make things easier for the object but it makes it vastly easier to mock things for testing. Anyway, here’s how this might work:

class ActorFactory {
    public Actor create(String name, Object ... args) {
        ResourceBundle bundle = lookUpBundle(name);
        Object[] newArgs = combine(name, args);
        return ReflectionUtils.create(name, newArgs);
    }
}

So here you see that the factory is responsible for looking up for the designated actor. Once it has created the bundle it passes it as the first argument to the constructor along with any additional parameters.

Conclusion

So what are the challenges and why am I not sharing this library? The big problem comes when trying to come up with a generally useful form of metadata. Personally, I would start off with XML and simple map actors to XML files. But things get complicated as soon as you start trying to represent things such as Slick Colors or Input keys. Naturally though, you can special case these problems for your own game.

Adopting this pattern is a major win in terms of design. Once your application is data driven you’ll start to see all sorts of opportunities to re-use behavior. Personally, the wow moment for me was when I realized that I could bind to different on-key-press events and take unique action without having to re-implement the same listener logic again and again or create a giant switch statement. Of course, there are many other exciting things you can do once the metadata has been moved into an external file. I’ll end this post with some cool ideas:

  1. Let the user set his controls
  2. Let the user create his own theme
  3. Support multiple difficulties
  4. Let the user create levels

What cool ideas are you going to pursue?

Related Posts

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>