11
\$\begingroup\$

I'm making a game designed with the entity-component paradigm that uses systems to communicate between components as explained here. I've reached the point in my development that I need to add game states (such as paused, playing, level start, round start, game over, etc.), but I'm not sure how to do it with my framework. I've looked at this code example on game states which everyone seems to reference, but I don't think it fits with my framework. It seems to have each state handling its own drawing and updating. My framework has a SystemManager that handles all the updating using systems. For example, here's my RenderingSystem class:

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());
    }

}

Also all the updating in my game is event-driven. I don't have a loop like theirs that simply updates everything at the same time.

I like my framework because it makes it easy to add new GameObjects, but doesn't have the problems some component-based designs encounter when communicating between components. I would hate to chuck it just to get pause to work. Is there a way I can add game states to my game without removing the entity-component design? Does the game state example actually fit my framework, and I'm just missing something?

EDIT: I might not have explained my framework well enough. My components are just data. If I was coding in C++, they'd probably be structs. Here's an example of one:

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;
    }

}

My components do not communicate with each other. Systems handle inter-component communication. My systems also do not communicate with each other. They have separate functionality and can easily be kept separate. The MovementSystem doesn't need to know what the RenderingSystem is rendering to move the game objects correctly; it just need to set the right values on the components, so that when the RenderingSystem renders the game objects, it has accurate data.

The game state could not be a system, because it needs to interact with the systems rather than the components. It's not setting data; it's determining which functions need to be called.

A GameStateComponent wouldn't make sense because all the game objects share one game state. Components are what make up objects and each one is different for each different object. For example, the game objects cannot have the same bounds. They can have overlapping bounds, but if they share a BoundsComponent, they're really the same object. Hopefully, this explanation makes my framework less confusing.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

I'll admit that I didn't read the link you posted. After your edit, and reading the link provided, my position has changed. The below reflects this.


I don't know that you need to worry about game states in the traditional sense. Considering your approach to development, each system is so specific that they, in effect, are the game's state management.

In an entity system, the components are just data, right? So is a state. In its simplest form, it's just a flag. If you build your states into components, and allow your systems to consume those components' data and react to the states (flags) within them, you will be building your state management into each system itself.

It seems management systems such as the AppHub example do not apply very well to your development paradigm. Creating a super-system that encapsulates other systems seems to defeat the purpose of separating logic from data.

This might help you to understand what I mean about not having to explicitly handle game states:

http://paulgestwicki.blogspot.com/2012/03/components-and-systems-of-morgans-raid.html

\$\endgroup\$
3
  • \$\begingroup\$ Please see my edit. Sorry if I was confusing. \$\endgroup\$
    – Eva
    Jun 26, 2012 at 8:43
  • \$\begingroup\$ Updated to reflect new discoveries and your edits. Hopefully someone with more experience in building entity systems will chime in, as this isn't an area that I have a lot of experience in. \$\endgroup\$
    – Cypher
    Jun 26, 2012 at 16:18
  • \$\begingroup\$ What about removing and adding systems when the game state changes? For example, when you pause the game perhaps your MovementSystem or CollisionSystem are not needed, but you still want your RenderSystem to draw stuff on the screen. Could the active systems represent a game state? \$\endgroup\$
    – argenkiwi
    Sep 8, 2014 at 21:23
0
\$\begingroup\$

State is a value that applies to an object. Game state, as the name suggests, would be the state of a 'Game' object. That Game object - or more likely, a specific component on it - would track the current state and create or destroy whatever objects are necessary to facilitate the current state. Since your components are just data you will need a new System to handle this, even though there may only ever be one instance of its associated component.

It's hard to comment on how you would implement pausing when it's not clear how you implement updating. The process that emits update events could elect not to do so, if the game object says the game is paused. How the game object communicates to the updating process is down to you; perhaps your getRelevantObjects call should allow the updater to find the Game object, or vice versa.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .