WisdomSoft - for your serial experiences.

ディスプレイの向き

Windows Phone を含む一般的なスマートフォンには3軸加速度センサが搭載されており、端末の向きを検出できます。

向きの検出

既定の設定では Windows Phone ゲームは携帯端末を横に持った状態、すなわちディスプレイの横幅が高さよりも長い状態に設定されています。ディスプレイの向きは Winows PC や Xbox 360 向けのゲームには存在しない設定で、ゲーム画面を回転させるという概念はありません。

現在のディスプレイの向きは GameWindow クラスの CurrentOrientation プロパティから得られます。

GameWindow クラス CurrentOrientation プロパティ
public abstract DisplayOrientation CurrentOrientation { get; }

このプロパティは、ゲーム画面の現在の向きを表す Microsoft.Xna.Framework.DisplayOrientation 列挙型の値を返します。

Microsoft.Xna.Framework.DisplayOrientation 列挙型
[FlagsAttribute]
public enum DisplayOrientation

この列挙型は表1のようなメンバが宣言されています。

表1
メンバ 解説
Default 既定のディスプレイの向き。
LandscapeLeft 反時計回りに 90 度回転した横向き。
LandscapeRight 時計回りに 90 度回転した横向き。
Portrait 縦向き。

Windows PC や Xbox 360 では Default メンバが設定されています。 これに対し Windows Phone では LandscapeLeft メンバや LandscapeRight メンバなどの値が得られます。ディスプレイの向きはユーザーが携帯端末の向きを変えることで、いつでも変更される可能性があります。

コード1
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public class TestGame : Game
{
#if WINDOWS || XBOX
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }
#endif

    private GraphicsDeviceManager graphicsDeviceManager;
    private SpriteBatch sprite;
    private SpriteFont font;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        TargetElapsedTime = TimeSpan.FromMilliseconds(33.3333);
        InactiveSleepTime = TimeSpan.FromMilliseconds(1000);
    }

    protected override void LoadContent()
    {
        sprite = new SpriteBatch(GraphicsDevice);
        font = Content.Load<SpriteFont>("TestFont");
        base.LoadContent();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        sprite.Begin();
        sprite.DrawString(font, Window.CurrentOrientation.ToString(), Vector2.Zero, Color.Black);
        sprite.End();

        base.Draw(gameTime);
    }
}
実行結果
コード1 実行結果

コード1は CurrentOrientation プロパティの値を文字列として画面に表示しているだけのプログラムです。Windows Phone の向きを変更すると、文字列が変化することが確認できます。

ただし XNA Framework ゲームの既定の設定では縦向きがサポートされていません。通常のゲームであれば横向き前提に画面が設計されるため、縦向きの画面に対応する必要はありませんが、GraphicsDeviceManager クラスの SupportedOrientations プロパティを変更することで縦向きにも対応できます。

GraphicsDeviceManager クラス SupportedOrientations プロパティ
public DisplayOrientation SupportedOrientations { get; set; }

DisplayOrientation 列挙型は FlagsAttribute 属性を持つため論理演算子で組み合わせられます。ゲームが対応する画面の向きを論理和演算子 | で組み合わせて設定することで、その画面の向きに対応できます。縦向きに対応するには Portrait メンバを加えてください。

コード2
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public class TestGame : Game
{
#if WINDOWS || XBOX
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }
#endif

    private GraphicsDeviceManager graphicsDeviceManager;
    private SpriteBatch sprite;
    private SpriteFont font;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        graphicsDeviceManager.SupportedOrientations = 
            DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight |
            DisplayOrientation.Portrait;

        Content.RootDirectory = "Content";
        TargetElapsedTime = TimeSpan.FromMilliseconds(33.3333);
        InactiveSleepTime = TimeSpan.FromMilliseconds(1000);
    }

    protected override void LoadContent()
    {
        sprite = new SpriteBatch(GraphicsDevice);
        font = Content.Load<SpriteFont>("TestFont");
        base.LoadContent();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        sprite.Begin();
        sprite.DrawString(font, Window.CurrentOrientation.ToString(), Vector2.Zero, Color.Black);
        sprite.End();

        base.Draw(gameTime);
    }
}
実行結果
コード2 実行結果

コード2は SupportedOrientations プロパティに Portrait メンバを追加しているため、縦向きの画面に対応しています。コード1とは異なり GameWindow オブジェクトの CurrentOrientation プロパティが Portrait メンバになることが確認できます。

向き変更イベント

ユーザーが携帯端末の向きを変えると、ゲーム中にいつでも画面の向きが変更されて今います。GameWindow クラスの CurrentOrientation プロパティを Update() メソッド内で監視することで画面の向きが変更したかどうかを調べることもできますが、画面の向きが変更されたときに呼び出される OrientationChanged イベントを用いた方が効率的です。

GameWindow クラス OrientationChanged イベント
public event EventHandler<EventArgs> OrientationChanged

このイベントは CurrentOrientation プロパティの値が変更されると発生します。画面の向きが変更したときに、何らかの処理を実行する必要がある場合に使えます。

コード3
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public class TestGame : Game
{
#if WINDOWS || XBOX
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }
#endif

    private GraphicsDeviceManager graphicsDeviceManager;
    private Color color = Color.Red;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        TargetElapsedTime = TimeSpan.FromMilliseconds(33.3333);
        InactiveSleepTime = TimeSpan.FromMilliseconds(1000);

        Window.OrientationChanged += Window_OrientationChanged;
    }

    void Window_OrientationChanged(object sender, EventArgs e)
    {
        switch (Window.CurrentOrientation)
        {
            case DisplayOrientation.LandscapeLeft:
                color = Color.Red;
                break;
            case DisplayOrientation.LandscapeRight:
                color = Color.Blue;
                break;
        }
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(color);
        base.Draw(gameTime);
    }
}
実行結果
コード3 実行結果

コード3は向きが変更されると画面の塗りつぶしに用いられている color フィールドの値を変更するプログラムです。画面の向きが変わると OrientationChanged イベントに登録している Window_OrientationChanged() メソッドが呼び出され、向きに応じた色が設定されることが確認できます。