如何在基于实体/组件的系统中构造游戏状态


11

我在做设计与实体分量范例,使用系统组件之间的通信,说明游戏在这里。在开发过程中,我已经达到需要添加游戏状态(例如暂停,播放,关卡开始,回合开始,游戏结束等)的地步,但是我不确定如何在我的框架中进行操作。我看对游戏状态的代码示例,每个人都似乎是参考,但我不认为它与我的框架适合。似乎每个状态都处理自己的绘图和更新。我的框架有一个SystemManager,可以处理使用系统进行的所有更新。例如,这是我的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());
    }

}

另外,我游戏中的所有更新都是事件驱动的。我没有像他们这样的循环可以同时更新所有内容。

我喜欢我的框架,因为它可以轻松添加新的GameObject,但是在组件之间进行通信时,不会遇到某些基于组件的设计遇到的问题。我不想为了工作而停下来。有没有一种方法可以在不删除实体组件设计的情况下向游戏添加游戏状态?游戏状态示例是否真的适合我的框架,而我只是缺少一些东西?

编辑: 我可能还没有很好地解释我的框架。我的组件只是数据。如果我用C ++编写代码,则它们可能是结构。这是一个例子:

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

}

我的组件无法相互通信。系统处理组件间的通信。我的系统也不互相通信。它们具有单独的功能,可以轻松地保持分开。MovementSystem不需要知道RenderingSystem正在渲染什么,就可以正确移动游戏对象。它只需要在组件上设置正确的值,以便RenderingSystem渲染游戏对象时,它具有准确的数据。

游戏状态不能是系统,因为它需要与系统而非组件进行交互。它不是在设置数据;它确定需要调用哪些函数。

GameStateComponent没有意义,因为所有游戏对象都共享一个游戏状态。组件是组成对象的对象,每个对象对于每个不同的对象都是不同的。例如,游戏对象不能具有相同的边界。它们可以具有重叠的边界,但是如果它们共享一个BoundsComponent,则它们实际上是同一对象。希望这种解释可以使我的框架不那么混乱。

Answers:


4

我承认我没有阅读您发布的链接。编辑完并阅读所提供的链接后,我的位置已更改。下面反映了这一点。


我不知道您需要担心传统意义上的游戏状态。考虑到您的开发方法,每个系统是如此具体,以至于实际上游戏的状态管理。

在实体系统中,组件只是数据,对吗?状态也是这样。以最简单的形式,它只是一个标志。如果将状态构建到组件中,并允许系统使用这些组件的数据并对其中的状态(标志)做出反应,则将状态管理构建到每个系统本身中。

诸如AppHub示例的管理系统似乎不适用于您的开发范例。创建一个封装其他系统的超级系统似乎无法达到将逻辑与数据分离的目的。

这可以帮助您理解我不必显式处理游戏状态的含义:

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


请看我的编辑。对不起,如果我感到困惑。
伊娃(Eva)2012年

更新以反映新发现和您的编辑。希望有人在建筑实体系统更多的经验将帮腔,因为这不是一个区域,我有很多的经验英寸
Cypher支架

当游戏状态改变时,删除和添加系统该怎么办?例如,当您暂停游戏时,也许不需要您的MovementSystem或CollisionSystem,但是您仍希望RenderSystem在屏幕上绘制内容。活动系统可以代表游戏状态吗?
argenkiwi 2014年

0

状态是适用于对象的值。顾名思义,游戏状态将是“游戏”对象的状态。该游戏对象(或更可能是其上的特定组件)将跟踪当前状态并创建或销毁促进当前状态所需的任何对象。由于您的组件只是数据,因此即使可能只有一个相关组件的实例,也需要一个新的System来处理它。

当不清楚如何实现更新时,很难评论如何实现暂停。如果游戏对象说游戏已暂停,则发出更新事件的进程可以选择不这样做。游戏对象如何与更新过程进行通信取决于您;也许您的getRelevantObjects呼叫应该允许更新程序找到Game对象,反之亦然。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.