엔티티 / 컴포넌트 기반 시스템에서 게임 상태를 구성하는 방법


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

}

또한 내 게임의 모든 업데이트는 이벤트 중심입니다. 나는 단순히 모든 것을 동시에 업데이트하는 루프와 같은 루프를 가지고 있지 않습니다.

새 게임 오브젝트를 쉽게 추가 할 수 있기 때문에 프레임 워크가 마음에 들지만 구성 요소 간 통신시 일부 구성 요소 기반 디자인에서 발생하는 문제는 없습니다. 나는 일을 잠시 멈추기 위해 척하는 것을 싫어합니다. 엔터티 구성 요소 디자인을 제거하지 않고 게임에 게임 상태를 추가 할 수있는 방법이 있습니까? 게임 상태 예제가 실제로 내 프레임 워크에 맞고 뭔가 빠졌습니까?

편집 : 내 프레임 워크를 충분히 설명하지 않았을 수 있습니다. 내 구성 요소는 단지 데이터입니다. 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를 공유하면 실제로 동일한 객체입니다. 이 설명이 프레임 워크를 덜 혼란스럽게 만들었기를 바랍니다.

답변:


4

게시 한 링크를 읽지 않았 음을 인정합니다. 편집하고 제공된 링크를 읽은 후 내 위치가 변경되었습니다. 아래는 이것을 반영합니다.


전통적인 의미에서 게임 상태에 대해 걱정해야한다는 것을 모르겠습니다. 개발 접근 방식을 고려, 각 시스템은 그들이 사실상 특정 있도록입니다 이다 게임의 상태 관리.

엔터티 시스템에서 구성 요소는 데이터 일뿐입니다. 국가도 마찬가지입니다. 가장 간단한 형태로, 그것은 단지 플래그 일뿐입니다. 상태를 구성 요소로 작성하고 시스템에서 해당 구성 요소의 데이터를 소비하고 해당 구성 요소 내의 상태 (플래그)에 반응 할 수 있도록 허용하면 각 시스템 자체에 상태 관리를 구축하게됩니다.

AppHub 예제와 같은 관리 시스템은 개발 패러다임에 잘 적용되지 않는 것 같습니다. 다른 시스템을 캡슐화하는 수퍼 시스템을 만들면 데이터와 논리를 분리하려는 목적을 무너 뜨리는 것 같습니다.

게임 상태를 명시 적으로 처리하지 않아도된다는 의미를 이해하는 데 도움이 될 수 있습니다.

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


내 편집 내용을 참조하십시오. 혼란스러워서 죄송합니다.
에바

새로운 발견 및 편집 내용을 반영하도록 업데이트되었습니다. 엔터티 시스템 구축에 더 많은 경험이있는 사람은 내가 경험 한 분야가 아니기 때문에 차임 할 것입니다.
Cypher

게임 상태가 변경 될 때 시스템을 제거하고 추가하는 것은 어떻습니까? 예를 들어, 게임을 일시 정지 할 때, 아마도 MovementSystem 또는 CollisionSystem은 필요하지 않지만 RenderSystem이 여전히 화면에 물건을 그리 길 원할 것입니다. 활성 시스템이 게임 상태를 나타낼 수 있습니까?
argenkiwi

0

상태는 객체에 적용되는 값입니다. 이름에서 알 수 있듯이 게임 상태는 '게임'오브젝트의 상태입니다. 해당 게임 오브젝트 또는 그 이상의 특정 구성 요소는 현재 상태를 추적하고 현재 상태를 용이하게하는 데 필요한 모든 오브젝트를 작성하거나 파괴합니다. 구성 요소는 단지 데이터이므로 관련 구성 요소의 인스턴스가 하나만있을 수 있지만이를 처리하려면 새로운 시스템이 필요합니다.

업데이트 구현 방법이 명확하지 않은 경우 일시 중지를 구현하는 방법에 대해서는 언급하기가 어렵습니다. 게임 객체가 게임이 일시 중지되었다고 표시하면 업데이트 이벤트를 내보내는 프로세스가 그렇게하지 않도록 선택할 수 있습니다. 게임 오브젝트가 업데이트 프로세스와 통신하는 방법은 사용자에게 달려 있습니다. 아마도 당신의 getRelevantObjects호출은 업데이터가 게임 객체를 찾도록 허용해야하며, 그 반대도 마찬가지입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.