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

今年上半年,微软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工程框架,古老而经典的三段式 ^ ^

来看效果:

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

久违了的那片蓝色,只不过宿主窗口已不再WinForm,而是实实在在的WebPage ^ ^

(注:如果看不到效果,请执行 右击--->Silverlight配置--->权限--->允许站点权限 即可)

最后再提醒大家一点,SilverXna工程中用到的一系列3D数据类型,需要微软官方提供的数学库最为基本支撑,后续的范例默认情况下都需要首先对其引入~

>> 以下点击下载:

http://files.cnblogs.com/kenkao/Microsoft.Xna.Framework.Math.rar

>> Silverlight5 Beta环境搭建资源及微软官方范例下载:

http://space.cnblogs.com/group/topic/47416/

以上,谢谢 ^ ^

 

 

==========================================================

 

后记:

Silverlight5 RC版于同一天发布,惊喜来的太快,令人措手不及 ^ ^

以下是本节SilverGame对象的更新版本:

SilverXna初体验:基本游戏框架——古老的三段式 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官方的最新说明文档~

 

 

 

你可能感兴趣的:(框架)