Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance/Interface design of a game

I'm designing a game, but I can't quite get my head around the inheritance structure. I'm normally fairly good at it, but this one just has too much overlap and I can't decide on it all.

I'm seeking to model sailing vessels - think the Age of Sail. Presumably therefore everything extends a Vessel class.

There are then several types of vessel style: rowed (galleys, canoes), square-rig, fore-and-aft rig, with different behaviour. Each of these is further subdivided into several other types. I can't decide whether this should be a series of interfaces or extensions of Vessel. Note also that there can be some cross over (a vessel can be both rowed and square rigged) which leads me to think interfaces?

Ships also have different behaviours: merchant vessels, men of war, privateer, pirates. I really can't work out whether this should be an interface or an extension of another class. There is no crossover of type in this case, however.

Finally there are several behaviours which individual ships can have. Merchants may be in a convoy (defend themselves) or independent (run away). Men of war almost always attack unless heavily outgunned... but may work in fleets, squadrons or independently. Privateers and pirates only attack if weaker - usually independently but occasionally in pairs. I'm assuming that this should be an interface too?

My big problem is that each style of ship (frigate, battleship etc) can fulfil almost any of these roles, so I can't build a simple solid inheritance structure. Frigate can't extend man-o-war because some are privateers. Sloop can't extend square rigged because some are fore and aft rigged. etcetc.

Any thoughts would be appreciated, I'm at a bit of a loose end. Thanks

like image 923
Jon Story Avatar asked Dec 30 '11 20:12

Jon Story


2 Answers

Make the "behavior" part as interfaces. That will help you assigning different behaviors to different ships without problem. Strategy Pattern is helpful here. In a nutshell, it states that the changeable and the constant properties should be separated.

For different means of movements, composition sounds like the most suitable answer at this moment.

Regarding the "but may work in fleets, squadrons or independently. Privateers and pirates only attack if weaker - usually independently but occasionally in pairs." part, I guess this has nothing to do with the inheritance tree. You can make "groups" of classes depending up on your need.

This might help you:

enter image description here

"There are then several types of vessel style:..." is specifying different possible behaviors. So "Movable" interface and its subclasses are for that. In the "Vessel" class, you can have a member of type "Movable". Since "Movable" is an interface, any class which implements it, is assignable to this member. So any subclass of Vessel can have any possible behavior, which we cna change at runtime as well. You can also make it an ArrayList. (Not sure if you actually want to do it or not). But if you need multiple different behaviors for a same vessel, you can do it.

When you say "Ships also have different behaviours:..." it feels like separate classes extending Vessel will satisfy this requirement. The sentence "There is no crossover of type in this case, however." makes life easier.

For the nest para "Finally there are several behaviours which individual ships can have...", you should add one more member for different possible behaviors. It will mostly be an ArrayList as one vessel will have multiple attack modes.

Fro the last para, if you can give some more details, I may be able to give some more ideas.

like image 158
Bhushan Avatar answered Nov 05 '22 07:11

Bhushan


Ok, here are some ideas:

  • Vessels have one or more means of propulsion (oars, sails, etc.), which you can model by composition (e.g. have a list of propulsion methods).
  • Vessels use one of a variety of strategies (use the strategy pattern -- see http://en.wikipedia.org/wiki/Strategy_pattern -- for this)
  • Strategies which depend on the presence of other nearby ships will need some way of querying for those other ships -- so you'll need some sort of data structure that allows you to find which objects are near which other objects (look into the sort of data structures that are used for broad-phase collision detection)

As an alternative to the strategy pattern, you could switch to using a component-based design. In this setup, a vessel would be composed of one or more propulsion components, a strategy component, etc. You could then combine individual components as you see fit to make different vessels.

As an extra bonus, component-based designs are very helpful if you want your game to be data-driven, because you can just write a saver/loader for each different type of component, rather than for each possible type of vessel.

You might want to see here if you're interested in this sort of approach:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

like image 28
Stuart Golodetz Avatar answered Nov 05 '22 06:11

Stuart Golodetz