Estoy haciendo un juego diseñado con el paradigma de entidad-componente que usa sistemas para comunicarse entre componentes como se explicó aquí . Llegué al punto en mi desarrollo de que necesito agregar estados de juego (como pausa, juego, inicio de nivel, inicio de ronda, juego terminado, etc.), pero no estoy seguro de cómo hacerlo con mi marco. He visto este ejemplo de código en los estados de juego a los que todos parecen hacer referencia, pero no creo que se ajuste a mi marco. Parece que cada estado maneja su propio dibujo y actualización. Mi marco tiene un SystemManager que maneja todas las actualizaciones usando sistemas. Por ejemplo, aquí está mi clase RenderingSystem:
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());
}
}
Además, todas las actualizaciones en mi juego están basadas en eventos. No tengo un ciclo como el de ellos que simplemente actualiza todo al mismo tiempo.
Me gusta mi marco porque hace que sea fácil agregar nuevos GameObjects, pero no tiene los problemas que encuentran algunos diseños basados en componentes cuando se comunican entre componentes. Odiaría tirarlo solo para hacer una pausa en el trabajo. ¿Hay alguna manera de agregar estados de juego a mi juego sin eliminar el diseño del componente de entidad? ¿El ejemplo del estado del juego realmente se ajusta a mi marco y me falta algo?
EDITAR: Podría no haber explicado mi marco lo suficientemente bien. Mis componentes son solo datos. Si estuviera codificando en C ++, probablemente serían estructuras. Aquí hay un ejemplo de uno:
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;
}
}
Mis componentes no se comunican entre sí. Los sistemas manejan la comunicación entre componentes. Mis sistemas tampoco se comunican entre sí. Tienen una funcionalidad separada y se pueden mantener fácilmente separadas. El MovementSystem no necesita saber qué renderiza el RenderingSystem para mover los objetos del juego correctamente; solo necesita establecer los valores correctos en los componentes, de modo que cuando RenderingSystem renderice los objetos del juego, tenga datos precisos.
El estado del juego no podría ser un sistema, ya que necesita interactuar con los sistemas en lugar de los componentes. No está estableciendo datos; determina qué funciones deben llamarse.
Un GameStateComponent no tendría sentido porque todos los objetos del juego comparten un estado de juego. Los componentes son los que componen los objetos y cada uno es diferente para cada objeto diferente. Por ejemplo, los objetos del juego no pueden tener los mismos límites. Pueden tener límites superpuestos, pero si comparten un BoundsComponent, son realmente el mismo objeto. Con suerte, esta explicación hace que mi marco sea menos confuso.