Ich mache ein Spiel, das mit dem Entity-Component-Paradigma entworfen wurde und Systeme verwendet, um zwischen Komponenten zu kommunizieren, wie hier erläutert . Ich habe den Punkt in meiner Entwicklung erreicht, an dem ich Spielzustände hinzufügen muss (z. B. Pause, Spielen, Levelstart, Rundenstart, Spielende usw.), bin mir aber nicht sicher, wie ich das mit meinem Framework machen soll. Ich habe mir dieses Codebeispiel für Spielzustände angesehen, auf die sich jeder zu beziehen scheint, aber ich denke nicht, dass es zu meinem Framework passt. Es scheint, dass jeder Staat seine eigene Zeichnung und Aktualisierung handhabt. Mein Framework verfügt über einen SystemManager, der alle Aktualisierungen mithilfe von Systemen übernimmt. Hier ist zum Beispiel meine RenderingSystem-Klasse:
public class RenderingSystem extends GameSystem {
private GameView gameView_;
/**
* Constructor
* Creates a new RenderingSystem.
* @param gameManager The game manager. Used to get the game components.
*/
public RenderingSystem(GameManager gameManager) {
super(gameManager);
}
/**
* Method: registerGameView
* Registers gameView into the RenderingSystem.
* @param gameView The game view registered.
*/
public void registerGameView(GameView gameView) {
gameView_ = gameView;
}
/**
* Method: triggerRender
* Adds a repaint call to the event queue for the dirty rectangle.
*/
public void triggerRender() {
Rectangle dirtyRect = new Rectangle();
for (GameObject object : getRenderableObjects()) {
GraphicsComponent graphicsComponent =
object.getComponent(GraphicsComponent.class);
dirtyRect.add(graphicsComponent.getDirtyRect());
}
gameView_.repaint(dirtyRect);
}
/**
* Method: renderGameView
* Renders the game objects onto the game view.
* @param g The graphics object that draws the game objects.
*/
public void renderGameView(Graphics g) {
for (GameObject object : getRenderableObjects()) {
GraphicsComponent graphicsComponent =
object.getComponent(GraphicsComponent.class);
if (!graphicsComponent.isVisible()) continue;
GraphicsComponent.Shape shape = graphicsComponent.getShape();
BoundsComponent boundsComponent =
object.getComponent(BoundsComponent.class);
Rectangle bounds = boundsComponent.getBounds();
g.setColor(graphicsComponent.getColor());
if (shape == GraphicsComponent.Shape.RECTANGULAR) {
g.fill3DRect(bounds.x, bounds.y, bounds.width, bounds.height,
true);
} else if (shape == GraphicsComponent.Shape.CIRCULAR) {
g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
}
/**
* Method: getRenderableObjects
* @return The renderable game objects.
*/
private HashSet<GameObject> getRenderableObjects() {
return gameManager.getGameObjectManager().getRelevantObjects(
getClass());
}
}
Außerdem sind alle Aktualisierungen in meinem Spiel ereignisgesteuert. Ich habe keine Schleife wie die ihre, die einfach alles gleichzeitig aktualisiert.
Ich mag mein Framework, weil es das Hinzufügen neuer GameObjects erleichtert, aber nicht die Probleme hat, auf die einige komponentenbasierte Designs bei der Kommunikation zwischen Komponenten stoßen. Ich würde es hassen, es zu schmeißen, nur um eine Pause zur Arbeit zu bekommen. Gibt es eine Möglichkeit, meinem Spiel Spielzustände hinzuzufügen, ohne das Design der Entitätskomponenten zu entfernen? Passt das Spielstatusbeispiel tatsächlich zu meinem Framework und mir fehlt nur etwas?
EDIT: Ich habe mein Framework möglicherweise nicht gut genug erklärt. Meine Komponenten sind nur Daten. Wenn ich in C ++ codieren würde, wären sie wahrscheinlich Strukturen. Hier ist ein Beispiel von einem:
public class BoundsComponent implements GameComponent {
/**
* The position of the game object.
*/
private Point pos_;
/**
* The size of the game object.
*/
private Dimension size_;
/**
* Constructor
* Creates a new BoundsComponent for a game object with initial position
* initialPos and initial size initialSize. The position and size combine
* to make up the bounds.
* @param initialPos The initial position of the game object.
* @param initialSize The initial size of the game object.
*/
public BoundsComponent(Point initialPos, Dimension initialSize) {
pos_ = initialPos;
size_ = initialSize;
}
/**
* Method: getBounds
* @return The bounds of the game object.
*/
public Rectangle getBounds() {
return new Rectangle(pos_, size_);
}
/**
* Method: setPos
* Sets the position of the game object to newPos.
* @param newPos The value to which the position of the game object is
* set.
*/
public void setPos(Point newPos) {
pos_ = newPos;
}
}
Meine Komponenten kommunizieren nicht miteinander. Systeme übernehmen die Kommunikation zwischen Komponenten. Meine Systeme kommunizieren auch nicht miteinander. Sie haben separate Funktionen und können leicht getrennt gehalten werden. Das MovementSystem muss nicht wissen, was das RenderingSystem rendert, um die Spielobjekte korrekt zu verschieben. Es müssen nur die richtigen Werte für die Komponenten festgelegt werden, damit das RenderingSystem beim Rendern der Spielobjekte genaue Daten enthält.
Der Spielstatus kann kein System sein, da er eher mit den Systemen als mit den Komponenten interagieren muss. Es werden keine Daten festgelegt. Es bestimmt, welche Funktionen aufgerufen werden müssen.
Eine GameStateComponent wäre nicht sinnvoll, da alle Spielobjekte einen Spielstatus gemeinsam haben. Komponenten bilden Objekte und jedes ist für jedes Objekt anders. Beispielsweise können die Spielobjekte nicht dieselben Grenzen haben. Sie können überlappende Grenzen haben, aber wenn sie eine BoundsComponent gemeinsam nutzen, sind sie wirklich dasselbe Objekt. Hoffentlich macht diese Erklärung meinen Rahmen weniger verwirrend.