zoukankan      html  css  js  c++  java
  • 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.0f0);
       
        
    // 绘制图形
        e.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 01);

        
    // 强制重绘
        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(100149237255), 1.0f0);

                
    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工程框架,古老而经典的三段式 ^ ^

    来看效果:

     

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

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

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

    >> 以下点击下载:

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

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

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

    以上,谢谢 ^ ^

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

    后记:

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

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

    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官方的最新说明文档~

  • 相关阅读:
    追踪路由信息
    Windows Server 2008 R2远程桌面服务安装配置和授权激活
    CentOS 7 下挂载NTFS盘及开机自动挂载
    functools 之 partial(偏函数)
    Flask-WTForms 简单使用
    Flask-Session 简单使用
    通过decorators = [,] 的形式给类中的所有方法添加装饰器
    Python __dict__属性详解
    面向对象的 __slots__
    related_name和related_query_name举例区别
  • 原文地址:https://www.cnblogs.com/kenkao/p/2162469.html
Copyright © 2011-2022 走看看