principlecsharpMajor
Reusability vs simplicity in a small game with a set of interfaces
Viewed 0 times
withsimplicityreusabilitygamesmallinterfacesset
Problem
I have a small game I'm working on with a set of interfaces:
As you can see, they all share a generic parameter
An additional problem is that this might not (conceivably) be the only time I need to do this. What if I want to add a
Since
IHavePosition:public interface IHavePosition
{
T Position { get; set; }
}ICanMove:public interface ICanMove : IHavePosition
{
IEnumerable> Motors { get; set; }
}ICharacter:public interface ICharacter : IHavePosition, ICanMove
{
///
/// Gets or sets the action points.
///
///
/// The action points.
///
int ActionPoints { get; set; }
///
/// Gets or sets the maximum action points.
///
///
/// The maximum action points.
///
int MaxActionPoints { get; set; }
}IPlayer:public interface IPlayer : ICharacter, IResetable
{
///
/// Gets or sets the gold in the player's inventory.
///
///
/// The gold.
///
int Gold { get; set; }
}IEnemy:public interface IEnemy : ICharacter
{
}As you can see, they all share a generic parameter
TPos, which is the data type used to store an object's position. I keep this generic because I hope to reuse these interfaces in later projects which might have different position storage types (e.g. floating point coordinates versus an integer grid. 3D coordinates versus 2D, etc). The problem, however, is that this means when creating my classes, I need to ferry around this TPos generic construct to places where it doesn't make sense to define it. I'm left creating new Player or Player instances all over the place when really I just want to be creating a Player.An additional problem is that this might not (conceivably) be the only time I need to do this. What if I want to add a
Health field that could be an int, or a float, etc? I'm now creating Player or Enemy instances all over the place.Since
TPos is the same project-wide, is there a better way of doing this than lugging around references to TPos everywhere?Solution
The problem, however, is that this means when creating my classes, I need to ferry around this TPos generic construct to places where it doesn't make sense to define it. I'm left creating new
Yes, specifying
You could create a
I think however that your class inheritance will become quite complex, if it isn't complex enough already. Which you state yourself with this:
An additional problem is that this might not (conceivably) be the only time I need to do this. What if I want to add a Health field that could be an int, or a float, etc? I'm now creating
It sounds like what you need is to use composition over inheritance. A common way to do this in modern games is to use the Entity Component System approach.
If you go with this approach, both a
There is a Entity Component System library named Artemis which has been ported to C# (I haven't used this myself, but I believe it's suitable enough for your needs). You can also make a Entity Component System implementation yourself, which many others have done on Code Review already (see entity-component-system)
To get an additional understanding of ECS, there is also an excellent question on GameDev StackExchange
Even though ECS is mostly used in real-time games, it is also possible to use it in turn-based games, which I have started doing myself in my Trading Card Game code.
Player or Player instances all over the place when really I just want to be creating a Player.Yes, specifying
Player each time can be quite frustrating. I'm not sure though if you just want to create just a Player or if you want to create a specific kind of playerYou could create a
GameOnePlayer class which extends Player, so then you create a GameOnePlayer and not a Player. You might have use for the Abstract Factory Pattern for the creation of these objects.I think however that your class inheritance will become quite complex, if it isn't complex enough already. Which you state yourself with this:
An additional problem is that this might not (conceivably) be the only time I need to do this. What if I want to add a Health field that could be an int, or a float, etc? I'm now creating
Player or Enemy instances all over the place.It sounds like what you need is to use composition over inheritance. A common way to do this in modern games is to use the Entity Component System approach.
If you go with this approach, both a
Player and an Enemy should both just be an Entity. Then you can add whatever components they need, such as a Vector3Position component or a Int2Position component. Also IntHealthComponent and FloatHealthComponent.There is a Entity Component System library named Artemis which has been ported to C# (I haven't used this myself, but I believe it's suitable enough for your needs). You can also make a Entity Component System implementation yourself, which many others have done on Code Review already (see entity-component-system)
To get an additional understanding of ECS, there is also an excellent question on GameDev StackExchange
Even though ECS is mostly used in real-time games, it is also possible to use it in turn-based games, which I have started doing myself in my Trading Card Game code.
Context
StackExchange Code Review Q#57569, answer score: 20
Revisions (0)
No revisions yet.