WindowsPhoneでダイスと籤

アプリを作っていると、いろいろな判定やランダムによるチェックを行うことがあると思います。

その中でもよくある方法としては、ダイス(サイコロ)を振ってその数値による判定というのと、一定数の当たりから籤を引くという判定があります。

まずはダイス判定関数です。
基本はランダムを利用したもので、ランダム用のシードを作成する関数。
シード利用してランダム関数をコールして、結果の数値に+1して返すダイス関数。(Random.Next(Count)は0~指定数値-1なので)
複数ダイスを判定する関数で構成しています。

        /// <summary>
        /// 複数ダイスのロール
        /// 2D6 なら DiceRoll(2, 6)
        /// 1Dなら「.First<int>()」をつけて呼び出せばintで見れる
        /// </summary>
        /// <param name="numCount">サイコロの数</param>
        /// <param name="surfaceCount">サイコロの面数</param>
        /// <returns>各個の返り値</returns>
        public static int[] DiceRoll(int numCount, int surfaceCount)
        {
            var ret = new int[numCount];

            for (int i = 0; i < numCount; i++)
            {
                ret[i] = Dice(surfaceCount);
            }

            return ret;
        }

        /// <summary>
        /// サイコロ
        /// 数値は0~maxCount - 1なので、出てきた数値に + 1
        /// </summary>
        /// <param name="maxCount">最大数を渡す、D6なら6を</param>
        /// <returns>1~maxCount</returns>
        private static int Dice(int maxCount)
        {
            // シードを生成
            var rnd = new Random((int)GenerateRndNumber());

            var ret = rnd.Next(maxCount) + 1;

            return ret;
        }

        /// <summary>
        /// ランダム用のシード生成
        /// </summary>
        /// <returns></returns>
        private static UInt32 GenerateRndNumber()
        {
            // Generate a random number.
            var rnd = CryptographicBuffer.GenerateRandomNumber();

            return rnd;
        }

次に、籤による判定関数です。
この関数は、箱の中に当たりくじを入れて、その配列を返す関数にしています。
普通にダイス関数での判定でもいいではないかと思う方もいらっしゃると思いますが、これは当たり籤を判断させるための判定です。

どこかに入っている当たりくじを引くというのはダイスでは比率になり、ランダム性にかけます。

そこで、当たりくじの箱を作って、ダイスを振り、そこが当たりくじかどうかを判定することで、比率だけではない判定を行うために作製しました。

        /// <summary>
        /// 100の中に当たりくじをランダムで仕込む
        /// </summary>
        /// <param name="trueDataCount">あたりの数</param>
        /// <returns></returns>
        public static bool[] CreateHundredLottery(int trueDataCount)
        {
            if (trueDataCount > 100) return null;

            // falseで初期化
            bool[] bLotteryArray = Enumerable.Repeat<bool>(false, 100).ToArray();
            bool[] bAddArray = Enumerable.Repeat<bool>(true, trueDataCount).ToArray();

            bAddArray.CopyTo(bLotteryArray, 0);

            // 配列のランダム化
            var retArray = bLotteryArray.OrderBy(i => Guid.NewGuid()).ToArray();

            // 配列の中身を確認する
            // string stData = string.Join(Environment.NewLine, retArray);
            // Debug.WriteLine(stCsvData);

            return retArray;
        }

これらのコードはWindowsPhoneSilverlight8.1ベースですが、WinRTでもほぼそのまま使えるのではないかと思います。
書き換えるとしたらシード生成のところを書き換える形で、Windowsストアアプリでも使用は可能なはずです。

Autorun.infで32/64bitを分けて起動する

Autorun.infの[AutoRun]セクションの拡張で[AutoRun.Amd64]というのがあるようで、これで起動ファイルを分岐できるようです。

[AutoRun.Amd64]
open=setup.exe
icon=setup.exe,0

[AutoRun]
open=sperr32.exe
icon=sperr32.exe,0

記事などでWindows9は64bitオンリーになるんではないかというのが流れてきて、デスクトップの起動はどうしたものかというのがTwitterで流れていたのですが、「いきなり32bitアプリが全面禁止は考えにくい」というのが自分の考えですが、64bitアプリの対応は行うべきかなという感じです。

ただ、最近デスクトップアプリは全く触ってなかったので、この方法にたどり着くのに検索しまくったのはダメな感じだなー(;´Д`)

WindowsPhone8.1開発メモ

WindowsPhoneのデバッグ作業の際、実機とエミュレータで試しますが、機能によってはエミュレータではカメラなどはできません。
(WebCamと連携してカメラが使えるとかになってほしい気はしてます)

そこで実機で動作中なのか、エミュレータで動作中なのかでコード分岐をしたいと思う時があります。

その為の判断は「if(Environment.DeviceType == DeviceType.Emulator)」でエミュレータであることを確認できます。

Environmentは「Environment.NewLine」等、改行コードを追加などで使われることが多いと思いますが、現在のところWindowsPhoneSilverlightでは「DeviceType」のみの実装となります。

WindowsPhoneWindowsRuntimeでは、「Environment.NewLine」が使用可能ではありますが「Environment.DeviceType」がありません。

これは、WindowsPhoneSilverlightでは「Microsoft.Devices.Environment」でWindowsPhoneWindowsRuntimeでは「System.Environment」で判定されるためです。

WindowsPhoneSilverlight開発では明示的に「System.Environment」とすれば、「System.Environment.NewLine」なども使用可能ですが、WindowsPhoneWindowsRuntime開発の場合はWindowsPhoneSilverlightを呼び出せないため、「Microsoft.Devices.Environment.DeviceType」は使用できません。

こんな所にも違いがあるので注意が必要です。

WindowsPhone8.1でのカメラAPIが変更されています

WindowsPhone8では「Windows.Phone.Media.Capture」を使用していましたが、このAPIがWindowsPhone8.1では「APIs is provided for backwards compatibility only.」と「後方互換」のためだけに提供されるAPIとなっています。

「Windows.Phone.Media.Capture」に代わってWindowsPhone8.1では「Windows.Media.Capture」というAPI群が提供されるようになりました。

「Windows.Media.Capture」は「Windows.Phone.Media.Capture」の代わりだけあって、細かな設定ができます。
細かな設定はいらないという場合は「CameraCaptureUI」というAPIが提供されています。

「CameraCaptureUI」は手軽なビデオ撮影機能を実現したい場合には便利ではないかと思います。
※CameraCaptureUI APIはWindowsストアアプリのみのAPIでした

WindowsRuntime(WindowsPhone SilverLight 8.1でも動きます)ですが、Back/Frontのチェック方法を発見したので掲載しておきます。

private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desired)
{
    DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
        .FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desired);

    if (deviceID != null) return deviceID;
    else throw new Exception(string.Format("Camera of type {0} doesn't exist.", desired));
}

片手用ControlPadなUserControlを作ってみた

環境はWindowsPhoneSilverLight8.1ですが、基本的にはC#+XAMLなのであまり変更せずにWinRTにも移植可能ではないかと思います。

まずは外観から
名称未設定 1

XAMLで「ChangePropertyAction」を利用して押した時の反応などを定義してあります

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:es="clr-namespace:Microsoft.Expression.Shapes;assembly=Microsoft.Expression.Drawing" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" xmlns:eim="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions" x:Class="CryEarthWPLib.Controller.View.SingleControllerPad"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="150" d:DesignWidth="150" Opacity="0.7">
    
	<Grid x:Name="LayoutRoot" Width="150" Height="150">
		<VisualStateManager.VisualStateGroups>
			<VisualStateGroup x:Name="VisualStateGroup"/>
		</VisualStateManager.VisualStateGroups>
		<Path x:Name="TopPath" UseLayoutRounding="False" VerticalAlignment="Top" Data="M84.8528,0 L98.9949,14.1422 L97.7933,15.3155 C85.2319,27.2917 68.2234,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1421 L14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,4E-06 z" Height="34.645" Margin="25.503,35.355,25.503,0" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Stroke="#667088B2" MouseEnter="RingPath_MouseEnter" MouseLeftButtonDown="RingPath_MouseLeftButtonDown" MouseLeftButtonUp="RingPath_MouseLeftButtonUp" MouseLeave="RingPath_MouseLeave">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<ec:ChangePropertyAction TargetName="TopPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=TopPath_State}"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseEnter">
					<ec:ChangePropertyAction TargetName="TopPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=TopPath_State}"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeftButtonUp">
					<ec:ChangePropertyAction TargetName="TopPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=TopPath_State}">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeave">
					<ec:ChangePropertyAction TargetName="TopPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=TopPath_State}">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
			</i:Interaction.Triggers>
			<Path.Fill>
				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
					<GradientStop Color="#FF71A0E4" Offset="1"/>
					<GradientStop Color="#FF17335B" Offset="0.246"/>
				</LinearGradientBrush>
			</Path.Fill>
			<Path.RenderTransform>
				<CompositeTransform ScaleY="-1"/>
			</Path.RenderTransform>
		</Path>
		<Path x:Name="BottomPath" UseLayoutRounding="False" VerticalAlignment="Bottom" Data="M14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,0 L98.995,14.1422 C86.3275,26.8097 68.8275,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1422 z" Height="34.645" Margin="25.503,0,25.503,5" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Stroke="#667088B2" MouseLeftButtonDown="RingPath_MouseLeftButtonDown" MouseLeftButtonUp="RingPath_MouseLeftButtonUp" MouseLeave="RingPath_MouseLeave" MouseEnter="RingPath_MouseEnter">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<ec:ChangePropertyAction TargetName="BottomPath_State" PropertyName="Visibility"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseEnter">
					<ec:ChangePropertyAction TargetName="BottomPath_State" PropertyName="Visibility"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeftButtonUp">
					<ec:ChangePropertyAction TargetName="BottomPath_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeave">
					<ec:ChangePropertyAction TargetName="BottomPath_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
			</i:Interaction.Triggers>
			<Path.Fill>
				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
					<GradientStop Color="#FF71A0E4" Offset="1"/>
					<GradientStop Color="#FF17335B" Offset="0.246"/>
				</LinearGradientBrush>
			</Path.Fill>
			<Path.RenderTransform>
				<CompositeTransform/>
			</Path.RenderTransform>
		</Path>
		<Path x:Name="RightPath" Data="M14.1422,0 C26.8097,12.6675 34.6447,30.1675 34.6447,49.4975 C34.6447,68.2234 27.2917,85.2319 15.3155,97.7933 L14.1422,98.995 L0,84.8528 C9.04823,75.8046 14.6447,63.3046 14.6447,49.4975 C14.6447,36.5533 9.72592,24.758 1.65557,15.8786 L0,14.1422 z" Margin="110.355,25.503,5,25.503" Stretch="Fill" UseLayoutRounding="False" Stroke="#667088B2" MouseLeftButtonDown="RingPath_MouseLeftButtonDown" MouseLeftButtonUp="RingPath_MouseLeftButtonUp" MouseLeave="RingPath_MouseLeave" MouseEnter="RingPath_MouseEnter">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<ec:ChangePropertyAction TargetName="RightPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=RightPath_State}"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseEnter">
					<ec:ChangePropertyAction TargetName="RightPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=RightPath_State}"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeftButtonUp">
					<ec:ChangePropertyAction TargetName="RightPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=RightPath_State}">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeave">
					<ec:ChangePropertyAction TargetName="RightPath_State" PropertyName="Visibility" TargetObject="{Binding ElementName=RightPath_State}">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
			</i:Interaction.Triggers>
			<Path.Fill>
				<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
					<LinearGradientBrush.RelativeTransform>
						<CompositeTransform CenterY="0.5" CenterX="0.5" Rotation="-90"/>
					</LinearGradientBrush.RelativeTransform>
					<GradientStop Color="#FF71A0E4" Offset="1"/>
					<GradientStop Color="#FF17335B" Offset="0.246"/>
				</LinearGradientBrush>
			</Path.Fill>
		</Path>
		<Path x:Name="LeftPath" UseLayoutRounding="False" HorizontalAlignment="Left" VerticalAlignment="Center" Data="M84.8528,0 L98.9949,14.1422 L97.7933,15.3155 C85.2319,27.2917 68.2234,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1421 L14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,4E-06 z" Height="34.645" Margin="-11.997,72.855,0,42.5" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Width="98.994" Stroke="#667088B2" MouseLeftButtonDown="RingPath_MouseLeftButtonDown" MouseLeftButtonUp="RingPath_MouseLeftButtonUp" MouseLeave="RingPath_MouseLeave" MouseEnter="RingPath_MouseEnter">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<ec:ChangePropertyAction TargetName="LeftPath_State" PropertyName="Visibility"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseEnter">
					<ec:ChangePropertyAction TargetName="LeftPath_State" PropertyName="Visibility"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeftButtonUp">
					<ec:ChangePropertyAction TargetName="LeftPath_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeave">
					<ec:ChangePropertyAction TargetName="LeftPath_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
			</i:Interaction.Triggers>
			<Path.Fill>
				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
					<GradientStop Color="#FF71A0E4" Offset="1"/>
					<GradientStop Color="#FF17335B" Offset="0.246"/>
				</LinearGradientBrush>
			</Path.Fill>
			<Path.RenderTransform>
				<CompositeTransform Rotation="90"/>
			</Path.RenderTransform>
		</Path>
		<es:Arc x:Name="TapArc" ArcThickness="1" ArcThicknessUnit="Percent" EndAngle="360" Height="40" Stretch="None" UseLayoutRounding="False" Width="40" HorizontalAlignment="Center" VerticalAlignment="Center" Tap="TapArc_Tap" Stroke="#33999DCB" d:IsLocked="True">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<ec:ChangePropertyAction TargetName="TapArc_State" PropertyName="Visibility"/>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeftButtonUp">
					<ec:ChangePropertyAction TargetName="TapArc_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
				<i:EventTrigger EventName="MouseLeave">
					<ec:ChangePropertyAction TargetName="TapArc_State" PropertyName="Visibility">
						<ec:ChangePropertyAction.Value>
							<Visibility>Collapsed</Visibility>
						</ec:ChangePropertyAction.Value>
					</ec:ChangePropertyAction>
				</i:EventTrigger>
			</i:Interaction.Triggers>
			<es:Arc.Fill>
				<RadialGradientBrush>
					<GradientStop Color="#FF2E4A93" Offset="0.884"/>
					<GradientStop Color="Black"/>
					<GradientStop Color="#FF4D77E8" Offset="0.53"/>
					<GradientStop Offset="1" Color="Transparent"/>
					<GradientStop Color="#FF162D66" Offset="0.944"/>
					<GradientStop Color="#FF2E4A93" Offset="0.19"/>
				</RadialGradientBrush>
			</es:Arc.Fill>
		</es:Arc>
		<es:RegularPolygon x:Name="TopTriangle" HorizontalAlignment="Center" Height="15" InnerRadius="1" PointCount="3" Stretch="Fill" UseLayoutRounding="False" VerticalAlignment="Top" Width="15" Fill="#66FFFFFF" Margin="67.5,7,67.5,0" IsHitTestVisible="False" d:IsLocked="True"/>
		<es:RegularPolygon x:Name="BottomTriangle" HorizontalAlignment="Center" Height="15" InnerRadius="1" PointCount="3" Stretch="Fill" UseLayoutRounding="False" VerticalAlignment="Bottom" Width="15" Fill="#66FFFFFF" Margin="67.5,0,67.5,7" RenderTransformOrigin="0.5,0.5" IsHitTestVisible="False" d:IsLocked="True">
			<es:RegularPolygon.RenderTransform>
				<CompositeTransform ScaleY="-1"/>
			</es:RegularPolygon.RenderTransform>
		</es:RegularPolygon>
		<es:RegularPolygon x:Name="LeftTriangle" HorizontalAlignment="Left" Height="15" InnerRadius="1" PointCount="3" Stretch="Fill" UseLayoutRounding="False" VerticalAlignment="Center" Width="15" Fill="#66FFFFFF" RenderTransformOrigin="0.5,0.5" Margin="7,0,0,0" IsHitTestVisible="False" d:IsLocked="True">
			<es:RegularPolygon.RenderTransform>
				<CompositeTransform ScaleY="-1" Rotation="90"/>
			</es:RegularPolygon.RenderTransform>
		</es:RegularPolygon>
		<es:RegularPolygon x:Name="RightTriangle" HorizontalAlignment="Right" Height="15" InnerRadius="1" PointCount="3" Stretch="Fill" UseLayoutRounding="False" VerticalAlignment="Center" Width="15" Fill="#66FFFFFF" RenderTransformOrigin="0.5,0.5" Margin="0,0,7,0" IsHitTestVisible="False" d:IsLocked="True">
			<es:RegularPolygon.RenderTransform>
				<CompositeTransform Rotation="-90" ScaleY="-1" ScaleX="-1"/>
			</es:RegularPolygon.RenderTransform>
		</es:RegularPolygon>
        <Path x:Name="TopPath_State" UseLayoutRounding="False" VerticalAlignment="Top" Data="M84.8528,0 L98.9949,14.1422 L97.7933,15.3155 C85.2319,27.2917 68.2234,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1421 L14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,4E-06 z" Height="34.645" Margin="25.503,35.355,25.503,0" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Stroke="#667088B2" Fill="#99FFFFFF" Visibility="Collapsed" IsHitTestVisible="False" d:IsLocked="True">
			<Path.RenderTransform>
				<CompositeTransform ScaleY="-1"/>
			</Path.RenderTransform>
		</Path>
		<Path x:Name="RightPath_State" Data="M14.1422,0 C26.8097,12.6675 34.6447,30.1675 34.6447,49.4975 C34.6447,68.2234 27.2917,85.2319 15.3155,97.7933 L14.1422,98.995 L0,84.8528 C9.04823,75.8046 14.6447,63.3046 14.6447,49.4975 C14.6447,36.5533 9.72592,24.758 1.65557,15.8786 L0,14.1422 z" Margin="110.355,25.503,5,25.503" Stretch="Fill" UseLayoutRounding="False" Stroke="#667088B2"  Fill="#99FFFFFF" Visibility="Collapsed" IsHitTestVisible="False" d:IsLocked="True"/>
		<Path x:Name="BottomPath_State" UseLayoutRounding="False" VerticalAlignment="Bottom" Data="M14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,0 L98.995,14.1422 C86.3275,26.8097 68.8275,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1422 z" Height="34.645" Margin="25.503,0,25.503,5" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Stroke="#667088B2" Fill="#99FFFFFF" Visibility="Collapsed" IsHitTestVisible="False" d:IsLocked="True">
			<Path.RenderTransform>
				<CompositeTransform/>
			</Path.RenderTransform>
		</Path>
		<Path x:Name="LeftPath_State" UseLayoutRounding="False" HorizontalAlignment="Left" VerticalAlignment="Center" Data="M84.8528,0 L98.9949,14.1422 L97.7933,15.3155 C85.2319,27.2917 68.2234,34.6447 49.4975,34.6447 C30.1675,34.6447 12.6675,26.8097 0,14.1421 L14.1421,0 C23.1904,9.04823 35.6904,14.6447 49.4975,14.6447 C63.3046,14.6447 75.8046,9.04823 84.8528,4E-06 z" Height="34.645" Margin="-11.997,72.855,0,42.5" RenderTransformOrigin="0.5,0.061905" Stretch="Fill" Width="98.994" Stroke="#667088B2" Fill="#99FFFFFF" Visibility="Collapsed" IsHitTestVisible="False" d:IsLocked="True">
			<Path.RenderTransform>
				<CompositeTransform Rotation="90"/>
			</Path.RenderTransform>
		</Path>
		<es:Arc x:Name="TapArc_State" ArcThickness="1" ArcThicknessUnit="Percent" EndAngle="360" Height="40" Stretch="None" UseLayoutRounding="False" Width="40" HorizontalAlignment="Center" VerticalAlignment="Center" Tap="TapArc_Tap" Stroke="#33999DCB" Margin="55" Fill="#99FFFFFF" Visibility="Collapsed" IsHitTestVisible="False" d:IsLocked="True"/>

	</Grid>
</UserControl>

続いてコード部分

    public partial class SingleControllerPad : UserControl
    {
        /// <summary>
        /// Key判断イベントHANDLE
        /// </summary>
        /// <param name="sender">this</param>
        /// <param name="keyId">0=Enter,1=TOP,2=Bottom,3=Left,4=Right,5=non</param>
        public delegate void TapKeyControlEventHandler(object sender, int keyId);

        public event TapKeyControlEventHandler TapKeyControl;

        /// <summary>
        /// Keyイベント
        /// </summary>
        /// <param name="keyId">0=Enter,1=TOP,2=Bottom,3=Left,4=Right,5=non</param>
        protected virtual void OnTopKeyControl(int keyId)
        {
            if (TapKeyControl != null)
            {
                TapKeyControl(this, keyId);
            }
        }

        public SingleControllerPad()
        {
            InitializeComponent();
        }

		/// <summary>
		/// 確定Button
		/// 所謂Aボタンを押したとか
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        private void TapArc_Tap(object sender, System.Windows.Input.GestureEventArgs e)
		{
            // 確定なので0で固定
            // イベントをチェックしているところでイベント発生後、イベントをリセットする
		    OnTopKeyControl(0);
		}

        /// <summary>
        /// 領域に入ってきたことを検知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RingPath_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            var ul = e.OriginalSource as UIElement;
            if (ul != null)
            {
                var name = ((System.Windows.Shapes.Path)ul).Name;
                CallRingPathEvent(name);
            }
        }

        /// <summary>
        /// 領域から出たことを検知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RingPath_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            // 何も押していないことを通知
            CallRingPathEvent("");
        }

        /// <summary>
        /// Buttonを選択
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RingPath_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var ul = e.OriginalSource as UIElement;
            if (ul != null)
            {
                var name = ((System.Windows.Shapes.Path)ul).Name;
                CallRingPathEvent(name);
            }
        }

        /// <summary>
        /// Buttonを離す
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RingPath_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var ul = e.OriginalSource as UIElement;
            if (ul != null)
            {
                var name = ((System.Windows.Shapes.Path)ul).Name;
                CallRingPathEvent(name);
            }
        }

        /// <summary>
        /// 外部にどのボタンを押しているかを知らせる
        /// </summary>
        /// <param name="pathName"></param>
        void CallRingPathEvent(string pathName)
        {
            switch (pathName)
            {
                case "TopPath":
                    OnTopKeyControl(1);
                    break;

                case "BottomPath":
                    OnTopKeyControl(2);
                    break;

                case "LeftPath":
                    OnTopKeyControl(3);
                    break;

                case "RightPath":
                    OnTopKeyControl(4);
                    break;

                default:
                    OnTopKeyControl(5);
                    break;
            }
        }

    }

このコントロール自体はあくまでもキー情報を通知するだけの機能にしています。
使うときは、イベントでKeyIDを確保して、ゲームループでそのIDを判断して各操作を行うという形にしています。

{
            var timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler(GameLoopTimerCallback), TimeSpan.FromMilliseconds(35));
            // メインUIのDispatcherを取得
            dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
}

        private async void GameLoopTimerCallback(ThreadPoolTimer timer)
        {
            if (dispatcher != null)
                await dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () =>
                    {
                            // 各種処理関数を呼び出す
                    });
        }

大分手抜き&片手コントロール用なのでいろいろ不足していますし、キャンセルボタンの扱いという問題もあります。
まあ、入り口ということで、こんなのもありかなと思います。

Microsoft MVP アワードでExpertise名称に変更がありました

7/1付で「Client Development」と「Windows Phone Development」が統合されて「Windows Platform Development」という名称に変更されました。

universal Appsが推進されたのと、クライアント開発としては非常に似通った開発技術、ということで、統合されて新名称となったとのことです。

自分は「Client Development」で受賞はしていますが、WindowsPhoneの開発も並行して行っていたのでうれしい変更です。