วิธีจัดโครงสร้างสถานะเกมในระบบที่ยึดเอนทิตี / ส่วนประกอบ


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

}

การอัปเดตทั้งหมดในเกมของฉันเป็นไปตามเหตุการณ์ ฉันไม่ได้วนเหมือนพวกเขาที่เพียงแค่อัปเดตทุกอย่างในเวลาเดียวกัน

ฉันชอบเฟรมเวิร์กของฉันเพราะมันทำให้การเพิ่ม GameObjects ใหม่ง่ายขึ้น แต่ไม่มีปัญหาที่การออกแบบที่ใช้องค์ประกอบบางอย่างเกิดขึ้นเมื่อทำการสื่อสารระหว่างส่วนประกอบ ฉันเกลียดที่จะเชยมันเพื่อหยุดงานชั่วคราว มีวิธีที่ฉันสามารถเพิ่มสถานะเกมลงในเกมของฉันโดยไม่ลบการออกแบบส่วนประกอบหรือไม่? ตัวอย่างสถานะของเกมตรงกับกรอบงานของฉันจริงหรือไม่

แก้ไข: ฉันอาจไม่ได้อธิบายกรอบงานของฉันดีพอ ส่วนประกอบของฉันเป็นเพียงข้อมูล ถ้าฉันเข้ารหัสใน C ++ พวกเขาอาจจะเป็น structs นี่คือตัวอย่างหนึ่ง:

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


โปรดดูการแก้ไขของฉัน ขออภัยถ้าฉันสับสน
Eva

อัปเดตเพื่อสะท้อนการค้นพบใหม่และการแก้ไขของคุณ หวังว่าใครบางคนที่มีประสบการณ์มากขึ้นในการสร้างระบบเอนทิตีจะเข้ามาเพราะนี่ไม่ใช่พื้นที่ที่ฉันมีประสบการณ์มากมาย
Cypher

สิ่งที่เกี่ยวกับการลบและเพิ่มระบบเมื่อสถานะเกมเปลี่ยนไป? ตัวอย่างเช่นเมื่อคุณหยุดเกมชั่วคราวอาจไม่จำเป็นต้องใช้ MovementSystem หรือ CollisionSystem แต่คุณยังต้องการให้ RenderSystem ของคุณวาดสิ่งต่างๆบนหน้าจอ ระบบที่ใช้งานสามารถเป็นตัวแทนของรัฐเกมได้หรือไม่?
argenkiwi

0

State คือค่าที่ใช้กับวัตถุ สถานะของเกมตามชื่อที่แนะนำจะเป็นสถานะของวัตถุ 'เกม' วัตถุเกมนั้น - หรือมีแนวโน้มมากขึ้นเป็นองค์ประกอบเฉพาะในนั้น - จะติดตามสถานะปัจจุบันและสร้างหรือทำลายสิ่งที่วัตถุที่จำเป็นเพื่ออำนวยความสะดวกสถานะปัจจุบัน เนื่องจากส่วนประกอบของคุณเป็นเพียงข้อมูลคุณจะต้องมีระบบใหม่เพื่อจัดการกับสิ่งนี้แม้ว่าอาจมีเพียงอินสแตนซ์เดียวขององค์ประกอบที่เกี่ยวข้อง

เป็นการยากที่จะแสดงความคิดเห็นเกี่ยวกับวิธีที่คุณจะใช้การหยุดชั่วคราวเมื่อยังไม่ชัดเจนว่าคุณจะใช้การอัปเดตอย่างไร กระบวนการที่ปล่อยการอัปเดตเหตุการณ์สามารถเลือกที่จะไม่ทำเช่นนั้นได้หากวัตถุของเกมบอกว่าเกมนั้นหยุดชั่วคราว วัตถุเกมสื่อสารกับกระบวนการอัปเดตเป็นอย่างไรสำหรับคุณ บางทีการgetRelevantObjectsโทรของคุณควรอนุญาตให้ตัวอัปเดตสามารถค้นหาวัตถุเกมหรือกลับกันได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.