1.概述和场景管理
一.概述
我研究的比较深入的引擎有《Professional XNA Game Programming》(以后简称《ProfessionalXNA》)中介绍的引擎,http://www.innovativegames.net/blog/2009/10/18/innovation-engine-roadmap-2009-2010/上的引擎教程,这个教程在讲到编辑器时停了好长时间,与2009年10月又开始连载,好像作者重新进行了构思,并给出了路线图,使用Farseer Physics实现2D物理引擎,JigLibX实现3D物理引擎。本引擎主要参考了TXnaEngine,http://txnage.codeplex.com/,截止到2009年11月,最新版本是0.5.3。稍微研究过的是QuickStart Engine (3D Game Engine for XNA),http://quickstartengine.codeplex.com/,Ox Game Engine for XNA,http://oxgameengine.codeplex.com/,XEN,http://xen.codeplex.com/。
对引擎的架构来说,我觉得成熟的开源引擎Ogre,http://ogre3d.cn/wiki/非常值得参考,虽然它并不是用XNA编写的,TxnaEngine引擎的基本框架与Ogre的非常相像。
至于不开源的商业引擎,可以有试用版下载的是visual3d,http://www.visual3d.net/和NeoAxisEngine,http://www.neoaxisgroup.com/,这也是我想实现的最终目标。
![NeoAxisEngine截图](images/soft/MySoft/NeoAxisEngine.jpg)
NeoAxisEngine场景编辑器
二.场景管理
一个游戏通常有多个屏幕,首先要解决的问题就是如何管理这些屏幕。一个很好的例子就是XNA官方网站上的场景管理,http://creators.xna.com/en-US/samples/gamestatemanagement,具体的教程可见例子的注释或者《XNA 3.0 Game Programming Recipes》(以后简称《XNARecipes》)中的3.6 创建2D菜单界面,我的引擎就是参考这个例子的。
核心思想就是先创建一个代表屏幕的Scene类(在官网的例子中叫做GameScreen类),这个类包含所有场景中绘制的对象等,再创建一个SceneManager类(在官网的例子中叫做ScreenManager类)管理Scene的集合,实现添加、移除屏幕等功能,而SceneManager类从DrawableGameComponent继承,这样在引擎主类中就可以自动调用SceneManager类的Draw(),Update()等方法了,使用DrawableGameComponent的方法可参考《XNARecipes》中的1.7 使用GameComponents。
下面是SceneManagement命名空间中的Scene类的代码:
namespace StunEngine.SceneManagement
...{
/**//// <summary>
/// 表示屏幕所处状态的枚举
/// </summary>
public enum ScreenState
...{
TransitionOn,
Active,
TransitionOff,
Hidden,
}
![]()
/**//// <summary>
/// 这是SceneNode得数据包含容器。一个Scene是根据绘制时间分组的对象的集合
/// Scene对象是自我包含的,这样属于这个场景的SceneNodes不会和其他场景中的nodes发生交互
/// 一个游戏可以包含一个或多个scene,但只有一个是激活的,只绘制属于它的nodes。
/// </summary>
public abstract class Scene
...{
成员变量和构造函数#region 成员变量和构造函数
![]()
protected StunXnaGE engine;
![]()
/**//// <summary>
/// 存储这个场景中的SceneNode的集合
/// </summary>
private List<SceneNode> nodes;
![]()
/**//// <summary>
/// 是否正在退出
/// </summary>
bool isExiting = false;
![]()
/**//// <summary>
/// 其他屏幕是否处在激活状态
/// </summary>
bool otherScreenHasFocus;
![]()
/**//// <summary>
/// 场景管理器
/// </summary>
SceneManager sceneManager;
![]()
/**//// <summary>
/// 这个场景拥有的UI管理器
/// </summary>
UIManager uiManager;
![]()
/**//// <summary>
/// scene的ID
/// </summary>
internal int sceneId;
![]()
/**//// <summary>
/// scene的名称
/// </summary>
private string name;
![]()
/**//// <summary>
/// 是否显示光标
/// </summary>
private bool isShowMouse;
![]()
/**//// <summary>
/// 是否弹出窗口
/// </summary>
bool isPopup = false;
![]()
/**//// <summary>
/// 淡入持续的时间
/// </summary>
TimeSpan transitionOnTime = TimeSpan.Zero;
![]()
/**//// <summary>
/// 淡出持续的时间
/// </summary>
TimeSpan transitionOffTime = TimeSpan.Zero;
![]()
/**//// <summary>
/// 淡入淡入过程中所处的位置
/// </summary>
float transitionPosition = 1;
![]()
//屏幕刚创建时处于淡入状态
ScreenState screenState = ScreenState.TransitionOn;
![]()
/**//// <summary>
/// 创建一个新scene对象
/// </summary>
/// <param name="engine">引擎</param>
/// <param name="name">scene的名称</param>
public Scene(StunXnaGE engine, string name) : this(engine, 0, name) ...{ }
![]()
/**//// <summary>
/// 创建一个新scene对象
/// </summary>
/// <param name="engine">引擎</param>
/// <param name="name">scene的名称</param>
/// <param name="aproxNodes">初始化nodes集合</param>
public Scene(StunXnaGE engine, string name, int aproxNodes) : this(engine, 0, name, aproxNodes) ...{ }
![]()
/**//// <summary>
/// 给定ID创建一个新Scene对象。
/// 调用者必须保证ID唯一
/// </summary>
/// <param name="engine">引擎</param>
/// <param name="sceneId">ID</param>
/// <param name="name">名称</param>
internal Scene(StunXnaGE engine, ushort sceneId, string name) : this(engine, sceneId, name, 255) ...{ }
![]()
/**//// <summary>
/// 使用一个给定ID创建一个新Scene对象。
/// 调用者必须保证ID唯一
/// </summary>
/// <param name="engine">引擎</param>
/// <param name="sceneId">ID</param>
/// <param name="name">名称</param>
/// <param name="aproximateNodes">估计的节点数量</param>
internal Scene(StunXnaGE engine, ushort sceneId, string name, int aproximateNodes)
...{
this.sceneId = sceneId;
this.name = name;
this.engine = engine;
this.sceneManager = engine.SceneManager;
this.isShowMouse = true;
uiManager = new UIManager(engine,this);
this.nodes = new List<SceneNode>(aproximateNodes);
}
![]()
private Scene() ...{ }
![]()
#endregion
![]()
属性#region 属性
![]()
/**//// <summary>
/// 获取这个场景拥有的uiManager
/// </summary>
public UIManager UiManager
...{
get ...{ return uiManager; }
}
![]()
/**//// <summary>
/// 获取这个屏幕所属的场景管理器
/// </summary>
public SceneManager SceneManager
...{
get ...{ return sceneManager; }
internal set ...{ sceneManager = value; }
}
![]()
/**//// <summary>
/// 检查当前屏幕是否被激活可以接受用户输入。
/// </summary>
public bool IsActive
...{
get
...{
return !otherScreenHasFocus &&
(screenState == ScreenState.TransitionOn ||
screenState == ScreenState.Active);
}
}
![]()
/**//// <summary>
/// 返回scene中的node数量
/// </summary>
public int Nodes ...{ get ...{ return nodes.Count; } }
![]()
/**//// <summary>
/// 获取当前屏幕变换的位置,从0(完全激活,没有转换)到1(转换到完全没有)。
/// </summary>
public float TransitionPosition
...{
get ...{ return transitionPosition; }
protected set ...{ transitionPosition = value; }
}
![]()
/**//// <summary>
/// 返回scene的ID.
/// </summary>
public int ID ...{ get ...{ return sceneId; } }
![]()
/**//// <summary>
/// 当一个屏幕在另一个之上时,第一个屏幕会淡出给新的屏幕留出位置
/// 这个属性表示这个屏幕是否是一个弹出屏幕
/// </summary>
public bool IsPopup
...{
get ...{ return isPopup; }
protected set ...{ isPopup = value; }
}
![]()
/**//// <summary>
/// 获取或设置是否显示光标
/// </summary>
public bool IsShowMouse
...{
get ...{ return isShowMouse; }
set ...{ isShowMouse = value; }
}
![]()
/**//// <summary>
/// 返回scene的名称
/// </summary>
public string Name ...{ get ...{ return name; } }
![]()
/**//// <summary>
/// 有两个原因屏幕会淡出。
/// 有可能它暂时离开为另一个屏幕留出位置,或者就是退出。
/// 这个属性表示屏幕是否在退出:
/// 如果是,屏幕会在淡出结束后移除自己。
/// </summary>
public bool IsExiting
...{
get ...{ return isExiting; }
protected internal set ...{ isExiting = value; }
}
![]()
/**//// <summary>
/// 获取或设置屏幕淡出持续的时间
/// </summary>
public TimeSpan TransitionOffTime
...{
get ...{ return transitionOffTime; }
protected set ...{ transitionOffTime = value; }
}
![]()
/**//// <summary>
/// 获取当前转换的alpha值,从255 (完全激活,没有转换)到0(转换到完全没有)。
/// </summary>
public byte TransitionAlpha
...{
get ...{ return (byte)(255 - TransitionPosition * 255); }
}
![]()
![]()
/**//// <summary>
/// 获取当前屏幕状态。
/// </summary>
public ScreenState ScreenState
...{
get ...{ return screenState; }
protected set ...{ screenState = value; }
}
![]()
/**//// <summary>
/// 获取或设置屏幕淡入的时间
/// </summary>
public TimeSpan TransitionOnTime
...{
get ...{ return transitionOnTime; }
set ...{ transitionOnTime = value; }
}
#endregion
![]()
虚拟方法#region 虚拟方法
![]()
/**//// <summary>
/// 加载素材
/// </summary>
public virtual void LoadContent() ...{ }
![]()
![]()
/**//// <summary>
/// 清除素材
/// </summary>
public virtual void UnloadContent() ...{ }
![]()
![]()
public virtual void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
...{
this.otherScreenHasFocus = otherScreenHasFocus;
![]()
//如果处于Exiting过程中
if (isExiting)
...{
// 如果此屏幕已经被移除,则它的状态应为TransitionOff
screenState = ScreenState.TransitionOff;
![]()
if (!UpdateTransition(gameTime, transitionOffTime, 1))
...{
// 当变换结束时,移除此屏幕
SceneManager.RemoveScene(this);
}
}
else if (coveredByOtherScreen)
...{
// 如果这个屏幕被其他屏幕覆盖,它应该处于TransitionOff状态
if (UpdateTransition(gameTime, transitionOffTime, 1))
...{
// 仍处于淡出状态
screenState = ScreenState.TransitionOff;
}
else
...{
// 否则淡出结束
screenState = ScreenState.Hidden;
}
}
else
...{
// 否则此屏幕仍处于淡入过程,结束后才能激活
if (UpdateTransition(gameTime, transitionOnTime, -1))
...{
// 仍处于淡入过程
screenState = ScreenState.TransitionOn;
}
else
...{
// 淡入过程结束!
screenState = ScreenState.Active;
}
}
![]()
// 更新此场景中所有非UISceneNode类型的SceneNode
foreach (SceneNode node in nodes)
node.Update(gameTime);
![]()
![]()
// 更新此场景中所有UISceneNode类型的SceneNode
//
if (this == sceneManager.ActiveScene)
...{
foreach (UISceneNode node in UiManager.UiElements)
node.Update(gameTime);
}
}
![]()
/**//// <summary>
/// 更新屏幕变换位置的辅助类
/// </summary>
bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
...{
// 淡入淡出过程持续到的位置
float transitionDelta;
![]()
if (time == TimeSpan.Zero)
transitionDelta = 1;
else
transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds /
time.TotalMilliseconds);
![]()
// 更新淡入淡出的位置
transitionPosition += transitionDelta * direction;
![]()
// 是否已经在淡入淡出过程的最后?
if (((direction < 0) && (transitionPosition <= 0)) ||
((direction > 0) && (transitionPosition >= 1)))
...{
transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
return false;
}
![]()
// 否则仍处于淡入淡出过程中
return true;
}
![]()
![]()
public virtual void Draw(GameTime gameTime)
...{
![]()
//绘制所有非UISceneNode类型的节点
foreach (RenderableSceneNode node in nodes)
node.Draw(gameTime);
![]()
//绘制所有UISceneNode类型的节点
uiManager.Draw(gameTime);
}
![]()
/**//// <summary>
/// 让屏幕可以接受用户输入。不同于Update,这个方法只在激活的屏幕中调用。
/// </summary>
public virtual void HandleInput() ...{ }
![]()
#endregion
![]()
![]()
公有方法#region 公有方法
![]()
/**//// <summary>
/// 告知屏幕离开,不同于SceneManager.RemoveScene方法,SceneManager.RemoveScene方法会立即移除屏幕
/// 这个方法让屏幕根据TransitionOffTime逐渐透明化的离开
/// </summary>
public void ExitScreen()
...{
if (TransitionOffTime == TimeSpan.Zero)
...{
// 如果TransitionOffTime为0,则移除这个屏幕
SceneManager.RemoveScene(this);
}
else
...{
// 否则仍处于淡出状态,当淡出结束后才能移除这个屏幕
isExiting = true;
}
}
![]()
/**//// <summary>
/// 在scene添加一个新node
/// </summary>
/// <param name="newNode"></param>
public void AddNode(SceneNode newNode)
...{
if (engine.GraphicsDevice.IsDisposed)
return;
![]()
newNode.Scene = this;
//如果是UI控件则添加到UIManager的UIElement集合中
if (newNode is UISceneNode)
...{
UISceneNode element = (UISceneNode)newNode;
element.UIManager = this.uiManager;
element.Initialize();
uiManager.AddElement(element);
}
//否则添加到nodes集合中
else
...{
nodes.Insert(0, newNode);
newNode.Initialize();
}
}
![]()
/**//// <summary>
/// 从场景中移除一个node
/// </summary>
/// <param name="node"></param>
public void RemoveNode(SceneNode node)
...{
nodes.Remove(node);
}
![]()
#endregion
}
}
其中叫做uiManager的类管理所有2D控件,下面会讲到。其他东西注释中已经写得很清楚了。
然后是SceneManager类的代码:
namespace StunEngine.SceneManagement
...{
/**//// <summary>
/// SceneManager负责管理一个scene集合,创建,添加,初始化scene对象。
/// 它还负责更新和绘制当前scene
/// </summary>
public sealed class SceneManager : DrawableGameComponent
...{
构造函数和成员变量#region 构造函数和成员变量
![]()
private StunXnaGE engine;
![]()
/**//// <summary>
/// 所有scene的集合
/// </summary>
List<Scene> scenes = new List<Scene>();
![]()
/**//// <summary>
/// scene集合的副本
/// </summary>
List<Scene> scenesToUpdate = new List<Scene>();
![]()
/**//// <summary>
/// 当前激活的屏幕
/// </summary>
Scene activeScene;
![]()
/**//// <summary>
/// 存储scene名称和ID的Dictionary
/// </summary>
private Dictionary<string, int> sceneIdForNames = new Dictionary<string, int>();
![]()
/**//// <summary>
/// 初始的sceneId
/// </summary>
private int sceneId = 0;
![]()
/**//// <summary>
/// 是否已经初始化
/// </summary>
bool isInitialized;
![]()
private SceneManager() : base(null) ...{ }
![]()
/**//// <summary>
/// 创建一个新SceneManager对象。
/// </summary>
/// <param name="engine"></param>
internal SceneManager(StunXnaGE engine)
: base(engine)
...{
this.engine = engine;
}
![]()
#endregion
![]()
属性#region 属性
![]()
/**//// <summary>
/// 获取当前激活的scene
/// </summary>
public Scene ActiveScene
...{
get ...{ return activeScene; }
set ...{ activeScene = value; }
}
![]()
/**//// <summary>
/// Scene索引器
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Scene this[int index] ...{ get ...{ return scenes[index]; } }
![]()
/**//// <summary>
/// 返回Scene对象数量
/// </summary>
public int Scenes ...{ get ...{ return scenes.Count; } }
![]()
/**//// <summary>
/// 获取是否显示光标
/// </summary>
/// <returns>Bool</returns>
public bool isShowMouseCursor
...{
get
...{
return ((scenes.Count > 0) && (activeScene.IsShowMouse == true));
}
}
![]()
#endregion
![]()
DrawableGameComponent重载方法#region DrawableGameComponent重载方法
/**//// <summary>
/// 初始化SCM
/// </summary>
public override void Initialize()
...{
base.Initialize();
isInitialized = true;
}
![]()
protected override void LoadContent()
...{
// 让所有屏幕加载内容
foreach (Scene scene in scenes)
...{
scene.LoadContent();
}
}
![]()
/**//// <summary>
/// 移除内容
/// </summary>
protected override void UnloadContent()
...{
// // 让所有屏幕移除内容
foreach (Scene scene in scenes)
...{
scene.UnloadContent();
}
}
![]()
/**//// <summary>
/// 更新激活scene的节点
/// </summary>
/// <param name="gameTime"></param>
public override void Update(GameTime gameTime)
...{
// 创建一个屏幕集合的副本以防止添加或移除屏幕时可能产生的冲突
scenesToUpdate.Clear();
![]()
foreach (Scene scene in scenes)
scenesToUpdate.Add(scene);
![]()
bool otherScreenHasFocus = !Game.IsActive;
bool coveredByOtherScreen = false;
![]()
// 更新所有的scene
while (scenesToUpdate.Count > 0)
...{
// 将集合顶部的scene移除
Scene scene = scenesToUpdate[scenesToUpdate.Count - 1];
scenesToUpdate.RemoveAt(scenesToUpdate.Count - 1);
![]()
// 更新当前scene
scene.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
![]()
if (scene.ScreenState == ScreenState.TransitionOn ||scene.ScreenState == ScreenState.Active)
...{
//如果此屏幕是第一个激活屏幕,则处理它的自定义输入
if (!otherScreenHasFocus)
...{
scene.HandleInput();
otherScreenHasFocus = true;
}
// 如果这不是一个弹出scene,告知其下的屏幕它们被这个屏幕覆盖
if (!scene.IsPopup)
coveredByOtherScreen = true;
}
}
//只更新激活scene的控件
activeScene.UiManager.Update(gameTime);
}
![]()
/**//// <summary>
/// 绘制scene
/// </summary>
/// <param name="gameTime"></param>
public override void Draw(GameTime gameTime)
...{
engine.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, engine.backGroundColor, 1.0f, 0);
//----------------------------------
// 设置常用的RenderState
//----------------------------------
Game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
Game.GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
Game.GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.Zero;
Game.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
Game.GraphicsDevice.RenderState.AlphaTestEnable = true;
Game.GraphicsDevice.RenderState.AlphaSourceBlend = Blend.One;
![]()
#if DEBUG
if (Input.Keyboard.IsKeyDown(Keys.F9))
...{
Game.GraphicsDevice.RenderState.FillMode = FillMode.WireFrame;
Game.GraphicsDevice.RenderState.CullMode = CullMode.None;
}
else
...{
Game.GraphicsDevice.RenderState.FillMode = FillMode.Solid;
Game.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
}
#endif
![]()
//绘制scene集合中的所有scene
for(int i=0;i<scenes .Count ;i++)
...{
if (scenes[i].ScreenState == ScreenState.Hidden)
continue;
scenes[i].Draw(gameTime);
}
}
![]()
#endregion
![]()
公有方法#region 公有方法
![]()
/**//// <summary>
/// 根据scene的名称返回一个scene
/// </summary>
/// <param name="name">scene的名称</param>
/// <returns></returns>
public Scene GetSceneByName(string name)
...{
![]()
if (!sceneIdForNames.ContainsKey(name))
throw new KeyNotFoundException("给定的Scene名称不存在");
return scenes[sceneIdForNames[name]];
![]()
}
![]()
/**//// <summary>
/// 根据scene的ID返回一个scene
/// </summary>
/// <param name="sceneId">scene的ID</param>
/// <returns></returns>
public Scene GetSceneById(ushort sceneId)
...{
![]()
if (sceneId > scenes.Count)
throw new IndexOutOfRangeException("ID必须小于Scene对象的数量");
![]()
return scenes[sceneId - 1];
}
![]()
/**//// <summary>
/// 将一个scene添加到SceneManager中的scene集合
/// </summary>
/// <param name="scene">要添加的scene</param>
public void AddScene(Scene scene)
...{
![]()
if (sceneIdForNames.ContainsKey(scene.Name))
throw new InvalidOperationException("给定的Scene名称已经存在了");
![]()
scene.sceneId = sceneId++;
sceneIdForNames.Add(scene.Name, scene.sceneId);
![]()
scene.SceneManager = this;
scene.IsExiting = false;
![]()
// 如果图形设备已经建立,加载secne的内容
if (isInitialized)
...{
scene.LoadContent();
}
scenes.Add(scene);
![]()
//将最后加入的scene作为当前激活的scene
activeScene = scenes[scenes.Count - 1];
}
![]()
![]()
/**//// <summary>
/// 从集合中移除一个scene。通常需要使用Scene.ExitScreen方法替代直接调用这个方法
/// 这样才能实现淡出效果
/// </summary>
public void RemoveScene(Scene scene)
...{
// 如果图形设备已建立,则移除scene的内容
if (isInitialized)
...{
scene.UnloadContent();
}
![]()
sceneIdForNames.Remove(scene.Name);
scenes.Remove(scene);
scenesToUpdate.Remove(scene);
![]()
//将集合中的最后一个scene作为当前激活的scene
if(scenes.Count >0)
activeScene = scenes[scenes.Count - 1];
}
![]()
/**//// <summary>
/// 返回包含所有scene的数组
/// </summary>
public Scene[] GetScenes()
...{
return scenes.ToArray();
}
![]()
#endregion
}
}
最后只要在引擎主类中添加SceneManager类就可以了:
namespace StunEngine
...{
/**//// <summary>
/// 引擎主类
/// </summary>
public class StunXnaGE : Microsoft.Xna.Framework.Game
...{
构造函数和成员变量#region 构造函数和成员变量
![]()
private readonly SceneManager scm;
private GraphicsDeviceManager graphics;
![]()
/**//// <summary>
/// 绘制所有图像和文字的spriteBatch
/// </summary>
protected static SpriteBatch spriteBatch;
![]()
/**//// <summary>
/// 默认字体
/// </summary>
protected SpriteFont defaultFont;
![]()
Texture2D cursor;
![]()
/**//// <summary>
/// 相对于800*600分辨率的缩放因子
/// </summary>
private Vector2 screenScalingFactor;
![]()
/**//// <summary>
/// 用于spriteBatch的缩放矩阵,使图像和文字能根据当前分辨率自动调整大小
/// </summary>
private Matrix globalTransformation;
![]()
/**//// <summary>
/// 背景颜色
/// </summary>
internal Color backGroundColor;
![]()
/**//// <summary>
/// 是否需要改变设备设置
/// </summary>
public bool applyDeviceChanges=true;
![]()
用于计算fps的变量#region 用于计算fps的变量
/**//// <summary>
/// 此帧所用的时间,单位毫秒
/// </summary>
private static float elapsedTimeThisFrameInMs = 0.001f;
![]()
/**//// <summary>
/// 总时间,单位毫秒
/// </summary>
private static float totalTimeMs = 0;
![]()
/**//// <summary>
/// 这一秒的开始时刻
/// </summary>
private static float startTimeThisSecond = 0;
![]()
/**//// <summary>
/// 为了计算更精确,只计算1秒内的帧数,然后更新fpsLastSecond。
/// </summary>
private static int
frameCountThisSecond = 0,
totalFrameCount = 0,
fpsLastSecond = 60;
![]()
/**//// <summary>
/// Fps
/// </summary>
/// <returns>Int</returns>
public static int Fps
...{
get
...{
return fpsLastSecond;
}
}
![]()
/**//// <summary>
/// 经过10秒后的插值fps
/// </summary>
private static float fpsInterpolated = 100.0f;
![]()
/**//// <summary>
/// 总帧数
/// </summary>
/// <returns>Int</returns>
public static int TotalFrames
...{
get
...{
return totalFrameCount;
}
}
![]()
#endregion
![]()
/**//// <summary>
/// 创建一个引擎对象。
/// 用户无法创建这个类的实例,必须从这个类继承
/// 这个类继承自Microsoft.Xna.Framework.Game,使用方法和Game对象相同
/// </summary>
public StunXnaGE()
...{
Content.RootDirectory = "Content";
graphics = new GraphicsDeviceManager(this);
![]()
![]()
scm = new SceneManager(this);
this.Components.Add(scm);
![]()
backGroundColor = Color.Black ;
![]()
#if DEBUG
// 在debug模式中不限制垂直刷新率
graphics.SynchronizeWithVerticalRetrace = false;
this.IsFixedTimeStep = false;
#endif
}
![]()
#endregion
![]()
属性#region 属性
![]()
/**//// <summary>
/// 返回当前GraphicsDevice.VeiwPort
/// </summary>
public Viewport ViewPort;
![]()
/**//// <summary>
/// 获取背景颜色
/// </summary>
public Color BackGroundColor
...{
get ...{ return backGroundColor; }
set ...{ backGroundColor = value; }
}
![]()
/**//// <summary>
/// 获取图形设备管理器
/// </summary>
public GraphicsDeviceManager Graphics ...{ get ...{ return graphics; } }
![]()
/**//// <summary>
/// 获取场景管理器
/// </summary>
public SceneManager SceneManager ...{ get ...{ return scm; } }
![]()
/**//// <summary>
/// 获取绘制所有图像和文字的spriteBatch
/// </summary>
public static SpriteBatch SpriteBatch
...{
get ...{ return spriteBatch; }
}
![]()
/**//// <summary>
/// 获取默认字体
/// </summary>
public SpriteFont DefaultFont
...{
get ...{ return defaultFont; }
}
![]()
发布时间:2009/11/18 下午12:59:47 阅读次数:9144