所以我在XNA中阅读了许多关于如何处理游戏状态的教程,对于我所读的每一篇教程,它都与其他教程不同。现在我想问一下,哪种方法更有效?我已经创建了我自己的ScreenManager,什么都没有,但我并不满意,因为它效率低下,因为我没有卸载任何未使用的内容。
我的问题是:管理屏幕及其内容的有效方法是什么?使用明矾罚款吗?还是.?
以下是我的当前代码:
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;
}
}
}
}发布于 2013-12-28 19:45:45
我不能肯定这一点(我需要培养我的XNA知识),但我可能会从DrawableGameComponent派生出该类,这样Update和Draw方法就会被重写(不仅仅是被命名为“更新”和“绘图”的方法),而且从该类派生出来可能会产生我不知道的其他后果;同样,我的XNA是相当基本的--对于一个拥有Update和Draw方法的类来说,从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>>,则可以更好地工作:
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实现变成如下所示:
private void Draw(SpriteBatch spriteBatch)
{
_gameScreenRenderer[ScreenState.Instance.CurrentState](spriteBatch);
}为您的Update方法实现类似的机制,您将只更新和呈现CurrentState的屏幕。
https://codereview.stackexchange.com/questions/38232
复制相似问题