忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

Silverlight5からXnaを使う その3 マウスとキーボード

前回までは三角形を回転させました。
しかしその三角形は自分で勝手に回るだけです。
ゲームを作りたいならユーザーがマウスを動かしたりキーボードをカチャカチャしたりするのに反応すべきです。


(キーボードの矢印キー「←か→」を押してください)

非SilverlightなXnaにはMouseクラスやKeyboardクラスがあります。
それを使ってマウスやキーボードの状態を取得できたのです。
が、Silverlight版Xnaには該当するクラスが公式にはありません。

ありません、では困るのでちゃんと用意されています。

Silverlight 5 Toolkit December 11

このサイトにあるmsiファイルを実行すると、Microsoft.Xna.Framework.Toolkitがインストールされます。
そのdllから、MouseクラスやKeyboardクラスが使えるようになるのです。
ただし使い方はオリジナルのものとちょっと違います。
はじめにRootControlにコントロールのインスタンスをセットする必要があります。

詳しく見て行きましょう。


プログラム

using System;
using System.Windows.Controls;

using Microsoft.Xna.Framework;
using Xna = Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Windows.Graphics;
using Microsoft.Xna.Framework.Input;


namespace SilverlightXna03
{
    public partial class MainPage : UserControl
    {
        private VertexBuffer vertexBuffer;
        private BasicEffect basicEffect;
        private bool loaded = false;
        private float angle;

        public MainPage()
        {
            InitializeComponent();
            showGpuError();
            Keyboard.RootControl = this;
        }

        private void showGpuError()
        {
            if (GraphicsDeviceManager.Current.RenderMode == RenderMode.Hardware)
            { return; }

            string message;
            switch (GraphicsDeviceManager.Current.RenderModeReason)
            {
                case RenderModeReason.Not3DCapable:
                    message = "あなたのグラフィックスハードウェアはこのページを表示出来ません";
                    break;
                case RenderModeReason.GPUAccelerationDisabled:
                    message = "ハードウェアグラフィックスアクセラレーションがこのwebページでは有効にされていません。\n\n" +
                        "webサイトのオーナーに通知してください";
                    break;
                case RenderModeReason.TemporarilyUnavailable:
                    message = "あなたのグラフィックスハードウェアは一時的に使用不可能になっています。\n\n" +
                        "webページをリロードするかブラウザを再起動してください。";
                    break;
                case RenderModeReason.SecurityBlocked:
                    message =
                      "webサイトが3Dグラフィックスを表示できるようにするには、システム構成を変える必要があります。\n\n" +
                      "  1. ここを右クリックします\n" +
                      "  2. 'Silverlight'を選択します\n" +
                      "     ('Microsoft Silverlight Configuration'ダイヤログが表示されます)\n" +
                      "  3. 'Permissions'タブを選択します\n" +
                      "  4. このサイトをリストの中から見つけ、その3Dグラフィックスパーミッションを'Deny'から'Allow'に変えます\n" +
                      "  5. 'OK'をクリックします\n" +
                      "  6. ページをリロードします";
                    break;
                default:
                    message = "不明なエラー";
                    break;
            }

            textBlock.Text = "3D表示がブロックされました!\n\n\n" + message;
        }

        private void DrawingSurface_Draw(object sender, DrawEventArgs e)
        {
            if (!loaded)
            {
                LoadContent();
                loaded = true;
            }

            Update();
            Draw();
            e.InvalidateSurface();
        }


        private GraphicsDevice GraphicsDevice
        {
            get
            {
                return GraphicsDeviceManager.Current.GraphicsDevice;
            }
        }

        private void LoadContent()
        {
            VertexPositionColor[] vertices = new[]
                {
                    new VertexPositionColor(
                        new Vector3(-1, -1, 0), 
                        new Color(1f, 0, 0)
                    ),
                    new VertexPositionColor(
                        new Vector3(0, 1, 0),
                        new Color(1f, 1f, 1f)
                    ),
                    new VertexPositionColor(
                        new Vector3(1, -1, 0),
                        new Color(0, 0, 1f)
                    )
                };

            vertexBuffer = new VertexBuffer(
                GraphicsDevice,
                VertexPositionColor.VertexDeclaration,
                vertices.Length,
                BufferUsage.WriteOnly
                );
            vertexBuffer.SetData(0, vertices, 0, vertices.Length, 0);

            basicEffect = new BasicEffect(GraphicsDevice)
            {
                VertexColorEnabled = true,
                Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45),
                    GraphicsDevice.Viewport.AspectRatio,
                    1, 100
                    )
            };
        }

        private void Update()
        {
            KeyboardState keyboardState = Keyboard.GetState();

            if (keyboardState.IsKeyDown(System.Windows.Input.Key.Left))
            {
                angle += 0.01f;
            }
            if (keyboardState.IsKeyDown(System.Windows.Input.Key.Right))
            {
                angle += -0.01f;
            }
        }

        private void Draw()
        {
            GraphicsDevice.Clear(new Xna.Color(0.39f, 0.58f, 0.93f));
            GraphicsDevice.RasterizerState = RasterizerState.CullNone;

            basicEffect.View = Matrix.CreateLookAt(
                new Vector3
                    (
                    3 * (float)Math.Sin(angle),
                    0,
                    3 * (float)Math.Cos(angle)
                    ),
                new Vector3(),
                Vector3.Up
                );

            basicEffect.CurrentTechnique.Passes[0].Apply();
            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            GraphicsDevice.DrawPrimitives(
                PrimitiveType.TriangleList,
                0,
                vertexBuffer.VertexCount / 3
                );
        }
    }
}

Silverlight版のKeyboardStateクラス、Keyboardクラス、MouseStateクラス、Mouseクラスは
オリジナルのXnaバージョンのクラスとほとんどかわりません。
ただし気を付けなければいけないことが1つだけ。
GetStateメソッドで状態を得る前に、RootControlプロパティでコントロールをセットしなければいけません。
このプログラムではコントロールのコンストラクタでそれを行なっています。
あとは普通のXnaと全く同じです。


追記 2012/03/10

どうやらMouse.RootControlにセットすると、右クリックした時にSilverlightメニューが現れなくなるようです。
ですからshowGpuErrorのメッセージは次のように書き換えるべきかもしれません:

1.[スタート]-[すべてのプログラム]をクリックします。
2.[Microsoft Silverlight]-[Silverlight]を選択します
    ([Microsoft Silverlight の構成
]ダイヤログが表示されます)
3. [アクセス許可]タブを選択します
4. このサイトをリストの中から見つけ、その3Dグラフィックスアクセス許可を[拒否]から[許可]に変えます
5. [OK]をクリックします
6. ページをリロードします

拍手[1回]

PR