การใช้ XNA ในโปรแกรมประยุกต์ WPF

ปรับปรุงหน้า :
วันที่สร้างเพจ :

สรุป

อธิบายวิธีการใช้เฟรมเวิร์ก XNA ในโปรแกรมประยุกต์ WPF

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

สภาพแวดล้อมในการทํางาน

ข้อกําหนดเบื้องต้น

รุ่น XNA ที่รองรับ
  • 2.0
  • 3.0
แพลตฟอร์มที่รองรับ
  • Windows (XP SP2 หรือใหม่กว่า, Vista)
Windows ต้องใช้เวอร์ชัน Vertex Shader 1.1
เวอร์ชัน Pixel Shader ที่จําเป็นของ Windows 1.1

สภาพแวดล้อมในการทํางาน

แท่น

สาร

เมื่อต้องการแสดงผลบนตัวควบคุมเฉพาะโดยใช้ DirectX คุณต้องรับที่จับหน้าต่างสําหรับตัวควบคุมนั้น อย่างไรก็ตาม ไม่เหมือนกับตัวควบคุม Windows ฟอร์ม ตัวควบคุม WPF ไม่มีที่จับหน้าต่าง (ใน WPF พวกเขาเพียงแค่ "วาด" ตัวควบคุม)

อย่างไรก็ตาม WPF มีตัวควบคุมที่เรียกว่า "WindowsFormsHost" ที่อนุญาตให้คุณใช้ตัวควบคุม Windows ฟอร์ม

ในบทความนี้ เราจะสร้างตัวอย่างการวาดรูปหลายเหลี่ยมขณะที่หมุนตามที่แสดงด้านบน แต่ฉันจะละเว้นรายละเอียดของ XNA เอง เนื่องจากจะยาวเกินไปที่จะอธิบาย ฉันจะพูดถึงความสัมพันธ์ระหว่าง WPF และ XNA

ขั้นแรก ให้เปิดหน้าต่าง WPF (ในกรณีนี้ Window1.xaml) และวางตัวควบคุม WindowsFormHost จากแถบเครื่องมือ แถบเลื่อนทางด้านขวาเป็นโบนัส

WPF ウインドウデザイン

ฉันจําเป็นต้องทํางานเพิ่มเติมเล็กน้อยใน XAML แต่ฉันจะปล่อยให้มันอยู่ในภายหลังเพราะฉันต้องสร้างตัวควบคุมเพื่อใช้ XNA ก่อน

เพิ่ม "Windows ฟอร์ม" "ตัวควบคุมแบบกําหนดเอง" ให้กับโครงการของคุณ ปล่อยให้ชื่อ GraphicsDeviceControl

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

อย่าลืมเพิ่มการอ้างอิง "Microsoft.Xna.Framework" ล่วงหน้า นอกจากนี้ยังมี "Microsoft.Xna.Framework.Game" แต่ใช้ในโครงการเฉพาะเกมดังนั้นจึงไม่จําเป็นต้องรวมไว้

Managed DirectX の参照

โปรแกรมที่เกี่ยวข้องกับ XNA ทั้งหมดจะสรุปเป็น GraphicsDeviceControl.cs ไม่ใช่รูปแบบการเขียนที่หลากหลายมากนัก ดังนั้นโปรดนําไปใช้และเขียนใหม่

รหัสแบบเต็มสําหรับ GraphicsDeviceControl แสดงอยู่ด้านล่าง (ยกเว้นส่วนของตัวออกแบบ) หากคุณเคยใช้ XNA คุณจะรู้ว่ามันไม่ได้ทําอะไรผิดปกติ ฉันกําลังใช้ส่วนประกอบ Timer เพื่อทําให้รูปหลายเหลี่ยมดูหมุนตลอดเวลา

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();
        }
    }
}

เมื่อคุณสร้างตัวควบคุมแล้ว มาดูที่ XAML กัน เนื่องจากเราจะวางตัวควบคุมที่เราสร้างขึ้นเราจะเพิ่มเนมสเปซให้กับแท็กราก ในที่นี้หมายถึง "xw"

<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>

ถัดไป ขยายแท็กสําหรับตัวควบคุม WindowsFormsHost ที่คุณเพิ่งวางไว้ และเพิ่ม GraphicsDeviceControl ดังที่แสดงด้านล่าง

<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>

คุณไม่จําเป็นต้องมี "x:Name" แต่ตัวอย่างจะใช้เพื่อเข้าถึงข้อมูลจุดยอดด้วยแถบเลื่อน

ถ้าคุณทําเช่นนี้ คุณสามารถเรียกใช้ฉากบน WPF ที่รูปหลายเหลี่ยมถูกวาดด้วยรูปหลายเหลี่ยมที่หมุนได้ ดังที่แสดงในตัวอย่าง การเข้าถึงด้วยแถบเลื่อนเป็นโบนัส ดังนั้นโปรดดาวน์โหลดข้อมูลตัวอย่างและตรวจสอบ

โปรแกรมต้องใช้ .NET Framework 3.0 รันไทม์ DirectX ล่าสุด และ Microsoft XNA Framework Redistributable 2.0 นอกจากนี้ ตามข้อกําหนดของฮาร์ดแวร์ จําเป็นต้องมี "การ์ดแสดงผลที่รองรับ Pixel Shader 1.1 หรือสูงกว่า"

นอกจากนี้โครงการยังถูกสร้างขึ้นใน "Visual Studio 2008 Professional Edition" เตรียมสภาพแวดล้อมสําหรับ Visual Studio 2008