【问题标题】:Monogame, Nez: Switching scenes, opening menuMonogame, Nez: 切换场景,打开菜单
【发布时间】:2017-07-27 18:12:29
【问题描述】:

我从 Monogame 和 Nez 库/引擎开始,但我正在努力打开菜单。我最初的想法是游戏将是一个场景类,另一个菜单。在 Esc 键上,我将 Core.scene 设置为菜单场景的新实例并记住原始场景。当菜单关闭时,我会将 Core.scene 设置回原来的那个。但是它不起作用;当一个场景被替换时,它就结束了,我无法恢复它。

所以我的问题是 - 我应该怎么做?显然我的设计有一些缺陷,但看不到正确的方法。打开菜单后,我想暂停游戏,显示菜单(可能切换几个菜单屏幕),然后在菜单关闭时取消暂停游戏并继续播放。

【问题讨论】:

    标签: c# monogame


    【解决方案1】:

    没有看到您的代码很难确定,但听起来您需要实现某种状态机。您需要能够保持对非活动/背景状态(窗口、游戏区等)的引用,以便在完成当前场景后恢复旧场景。

    一种方法——也是我个人最喜欢的一种——是使用有限状态机 (FSM) 模式。

    基本原则是有一堆对象(在这种情况下是场景),每次新场景开始时,您都会将该场景添加到堆栈顶部。场景结束后,将其从堆栈中移除(称为从堆栈中弹出)。

    听起来很复杂,但实际上使用起来非常简单。这是一个简单的例子:

    public class StateManager
    {
        private ContentManager Content { get; set; }
        private Game1 Game { get; set; }
        private Stack<Scene> sceneStack = new Stack<Scene>();
        private GameState currentScene;
        private GameState previousScene;
    
        public StateManager(ContentManager content, Game1 game)
        {
            // Pretty common to pass one or both of these instances around in your code.
            this.Game = game;
            this.Content = content;
        }
    
        public void AddScene(GameState newScene)
        {
            // This is the crucial part. We are saving the state of the old scene.
    
            if (currentScene != null)
                this.previousScene = currentScene;
    
            sceneStack.Push(newScene); // New scene is stacked 'on top' of the old one
            this.currentScene = newScene;
        }
    
        public void Draw(SpriteBatch spriteBatch)
        {
            // Out in Game1.cs we are calling this method from within
            // its own Draw() method.
    
            this.currentScene.Draw(spriteBatch);
        }
    }
    
    public class Scene : GameState
    {
        // Any state information needed for your scene like menus, terrain, etc
    }
    
    public abstract class GameState
    {
        // The base class for your Scenes which contains code relevant to all scene types.
        // You could go a step further and make an interface as well.
    
        public virtual void Draw(SpriteBatch spriteBatch)
        {
            // Logic to draw the game state. Textures, sprites, text, child
            // elements contained inside this state, etc.
        }
    }
    

    如您所见,通过此设置,StateManager(以及 Game1)的 Draw() 方法将始终主动渲染堆栈顶部的任何场景,这应该始终是使用 NewScene 添加的最新场景() 方法。

    RemoveScene() 方法非常简单,因为您基本上颠倒了您在 NewScene() 中所做的操作。调用 sceneStack.Pop();并且顶部场景被移除,将前一个场景设置为 currentScene 将确保堆栈上的最后一个场景将在它离开的地方继续。

    当然,您需要为真正的游戏添加更多逻辑,因为在一个场景中完成的事情可能会改变场景的外观或行为,但其中大部分都可以在Update() 方法(其工作原理与这里的 Draw() 方法基本相同)。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-08-06
      • 2014-02-28
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2021-01-25
      • 1970-01-01
      相关资源
      最近更新 更多