您的位置:首页 > 其它

SilverXna初体验:基本游戏框架——古老的三段式

2011-09-01 21:42 267 查看
今年上半年,微软Silverlight5 Beta发布,随之而来的是更多的惊喜与更加亮眼的新特性。

其中最令我在意的一点便是针对Xna 3D API的支持,虽然目前Silverlight5 Beta版中的Xna还只是完整Xna框架中的一个轻量子集,但自此之后web3D已再不是遥不可及的抽象概念~

本节我们就以一个古老的三段式框架为例,看Silverlight如何帮我们将Xna实实在在的嵌入到网页中 ^ ^

Silverlight中Xna 3D API的调用,以硬件加速为起始,以DrawingSurface为基础容器,因此我们首先要做的便是对这两者的显示支持。

1.在宿主网页中添加硬件加速支持。只需在Silverlight插件标签内嵌入如下代码即可 ^ ^

<param name="EnableGPUAcceleration" value="true" />
2.Silverlight主页面MainPage.xaml中添加一个DrawingSurface元素。

<Grid x:Name="LayoutRoot" Background="White">
<DrawingSurface Name ="_GameSurface"/>
</Grid>
之后,只需为我们的_GameSurface注册一个Draw事件,便可在其函数体中获取3D设备并进行绘制了,相应方法的调用几乎跟Xna环境下一模一样。就好像下面这样:

void _GameSurface_Draw(object sender, DrawEventArgs e)
{
// 清空渲染表面
e.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer,
Color.Transparent, 1.0f, 0);

// 绘制图形
e.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

// 强制重绘
e.InvalidateSurface();
}
用过Xna的朋友,看上面的代码是不是感觉挺眼熟?呵呵~

这里,为提高代码的重用性,我们仿Xna下的Game类,创建一个专属于Silverlight环境的SilverGame~

/*-------------------------------------

代码清单:SilverGame.cs
来自:http://www.cnblogs.com/kenkao

-------------------------------------*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Silverlight;

namespace Microsoft.Xna.Framework
{
public class SilverGame
{
/// <summary>
/// 初始GraphicsDeviceManager
/// </summary>
public GraphicsDeviceManager Graphics
{
get
{
return GraphicsDeviceManager.Current;
}
}

/// <summary>
/// Xna3D图形设备GraphicsDevice
/// </summary>
GraphicsDevice _GraphicsDevice;
public GraphicsDevice GraphicsDevice
{
get
{
if (_GraphicsDevice == null)
return GraphicsDeviceManager.Current.GraphicsDevice;
else
return _GraphicsDevice;
}
set
{
_GraphicsDevice = value;
}
}

/// <summary>
/// 渲染表面尺寸
/// </summary>
Vector2 _ActualSize;
public Vector2 ActualSize
{
get
{
return _ActualSize;
}
set
{
_ActualSize = value;
}
}

/// <summary>
/// 渲染表面DrawingSurface
/// </summary>
DrawingSurface _GameSurface;
public DrawingSurface GameSurface
{ get { return _GameSurface; } }

/// <summary>
/// 重置GraphicsDevice
/// </summary>
/// <param name="graphicsDevice"></param>
void ResetDevice(GraphicsDevice graphicsDevice)
{ _GraphicsDevice = graphicsDevice; }

/// <summary>
/// 重置渲染表面尺寸
/// </summary>
/// <param name="actualSize"></param>
void ResetActualSize(Vector2 actualSize)
{ _ActualSize = actualSize; }

/// <summary>
/// 构造方法
/// </summary>
/// <param name="GameSurface">所关联的渲染表面</param>
public SilverGame(DrawingSurface GameSurface)
{
_GameSurface = GameSurface;

_ActualSize = new Vector2((float)_GameSurface.ActualWidth, (float)_GameSurface.ActualHeight);
// 自动为渲染表面关联必要的事件
_GameSurface.Loaded += new RoutedEventHandler(_GameSurface_Loaded);
_GameSurface.Unloaded += new RoutedEventHandler(_GameSurface_Unloaded);
_GameSurface.Draw += new EventHandler<DrawEventArgs>(_GameSurface_Draw);
_GameSurface.SizeChanged += new SizeChangedEventHandler(_GameSurface_SizeChanged);
// 虚函数调用——初始化
this.Initialize();
}

void _GameSurface_Loaded(object sender, RoutedEventArgs e)
{
// 虚函数调用——加载资源
this.LoadContent();
}

void _GameSurface_Unloaded(object sender, RoutedEventArgs e)
{
// 虚函数调用——释放资源
this.UnloadContent();
}

void _GameSurface_SizeChanged(object sender, SizeChangedEventArgs e)
{
// 渲染表面大小改变时自动重置其尺寸
Size s = e.NewSize;
this.ResetActualSize(new Vector2((float)s.Width, (float)s.Height));
}

void _GameSurface_Draw(object sender, DrawEventArgs args)
{
// 重置图形设备
this.ResetDevice(args.GraphicsDevice);
// 虚函数调用——更新
this.Update(args.DeltaTime, args.TotalTime);
// 虚函数调用——渲染
this.Draw(args.DeltaTime, args.TotalTime);
// 强制重绘
args.InvalidateSurface();
}

//----一系列虚函数,供子类重写----//

public virtual void Initialize()
{ }

public virtual void LoadContent()
{ }

public virtual void UnloadContent()
{ }

public virtual void Update(TimeSpan DeltaTime, TimeSpan TotalTime)
{ }

public virtual void Draw(TimeSpan DeltaTime, TimeSpan TotalTime)
{ }
}
}
功能上还相当简单,不过没关系,后续我们会以它为基础,为整个工程添枝加叶 ^ ^

值得一提的是,SilverGame中对于已持有的Xna3D设备GraphicsDevice的处理方式。

工程构建之初,Silverlight体系会自动提供一个静态的图形设备,用于加载或生成诸如特效、纹理等资源,我们可以通过GraphicsDeviceManager.Current.GraphicsDevice获得。

而绘制过程中,处于DrawingSurface内部安全机制考虑,我们必须使用从事件体DrawEventArgs中获取的GraphicsDevice引用进行图形绘,如果此时再使用原来的静态设备进行绘制,将被视作非法操作~

SilverGame的处理方式使得这一过程对外透明化,用户通过GraphicsDevice属性获取到的图形设备将永远是合法的图形设备 ^ ^

SilverGame构建完毕之后,是工程范例的第三步:

3.引入SilverGame类,在此基础上派生其子类Game,作为游戏的主逻辑框架。

/*-------------------------------------

代码清单:Game.cs
来自:http://www.cnblogs.com/kenkao

-------------------------------------*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Silverlight;

namespace SilverXna
{
public class Game : SilverGame
{

public Game(DrawingSurface GameSurface)
: base(GameSurface)
{ }

public override void Initialize()
{
base.Initialize();
}

public override void LoadContent()
{
base.LoadContent();
}

public override void UnloadContent()
{
base.UnloadContent();
}

public override void Update(TimeSpan DeltaTime, TimeSpan TotalTime)
{
base.Update(DeltaTime, TotalTime);
}

public override void Draw(TimeSpan DeltaTime, TimeSpan TotalTime)
{
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(100, 149, 237, 255), 1.0f, 0);

base.Draw(DeltaTime, TotalTime);
}
}
}
与标准的Xna工程同样的处理手法,呵呵~ 之后是最后一步:

4.派生子类与主页面中的DrawingSurface进行关联~

/*-------------------------------------

代码清单:MainPage.xaml.cs
来自:http://www.cnblogs.com/kenkao

-------------------------------------*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Silverlight;

namespace SilverXna
{
public partial class MainPage : UserControl
{
Game _Game;
public MainPage()
{
InitializeComponent();
_Game = new Game(_GameSurface);
}
}
}
这样,一个无限复用的SilverXna框架就诞生了。结构仿Xna工程框架,古老而经典的三段式 ^ ^

来看效果:

SilverGame.cs

/*-------------------------------------

代码清单:SilverGame.cs
来自:http://www.cnblogs.com/kenkao

-------------------------------------*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Graphics;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Microsoft.Xna.Framework
{
public class SilverGame
{
/// <summary>
/// 初始GraphicsDeviceManager
/// </summary>
public GraphicsDeviceManager Graphics
{
get
{
return GraphicsDeviceManager.Current;
}
}

/// <summary>
/// Xna3D图形设备GraphicsDevice
/// </summary>
GraphicsDevice _GraphicsDevice;
public GraphicsDevice GraphicsDevice
{
get
{
return GraphicsDeviceManager.Current.GraphicsDevice;
}
set
{
_GraphicsDevice = value;
}
}

ContentManager _Content;
public ContentManager Content
{ get { return _Content; } }

/// <summary>
/// 渲染表面尺寸
/// </summary>
Vector2 _ActualSize;
public Vector2 ActualSize
{
get
{
return _ActualSize;
}
set
{
_ActualSize = value;
}
}

/// <summary>
/// 渲染表面DrawingSurface
/// </summary>
DrawingSurface _GameSurface;
public DrawingSurface GameSurface
{ get { return _GameSurface; } }

/// <summary>
/// 重置渲染表面尺寸
/// </summary>
/// <param name="actualSize"></param>
void ResetActualSize(Vector2 actualSize)
{ _ActualSize = actualSize; }

/// <summary>
/// 构造方法
/// </summary>
/// <param name="GameSurface">所关联的渲染表面</param>
public SilverGame(DrawingSurface GameSurface)
{
_GameSurface = GameSurface;
_Content = new ContentManager(this);
_ActualSize = new Vector2((float)_GameSurface.ActualWidth, (float)_GameSurface.ActualHeight);
// 自动为渲染表面关联必要的事件
_GameSurface.Loaded += new RoutedEventHandler(_GameSurface_Loaded);
_GameSurface.Unloaded += new RoutedEventHandler(_GameSurface_Unloaded);
_GameSurface.Draw += new EventHandler<DrawEventArgs>(_GameSurface_Draw);
_GameSurface.SizeChanged += new SizeChangedEventHandler(_GameSurface_SizeChanged);
// 虚函数调用——初始化
this.Initialize();
}

void _GameSurface_Loaded(object sender, RoutedEventArgs e)
{
// 虚函数调用——加载资源
this.LoadContent();
}

void _GameSurface_Unloaded(object sender, RoutedEventArgs e)
{
// 虚函数调用——释放资源
this.UnloadContent();
}

void _GameSurface_SizeChanged(object sender, SizeChangedEventArgs e)
{
// 渲染表面大小改变时自动重置其尺寸
Size s = e.NewSize;
this.ResetActualSize(new Vector2((float)s.Width, (float)s.Height));
}

void _GameSurface_Draw(object sender, DrawEventArgs args)
{
// 虚函数调用——更新
this.Update(args.DeltaTime, args.TotalTime);
// 虚函数调用——渲染
this.Draw(args.DeltaTime, args.TotalTime);
// 强制重绘
args.InvalidateSurface();
}

//----一系列虚函数,供子类重写----//

public virtual void Initialize()
{ }

public virtual void LoadContent()
{ }

public virtual void UnloadContent()
{ }

public virtual void Update(TimeSpan DeltaTime, TimeSpan TotalTime)
{ }

public virtual void Draw(TimeSpan DeltaTime, TimeSpan TotalTime)
{ }
}
}
更新说明:

1.原有的基于DrawingSurface的GraphicsDevice安全机制消除,统一由GraphicsDeviceManager.Current.GraphicsDevice获取即可。

2.片尾列出的dll库无需再从外部引用,直接由Silverlight系统环境即可找到该程序集。

3.命名空间有变动,取消了Microsoft.Xna.Framework.Silverlight明明空间,添加了System.Windows.Xna程序集。

4.其他变动请参见Silverlight RC官方的最新说明文档~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: