首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GameState管理效率

GameState管理效率
EN

Code Review用户
提问于 2013-12-28 18:29:39
回答 1查看 250关注 0票数 3

所以我在XNA中阅读了许多关于如何处理游戏状态的教程,对于我所读的每一篇教程,它都与其他教程不同。现在我想问一下,哪种方法更有效?我已经创建了我自己的ScreenManager,什么都没有,但我并不满意,因为它效率低下,因为我没有卸载任何未使用的内容。

我的问题是:管理屏幕及其内容的有效方法是什么?使用明矾罚款吗?还是.?

以下是我的当前代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Menu
{
    public class ScreenManager
    {
        // Variables
        List<GameScreen> gameScreens = new List<GameScreen>();

        // Constructors
        public ScreenManager()
        {
            gameScreens.Add(new Splashscreen());
            gameScreens.Add(new Mainscreen());
            gameScreens.Add(new Playscreen());
            gameScreens.Add(new Pausescreen());
        }

        // Public Properties
        public List<GameScreen> Screens
        {
            get { return gameScreens; }
            set { gameScreens = value; }
        }

        // Public Methods
        public void Add(GameScreen screen)
        {
            gameScreens.Add(screen);
        }

        public void LoadContent(ContentManager Content)
        {
            foreach (GameScreen screen in gameScreens)
            {
                screen.LoadContent(Content);
            }
        }

        public void Update(GameTime gameTime)
        {
            foreach (GameScreen screen in gameScreens)
            {
                screen.Update(gameTime);
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            switch (ScreenState.Instance.CurrentState)
            {
                case State.Splashscreen:
                    gameScreens[0].Draw(spriteBatch);
                    break;
                case State.Menu:
                    gameScreens[1].Draw(spriteBatch);
                    break;
                case State.Play:
                    gameScreens[2].Draw(spriteBatch);
                    break;
                case State.Pause:
                    gameScreens[3].Draw(spriteBatch);
                    break;
            }
        }
    }
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2013-12-28 19:45:45

我不能肯定这一点(我需要培养我的XNA知识),但我可能会从DrawableGameComponent派生出该类,这样UpdateDraw方法就会被重写(不仅仅是被命名为“更新”和“绘图”的方法),而且从该类派生出来可能会产生我不知道的其他后果;同样,我的XNA是相当基本的--对于一个拥有UpdateDraw方法的类来说,从DrawableGameComponent派生出来是很自然的:这些方法名称不是偶然的。

更新

您的Update()方法正在循环遍历每个GameScreen,并对它们调用Update()

GameScreen屏幕in gameScreens) { screen.Update(gameTime);}

我认为这样做需要不必要的处理:为什么每次迭代时都需要更新启动屏幕和暂停屏幕呢?你这是在浪费周期。

绘图

您的Draw()方法更具选择性:

公开无效抽奖( gameScreens0.Draw(spriteBatch);spriteBatch) { switch (ScreenState.Instance.CurrentState) { case State.Splashscreen: case State.Splashscreen;case State.Menu: gameScreens1.Draw(spriteBatch);break;case State.Play: gameScreens2.Draw(spriteBatch);break;案例State.Pause: gameScreens3..Draw(spriteBatch);break;}}

我喜欢你在这里使用枚举,但我不喜欢你硬编码gameScreens索引。让我想想..。您正在将屏幕存储在List中,如下所示:

List gameScreens =新List();public ScreenManager() {gameScreens.Add(新屏幕());gameScreens.Add(新主屏幕());gameScreens.Add(新播放屏幕());gameScreens.Add(新Pausescreen())};

请允许我在这里打开一个挑剔的括号:

在构造时,我会使用一个接口,而不是List<GameScreen> gameScreens = new List<GameScreen>();,然后在列表中添加屏幕,并在一个语句中初始化所有内容:私有只读IList _gameScreens;public ScreenManager() { _gameScreens =新List {新的SplashScreen(),新的MainScreen(),新的PlayScreen(),新的PauseScreen() };}这允许_gameScreens私有字段为readonly,从而防止对列表的引用进行篡改。

该机制可以工作,但如果您利用IDictionary并将List<GameScreen> gameScreens转换为IDictionary<State, Action<SpriteBatch>>,则可以更好地工作:

代码语言:javascript
复制
private readonly IDictionary<State, Action<SpriteBatch>> _gameScreenRenderer;
private readonly GameScreen _splashScreen = new SplashScreen();
private readonly GameScreen _mainScreen = new MainScreen();
private readonly GameScreen _playScreen = new PlayScreen();
private readonly GameScreen _pauseScreen = new PauseScreen();

public ScreenManager()
{
    _gameScreenRenderer = new Dictionary<State, Action<SpriteBatch>>
                            {
                                { State.SplashScreen, sb => _splashScreen.Draw(sb) },
                                { State.MainScreen, sb => _mainScreen.Draw(sb) },
                                { State.PlayScreen, sb => _playScreen.Draw(sb) },
                                { State.PauseScreen, sb => _pauseScreen.Draw(sb) }
                            };
}

Action<SpriteBatch>是指向任何返回void并接受SpriteBatch参数的方法的委托;这里的方法是匿名的。

每个GameScreen都成为ScreenManager类的一个字段,没有必要将它们包含在任何类型的列表中。这样做会使您的Draw实现变成如下所示:

代码语言:javascript
复制
private void Draw(SpriteBatch spriteBatch)
{
    _gameScreenRenderer[ScreenState.Instance.CurrentState](spriteBatch);
}

为您的Update方法实现类似的机制,您将只更新和呈现CurrentState的屏幕。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/38232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档