I need more hindsight


I started rewriting the entire project yesterday and so far I’m really pleased with the results. I find it helps me to implement something, analyze it, and then scrap it completely. That way I gain the experience of why certain decisions where good and why others were bad.

Some changes I made in the new design are as follows:

  • I got rid of the IDungeonTile metaphor. IDungeonTile constrained me to dungeons and contained logic related to movement. I now use an ITerrainType interface which contains one property describing the terrain composition. This change brings about the Terrain metaphor allowing me to use the same construct for towns, wilderness and dungeons. Each ITerrainType instance defines its own composition based on a set of flags for example Acid, Granite, Lava, etc.
  • I shifted the focus to from a player to actors. No longer do I have hard coded logic based on the player, but rather handle anything from the perspective of an actor. Monsters, NPCs and players are all actors. For testing purposes I take out the player and just have monsters playing the game.
  • Ok, I don’t really have monsters or NPCs either, but rather an actor with an intellect. The intellect is defined by the IIntellect interface and allows me to give an actor a specific IIntellect implementation. Currently I make use of a ComputerAI and PlayerAI. The ComputerAI implementation will make decisions based on it’s needs at the time. Decisions are translated into Commands and then executed by the game engine. PlayerAI is under the control of the player and does nothing until it receives an input command from the player which is then translated into a Command.
  • From the above you will realize that I’ve added a generic command structure using the Command design pattern. All actions within the game get translated into a ICommand object and are executed in turn by the engine.
  • IMovementBehaviour has become IMovementProfile. I just like the terminology better. I changed the handle bump functionality somewhat. The movement profile now provides a default action to perform when an actor collides with something. This is useful if I have an actor that can dig through walls versus an actor that moves like a humanoid. The default action for a digging actor when colliding with rock would be to dig versus a humanoid actor who would do nothing.
  • I added a new IFovProfile to my field of view code. The field of view profile describes how something “sees” in the game. This includes the field of view shape, sight range, and some functionality to determine if something is visible based on the amount of light it receives. The last bit of functionality is useful to implement blindness, infravision, etc.
  • I created a GameLevel object that will manage the aspects of the particular game level. This could be a town, wilderness area or a dungeon. The GameLevel has a TerrainMap (which is a bunch of ITerrainType instances), a list of actors, and a lightmap (which describes the lighting information for the level). In the future I will add a list of level objects i.e. treasure to the game level.

The above changes are a big departure from the original design, but feel a lot more like a game design (from a software design perspective) rather than a dungeon generator with stuff hacked onto it. I am thinking that the IMovementProfile and IFovProfile interfaces will probably move from the Actor class to some kind of Race class. That way the actor’s race would define its movement and field of view characteristics.

My new implementation has already raised some more questions. When I check for a collision I ask my GameLevel object for the composition properties of the terrain at the location I want to move to. Then I ask my GameLevel object for the composition properties of any actors at that location. An actor has a collision when the union of the terrain and actor composition properties is impassable for the IMovementProfile at the target location.

The question is whether I should leave the check as two separate calls, one for terrain and one for actors? This seems a bit clumsy. To change it to a single method call would necessitate the ITerrainType and Actor classes to inherit from the same base class. The base class would define a common Composition property which is used during collision checks. As a rule I am not keen on inheritance hierarchies and never imagined all my “game” objects inheriting from some super class.

Hence the need for more hindsight.

Advertisements

3 thoughts on “I need more hindsight

  1. Its good to see articles on the design of a roguelike from a software design/engineering point of view.

    The command design pattern is quite nifty, I used it for the AI in my Roguelike.

    It consisted of a baseclass AI and then children AI_FIGHT, AI_ARCHER, AI_MAGE etc..

    With abstract methods think() and act() to be overridden in each childclass. Worked pretty well.

  2. Sounds cool.

    My initial difficulty with my Command pattern implementation was making the various game elements available in the Execute method of the command.

    For the Move command I need to provide the Actor to move and the direction, but then I also need to determine if I can actually move in the direction. For this I need access to my Terrain.

    My solution was to implement some bi-directional relationships between my objects. This allows me to navigate up the hierarchy to get access to resources I might need to make decisions.

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