WPF Uygulamalarında XNA Kullanımı

Sayfa güncel :
Sayfa oluşturma tarihi :

özet

WPF uygulamalarında XNA Framework'ün nasıl kullanılacağını açıklar.

WPF アプリケーションで XNA を使用する

Çalışma ortamı

Önkoşullar

Desteklenen XNA Sürümleri
  • 2.0
  • 3.0
Desteklenen Platformlar
  • Windows (XP SP2 veya üstü, Vista)
Windows Gerekli Köşe Gölgelendiricisi Sürümü 1.1
Windows Gerekli Pixel Shader Sürümü 1.1

Çalışma ortamı

peron

madde

DirectX kullanarak belirli bir denetimde görüntü oluşturmak için, bu denetimin pencere tanıtıcısını almanız gerekir. Ancak, Windows Form denetimlerinden farklı olarak, WPF denetimlerinin pencere tutamaçları yoktur (WPF'de denetimi yalnızca "çizerler").

Ancak, WPF, Windows Forms denetimlerini kullanmanıza olanak sağlayan "WindowsFormsHost" adlı bir denetim sağlar.

Bu yazıda, yukarıda gösterildiği gibi döndürüldüğü gibi bir çokgen çizme örneği oluşturacağız, ancak XNA'nın ayrıntılarını atlayacağım çünkü bunu açıklamak çok uzun olacak. Ben sadece WPF ve XNA arasındaki ilişkiden bahsedeceğim.

İlk olarak, bir WPF penceresi açın (bu örnekte, Window1.xaml) ve araç çubuğundan bir WindowsFormHost denetimi yerleştirin. Sağdaki kaydırıcı bir bonus.

WPF ウインドウデザイン

XAML üzerinde gerçekten biraz daha fazla çalışmam gerekiyor, ancak önce XNA'yı kullanmak için kontrolleri oluşturmam gerektiği için daha sonraya bırakacağım.

Projenize bir "Windows Forms" "Özel Denetimi" ekleyin. GraphicsDeviceControl adını bırakın.

Windows Forms のカスタムコントロールを追加

Önceden "Microsoft.Xna.Framework" referansını eklemeyi unutmayın. Ayrıca "Microsoft.Xna.Framework.Game" de var, ancak bu yalnızca oyun projesinde kullanılıyor, bu yüzden dahil etmeye gerek yok.

Managed DirectX の参照

Örnek kodu kısa tutmak için, XNA ile ilgili tüm programlar GraphicsDeviceControl.cs'da özetlenmiştir. Çok yönlü bir yazı stili değildir, bu yüzden lütfen uygulayın ve yeniden yazın.

GraphicsDeviceControl'ün tam kodu aşağıda gösterilmiştir (tasarımcı kısmı hariç). XNA'yı daha önce kullandıysanız, sıra dışı bir şey yapmadığını bilirsiniz. Çokgenin her zaman dönüyormuş gibi görünmesini sağlamak için bir Zamanlayıcı bileşeni kullanıyorum.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace XNAOnWPF
{
    /// <summary>
    /// グラフィックデバイスコントロール
    /// </summary>
    public partial class GraphicsDeviceControl : Control
    {
        /// <summary>
        /// グラフィックデバイス
        /// </summary>
        private GraphicsDevice device = null;

        /// <summary>
        /// エフェクト
        /// </summary>
        private BasicEffect effect = null;

        /// <summary>
        /// 頂点データ
        /// </summary>
        private VertexPositionColor[] vertices = new VertexPositionColor[3];
        /// <summary>
        /// 頂点データ
        /// </summary>
        public VertexPositionColor[] Vertices
        {
            get { return this.vertices; }
        }


        /// <summary>
        /// コンストラクタ
        /// </summary>
        public GraphicsDeviceControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// コントロールが作成されるとき
        /// </summary>
        protected override void OnCreateControl()
        {
            if (this.DesignMode == false)
            {
                try
                {
                    // デバイス作成
                    PresentationParameters pp = new PresentationParameters();
                    pp.SwapEffect = SwapEffect.Discard;
                    pp.BackBufferWidth = 300;
                    pp.BackBufferHeight = 300;
                    pp.EnableAutoDepthStencil = true;
                    pp.AutoDepthStencilFormat = DepthFormat.Depth16;
                    this.device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
                        DeviceType.Hardware, this.Handle, pp);

                    // 頂点データの設定
                    this.vertices[0] = new VertexPositionColor(
                        new Vector3(0.0f, -2.0f + (float)Math.Sqrt(3) * 3.0f, 0.0f),
                        new Microsoft.Xna.Framework.Graphics.Color(255, 0, 0));
                    this.vertices[1] = new VertexPositionColor(
                        new Vector3(3.0f, -2.0f, 0.0f),
                        new Microsoft.Xna.Framework.Graphics.Color(0, 255, 0));
                    this.vertices[2] = new VertexPositionColor(
                        new Vector3(-3.0f, -2.0f, 0.0f),
                        new Microsoft.Xna.Framework.Graphics.Color(0, 0, 255));

                    // 頂点定義
                    this.device.VertexDeclaration =
                        new VertexDeclaration(this.device, VertexPositionColor.VertexElements);

                    // エフェクト
                    this.effect = new BasicEffect(this.device, null);
                    this.effect.VertexColorEnabled = true;

                    // ビュー変換行列を設定
                    this.effect.View = Matrix.CreateLookAt(
                        new Vector3(0.0f, 0.0f, -10.0f),
                        new Vector3(0.0f, 0.0f, 0.0f),
                        Vector3.Up);

                    // 射影変換を設定
                    this.effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f), 1.0f, 1.0f, 100.0f);

                    // レンダリングステート設定
                    this.device.RenderState.CullMode = CullMode.None;
                    this.device.RenderState.AlphaBlendEnable = true;
                    this.device.RenderState.SourceBlend = Blend.SourceAlpha;
                    this.device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex.ToString());
                }
            }

            base.OnCreateControl();
        }

        /// <summary>
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            if (disposing)
            {
                if (this.device != null)
                {
                    this.device.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// 描画イベント
        /// </summary>
        /// <param name="pe"></param>
        protected override void OnPaint(PaintEventArgs pe)
        {
            this.Draw();

            base.OnPaint(pe);
        }

        /// <summary>
        /// 描画
        /// </summary>
        private void Draw()
        {
            if (this.device == null)
            {
                return;
            }

            this.device.Clear(Microsoft.Xna.Framework.Graphics.Color.DarkBlue);

            // ポリゴンを描画する
            this.effect.Begin();
            this.effect.Techniques[0].Passes[0].Begin();

            this.effect.World = Matrix.CreateRotationY((float)Environment.TickCount / 1000.0f);
            this.device.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.TriangleList, vertices, 0, 1);

            this.effect.Techniques[0].Passes[0].End();
            this.effect.End();

            this.device.Present();
        }

        /// <summary>
        /// タイマーイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_Tick(object sender, EventArgs e)
        {
            this.Draw();
        }
    }
}

Denetimi oluşturduğunuza göre, XAML'ye göz atalım. Oluşturduğumuz control'ü yerleştireceğimiz için root etiketine bir namespace ekleyeceğiz. Burada "xw" olarak tanımlanır.

<Window&nbsp;x:Class="ManagedDirectXOnWPF.Window1"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
&nbsp;&nbsp;&nbsp;&nbsp;Title="WPFウインドウ上でManaged DirectXを使用してポリゴン描画"
&nbsp;&nbsp;&nbsp;&nbsp;Height="338"&nbsp;Width="422"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xw="clr-namespace:ManagedDirectXOnWPF">
    <!-- 省略 -->
</Window>

Ardından, az önce yerleştirdiğiniz WindowsFormsHost denetiminin etiketini genişletin ve aşağıda gösterildiği gibi bir GraphicsDeviceControl ekleyin.

<my:WindowsFormsHost&nbsp;Name="windowsFormsHostManagedDirectX"&nbsp;Width="300"&nbsp;Height="300"
                    HorizontalAlignment="Left"&nbsp;VerticalAlignment="Top">
  <xw:GraphicsDeviceControl&nbsp;x:Name="GraphicsDeviceControl"&nbsp;/>
</my:WindowsFormsHost>

Bir "x:Name" sahip olmanız gerekmez, ancak örnek bunu bir kaydırıcıyla köşe verilerine erişmek için kullanır.

Bunu yaparsanız, örnekte gösterildiği gibi, WPF üzerinde çokgenlerin dönen bir çokgenle çizildiği bir sahne çalıştırabilirsiniz. Kaydırıcı ile erişim bir bonus, bu yüzden lütfen örnek verileri indirin ve kontrol edin.

Program, .NET Framework 3.0, en son DirectX çalışma zamanı ve Microsoft XNA Framework Yeniden Dağıtılabilir 2.0 gerektirir. Ek olarak, bir donanım gereksinimi olarak, "Pixel Shader 1.1 veya üstünü destekleyen bir grafik kartı" gereklidir.

Ayrıca, proje "Visual Studio 2008 Professional Edition" da oluşturulmuştur. Visual Studio 2008 için bir ortam hazırlayın.