I'm developing a tile-based game creation library in C# and along with it I'm creating a game to test all of its functions.
This is a screenshot of the game:
You've probably never heard of the original, but my game is a clone of Deadly Rooms of Death (DROD), which you can find at http://caravelgames.com
Anyway, as you can see from the screenshot, my game (and my library) is all about 2D puzzle games on a grid, rigorously turn based.
My library has this structure:
- Entity: class that gets updated every turn and every game elements inherits from
- Tile: class that holds entities (any amount of entities)
- TileManager: class that contains a 2D array of all the tiles
- Field: class that contains a TileManager and all the methods for querying it and finding entities
For fast queries and flexibility, I'm using interfaces and inheritance to group entities. Let me explain with code for the roach entity:
public class TDLMonster : TDEntity, IHasTarget, IDrawn, IHasDirection, ISolid,
IHitByWeapon, IHitByMonster
{
...
}
The TDLMonster class inherits from TDEntity (which inherits from Entity). It also uses interfaces as a way to mark certain properties of elements.
public interface IHitByWeapon : IEntity
{
void HitBySword(IWeapon mWeapon);
}
This is the IHitByWeapon interface. After every turn, weapons check if there is any instance of IHitByWeapon on their tile. If there is, call HitBySword. Here's the code that does this:
public virtual void CheckHits()
{
List<Entity> hitEntities = Field.GetEntities(X, Y, typeof (IHitByWeapon));
for (int i = 0; i < hitEntities.Count; i++)
{
IHitByWeapon hitEntity = (IHitByWeapon) hitEntities[i];
hitEntity.HitByWeapon(this);
}
}
Field.GetEntities(x, y, type) returns a list of entities of that type in a specific tile. When an entity is initialized, my library gets all the types and interfaces using the following code snippet, then puts the entity in dictionaries having types and interfaces as keys:
public static List<Type> GetAllTypes(Entity mEntity)
{
List<Type> types = new List<Type> {mEntity.GetType()};
Type[] nestedTypes = mEntity.GetType().GetNestedTypes();
types.AddRange(nestedTypes);
Type[] interfaces = mEntity.GetType().GetInterfaces();
types.AddRange(interfaces);
foreach (Type type in nestedTypes) types.AddRange(type.GetInterfaces());
return types;
}
...
foreach (Type type in GetAllTypes(this))
{
if (!Tile.TileManager.GroupedEntities.ContainsKey(type)) Tile.TileManager.GroupedEntities.Add(type, new List<Entity>());
Tile.TileManager.GroupedEntities[type].Add(this);
}
My library/game is relies completely on types and interfaces.
This is a good thing because I know what methods and properties entities have, and because different entities can share the same interface. I can have 20 different types of monsters, but as long as they implement IHitByWeapon they will all get killed by the player's sword.
This is a bad thing because it relies on hardcoding elements, and I cannot manipulate interfaces at runtime. Let's say I have a door element. I need it to be solid when the door is closed and to be non-solid when the door is open. If the element implements ISolid I cannot remove it. The same problem applies if I suddenly want a flying roach. I would have to code another element that implements ICanFly, because I cannot add an interface to an entity at runtime.
I've thought about using a List of stuff like "solid", "enemy", "player" - but it's not flexible enough, since I cannot have interface-like methods or properties, and I need to guess if the entity has a method or use the dynamic keyword.
How can I solve this problem? Is there something that lets me have the ease of use as interfaces but also the flexibility as List?
Let me know if you need more information or parts of the source code.