patterncppMinor
Simple game engine layout
Viewed 0 times
enginegamesimplelayout
Problem
I'm trying to make a game with inheritance & interfaces and I'm wondering if my system could be working without ECS. (I explain at the end why I'm not using components).
To make it easier to understand there are three core class "families" in the code:
Engine related classes:
Using E~~~ as a prefix for each class
Interfaces:
I'm using them like properties, they don't contain data, they're contracts, like C# interfaces (and Java I believe?):
Using I~~~ as a prefix for each class
"Concrete" classes:
They contain data and implements the interfaces. The could be
Using C~~~ as a prefix for each class
Plus a class named Engine that contains every E~~~ class so it makes it easy to access "Engine elements".
Engine-related code:
Interface-related code:
```
class ITransformable {
public:
virtual float getX() = 0;
virtual float getY() = 0;
virtual void setX(float x) = 0;
virtual void setY(float x) = 0;
virtual ~ITransformable() {}
};
class IDestroyable {
public:
virtual float getHp() = 0;
virtual void setHp(float hp) = 0;
virtual void hurt(float amount) = 0;
virtual void kill() = 0;
virtual bool isAlive() = 0;
virtual ~IDestroyable() {}
};
class IEngine {
public:
virtual void provideEngine(EEngine* engine) = 0;
virtual ~IEngine() {}
};
class ITeam {
public:
virtu
To make it easier to understand there are three core class "families" in the code:
Engine related classes:
Graphics, Inputs, Audio, Physics,...Using E~~~ as a prefix for each class
Interfaces:
I'm using them like properties, they don't contain data, they're contracts, like C# interfaces (and Java I believe?):
Transformable, Destroyable, ...Using I~~~ as a prefix for each class
"Concrete" classes:
They contain data and implements the interfaces. The could be
Player, Bullet, etc.Using C~~~ as a prefix for each class
Plus a class named Engine that contains every E~~~ class so it makes it easy to access "Engine elements".
Engine-related code:
class EInput {
public:
enum { keyCount = 64 };
char state[keyCount];
char previousState[keyCount];
};
class EGraphics {
public:
int width, height;
};
class EPhysics {
public:
float gravity;
};
class EEngine {
public:
EInput* input;
EGraphics* graphics;
EPhysics* physics;
EEngine() {
input = new EInput();
graphics = new EGraphics();
physics = new EPhysics();
}
~EEngine() {
delete input;
delete graphics;
delete physics;
}
};Interface-related code:
```
class ITransformable {
public:
virtual float getX() = 0;
virtual float getY() = 0;
virtual void setX(float x) = 0;
virtual void setY(float x) = 0;
virtual ~ITransformable() {}
};
class IDestroyable {
public:
virtual float getHp() = 0;
virtual void setHp(float hp) = 0;
virtual void hurt(float amount) = 0;
virtual void kill() = 0;
virtual bool isAlive() = 0;
virtual ~IDestroyable() {}
};
class IEngine {
public:
virtual void provideEngine(EEngine* engine) = 0;
virtual ~IEngine() {}
};
class ITeam {
public:
virtu
Solution
I had a few thoughts whilst reading through your code:
Naming
I don't mind the
Interfaces
Some of your interfaces don't really feel like interfaces. For example,
Initialisation
You're declaring variables and calling methods on them at the same time:
This seems error prone. It also flags up a possible design error. Does it make sense for a
Public fields
You're passing an instance of
Naming
I don't mind the
I prefix for interfaces, I've never really liked C as a prefix for classes although I can live with it. Having another prefix of E for engine specific classes feels wrong/confusing. EEngine is a concrete class, that does stuff, why isn't it ECEngine / CEEngine for example?Interfaces
Some of your interfaces don't really feel like interfaces. For example,
IEngine has one method provideEngine. This isn't what I think of when I think of an Engine interface. It could be an IEngineUser interface but it still feels a bit wrong. I'd expect IEngine to define operations that were then implemented in EEngine.Initialisation
You're declaring variables and calling methods on them at the same time:
CAIPlayer lambert; lambert.provideEngine(&engine);This seems error prone. It also flags up a possible design error. Does it make sense for a
CAIPlayer to exist without an engine / without a team? If not, then I would expect it to be passed into the constructor, rather than passed in immediately after every construction. It seems like you've done it this way because of the interfaces you've declared which specify class dependencies rather than what a class can do...Public fields
You're passing an instance of
EEngine into every class it has public pointers to other engine classes that have public fields. This feels like way too much exposure of your engines implementation. I would hide this information behind getter methods. Then either pass the intial values into the constructor or provide setter methods. Whilst they may be simple pass throughs initially it will easier in the future if you want to make changes such as supporting different gravity zones Does it really make sense that at the moment any CCharacter can change the gravity in the game?Code Snippets
CAIPlayer lambert; lambert.provideEngine(&engine);Context
StackExchange Code Review Q#147621, answer score: 6
Revisions (0)
No revisions yet.