Syncfusion Essential Studio に COMMUNITY LICENSE が!

Syncfusion 社の「ESSENTIAL STUDIO」に≪COMMUNITY LICENSE≫が追加されました!

ESSENTIAL STUDIOって?

ESSENTIAL STUDIOはアプリを開発する際に使用可能なコンポーネントライブラリです。
android、iOS、Xamarin(Android,iOS,Forms)、JavaScript、ASP.NET、ASP.NET MVC、Windows Forms、WPF、WinRT、UWP、Windows Phoneの各種プラットフォームに対応しています。

何ができるの?

自作しようとすると面倒になりがちな「チャート」や「カレンダー」、「ダイアグラム」、「PDF」などをコンポーネント提供してくれています。

COMMUNITY LICENSEって結局なに?

・個人開発者
・年間売り上げ100万$(約1億円)以下の企業
・使用可能な開発ユーザー5人まで
上記の条件を満たしていれば「無償」で使用可能なライセンスになっています!
しかも、「商用アプリも可」というすごいライセンスです。

なんでそんなすごいライセンスが提供されたの?

マイクロソフト社が「Visual Studio Community」という開発ソフトの無償ライセンスの拡充を行ったことに触発されて、Syncfusion 社が提供に踏み切ったそうです。

使うにはどうするの?

COMMUNITY LICENSEのページ≫からユーザー登録をしてダウンロード後、インストールしてください。
専用のアンロックキーが提供されますので、キーの入力で使用可能になります。

さて、さらにありがたいことにSyncfusion 社は≪METRO STUDIO≫というフリーのアイコンツールも提供していただけています。
アプリの作成時に必要な各種アイコンはこれでほぼ事足りますので、ぜひ一緒に使用しましょう。

そして最後にVisual StudioXamarinを利用して、ぜひアプリを作りませんか?

Windows Phone/Windows 10 Mobile に関するゲームパッド考察

ゲームパッドを使用することができるのか?

さて、「Windows Phone/Windows 10 MobileでGamePadは使用できるのか?」ですが、結論から先に言っておきます、条件付きで可能、ふつうは無理です。

WindowsPhone8/8.1用として実は「MOGA Game On Anywhere(以下 MOGA)」が出したコントローラーがBTを利用した(おそらく)シリアル通信的な方法で、使用できるようにしていました。
ただこれは専用SDKが提供されない限り使用できないという形で、更新をしていない状況から今後使用できることはないだろうと思います。

次に目を付けたのは「Windows8.1 UpDate2(以下 WP8.1UP2)」から解禁された「Bluetooth HID Profile」の存在です。
HID(Human Interface Device)、USBにもありますが所謂入力機器の受け取りができる機能です。

さてこれを実験だと思ったのですが、残念ながら手持ちの端末には「WP8.1UP2」が降りてこないという状況でしたが、この機能は「Windows 10 Mobile(以下W10M)」でも使用可能になりました。

これはやるしかないということで、いろいろ仕込んでいたのですが、まずは先だって開催された「Microsoft MVP Asia Meet Up」イベントに参加した際にMADOSMAをW10Mにアップされた方が持ってきているよなと思い、接続を試させていただくことにしました。

結果

BT機器があるということは認識するもののペアリングは却下されるという状況でした。
もちろんイベントの隙間を利用した短時間での確認のため、これだけで出来ないということは確定できないですが、正直どうしようと思いました(汗

次の一手

wp_ss_20150411_0003
あきらめるわけにもいかないので、1320にInsider Programでアップデートをかけて実験という形にしました。

wp_ss_20151211_0003
こちらでも認識(SS取れなかったですがキーボードHID認識のようです)はしました。

wp_ss_20151211_0004
そして、ペアリングも完了!

なら使うぞ!

UWP向けにAPIが追加されているのですが、その中に「Windows.Gaming.Input」というそのものずばりなAPIがあります。
で、APIを確認している限りではMobileに対する縛りはないようなので、「これは使える!」と実験開始

いきなりモバイルというわけにもいかないのでまずはDesktopUWPで実験、、、困ったことにWindows上では認識しているもののUWPのAPI上では存在しないというのが返ってきました。
とりあえずAPIの確認のためDevice転送でチェックしたところAPIはそのまま通りました。
機能宣言は「AllJoin」「Bluetooth」にはチェックを入れたものの、HIDに関する項目ないなこれ(汗
API条件に宣言しなければいけないようなことは記載されていないので、API自体はチェックなしでもエラーなく動きます。

さて、「Windows.Gaming.Input」ですが、内部的には「XInput」ではなかろうかと思います。
となるとMoga2では認識しないですよねこれ、、、
手持ちにXInput対応機器がないので、自分には検証しきれませんでした。

というわけで最初に書いた通りなのですが、「条件付きで可能 / ふつうは無理」が今のところの結論です。
もちろんもっと深く探っていけば可能になるんではと思ってはいます。
もう少しさっくり対応できるようになっていると「A端末とかi端末で出来るのに、WP出来ないから~」とは言われなくて済むかなーと

まあ、解放できない理由は、セキュリティーとか考えるとわからないでもないので………

というわけで、「ゲームコントローラー周りの対応状況をぼそっと公開してくれないかなー>MS様」等と書くためだけのネタ記事でした。

「Windows 10 Mobile」は良い端末ですし、まだまだこれからさらに良くなっていくことでしょう。

おまけ

さて、これだけで何なのでちょっとおまけを

WP_20151212_10_16_39_Pro
こんなのを入手したわけですよ。
ええ、ご想像の通りです…………「1320はUSB OTG非対応
何をつなごうが全く認識しません(;´Д`)

Windows Phone / Windows 10 Mobile Advent Calendar 2015」に参加しています。

裏ではいろいろ仕込んでるんですが、公開レベルに持っていけなくてこんな記事になりましたが、ほかの方の記事には良いものがあるので、是非一読を!

※追記(2015/12/12/21:30)

DirectInputじゃダメなの?

もちろんこうなれば「DirectInput」をラップ実装してというのは頭の片隅にあったのですが、XInputをストアアプリ荷を調べていた際に「XInput and DirectInput」というMicrosoftの公式ページを見つけましてそこに

Note Use of legacy DirectInput is not recommended, and DirectInput is not available for Windows Store apps.

レガシーでストアアプリには対応していないと書かれていました。

Unityでuniversal Appのメモ

Unityスクリプト上でBackKeyは「KeyCode.Escape」になる。
でもあんまり行儀のいいコードでは無いような気がする

#if UNITY_WINRT
        if (Input.GetKey(KeyCode.Escape))
        {
            Application.Quit();
        }
#endif

※これは間違い
Main.csにBackキーをとるためのコードをMainPage関数に追加したものの、発生しない模様

		public MainPage(SplashScreen splashScreen)
		{
            …
#if UNITY_WP_8_1

            Windows.Phone.UI.Input.HardwareButtons.BackPressed += (sender, e) =>
		    {
                Frame frame = Window.Current.Content as Frame;
                if (frame == null)
                {
                    return;
                }

                if (frame.CanGoBack)
                {
                    frame.GoBack();
                    e.Handled = true;
                }
		    };

#endif
		}

傾き検出
 全部テスト
 いくつか機能しない、実機では「Input.gyro.enabled」をtrueにしていても「False」と表示される

	void Start () {
        Input.gyro.enabled = true;
        Input.gyro.updateInterval = 0.01F;
	}
	
	// Update is called once per frame
	void Update ()
	{
        var gyroText = "enabled : " + Input.gyro.enabled.ToString() + Environment.NewLine;
        gyroText += "attitude : " + Input.gyro.attitude.ToString() + Environment.NewLine;
        gyroText += "gravity : " + Input.gyro.gravity.ToString() + Environment.NewLine;
        gyroText += "rotationRate : " + Input.gyro.rotationRate.ToString() + Environment.NewLine;
        gyroText += "rotationRateUnbiased : " + Input.gyro.rotationRateUnbiased.ToString() + Environment.NewLine;
        gyroText += "updateInterval : " + Input.gyro.updateInterval.ToString() + Environment.NewLine;
        gyroText += "userAcceleration : " + Input.gyro.userAcceleration.ToString() + Environment.NewLine;

        guiText.text = gyroText;
	}

GyroTest

Unity-chanの表示がおかしいですが、これはWindowsPhone8.1(実機)がカスタムシェーダーに対応していないためです。
マテリアルを改良または取り去れば、きちんと表示されるはずです

Unity3dでuniversal App Projectを吐き出す際のメモ

※再度試したところ、プロジェクトファイルを書き換えなくてもコンパイラが通りました。
 自分の環境のせいで何かしらおかしなことが起こっていたのかもしれないですが、なぜ通らない現象が起きたのか、何が原因なのかよくわかりません。


吐き出して其の儘だとVisualStudio2013Up3でコンパイルが通りません。

参照の中にリンク不明のエラーが二つでます。

Unity3d Ver4.5.4p2
VisualStudio2013 UpDate3
VisualStudio Tools Unity 1.9.1
上記環境で現象が起きています。

・.Windows.csproj
・.WindowsPhone.csproj
上記二つのプロジェクトファイルの一部を書き換えます。
エラーを起こしているファイルは「Assembly-CSharp.dll」「Assembly-CSharp-firstpass.dll」の二つです。

	<Reference Include="$(UnityProjectDir)\bin\Store 8.1\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp-firstpass.dll" >
		<HintPath>.\$(UnityProjectDir)\bin\Store 8.1\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp-firstpass.dll</HintPath>
	</Reference>
	<Reference Include="$(UnityProjectDir)\bin\Store 8.1\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp.dll" >
		<HintPath>.\$(UnityProjectDir)\bin\Store 8.1\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp.dll</HintPath>
	</Reference>

このように書かれており、一見問題なく通ると思われるのですが、なぜか「$(PlatformName)」がコンパイラで指定している「ARM」「x86」ではなく「AnyCPU」となってしまうために起こるエラーです。
(「Store 8.1」の部分はWP8.1用では「Phone 8.1」となっています)

    <Reference Include="Assembly-CSharp">
      <HintPath>bin\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp.dll</HintPath>
    </Reference>
    <Reference Include="Assembly-CSharp-firstpass">
      <HintPath>bin\$(PlatformName)\$(ConfigurationName)\Assembly-CSharp-firstpass.dll</HintPath>
    </Reference>

そこで上記のように書き換えます。
さらに、VisualStudio2013Up3の「デバッグ」>「オプションと設定」>「全般」の中の「起動時にユーザーコードが見つからない時警告(マネージのみ)」についているチェックを外します。

debugoption
これが自分の環境のせいなのか、VS側の問題なのか、Unityの書き出しの問題なのか不明です。
もう少し調べてみたいところですが、そんなことよりアプリ作るために作業を進めたいと思います。

※追記
Unity-chanというUnity公式キャラクターがあります。
オフィシャルページからUnity用のAssetファイルをダウンロードすることができます。

このキャラクターを使ったアプリを作成しようとテストしていたのですが、ストアアプリ向けに吐き出そうとするとエラーが発生します。

困ったことにエラーのログが文字化けして詳しいエラー内容がわかりませんが、エラーコードから「Script/AutoBlink.cs」に書かれている「using System.Security.Policy;」はassemblyがないというエラー。
これはコメントアウトすれば解決するので、それほど問題はないと思います。
(もしくは#ifで囲ってしまうほうがいいかもしれません)

もう一つは下記画像なのですが

BycphOiIYAEf1nW.jpg large

「Script/SpringManager.cs」にある「UpdateParameter」関数内

			var prop = springBones [0].GetType ().GetField (fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

GetType しているGetField の内容が不正ということだと思うのですが、取りあえずこれも「#if」で囲って使用されないようにすることで、吐き出すことができました。

とりあえず出だしのところで躓くというへっぽこな開発スタートでしたが、まずはどうすればいいかを早いところ洗い出しておきたいです。

WindowsPhone8/8.1 Game Pad/Controller

WindowsPhone8/8.1(以降WP8/8.1)にはGame Pad/Controllerが有りませんでした。
これはモバイル向けGame Pad/Controllerとの接続で良く使用されるBluetoothですが、WP8/8.1にはBluetoothは搭載されているものの、対応profileとして「HID」が無いため外部入力機器が使用できませんでした。

ところが、最近検索していて見つけたのですが、Bensussen Deutsch & Associates, Inc(以下 BDA)社の「MOGA Game On Anywhere(以下 MOGA)」シリーズの一部が対応しているとの記事を見つけました。

MOGAにはiPhone用とAndroid用のゲームコントローラーがあるのですが、Android用でWP8/8.1に使用できる機能が付き、WP8用SDK(WinPRT)が公開されています。

MOGA Pro SDK – WindowsPhone8

自分は下記のコントローラーを購入して、SDKにあったサンプルでコントローラーが動作することを確認しました。


此方はUSB充電伝可能なリチウム電池内蔵型です。


価格は安いものの、単三電池二本が必要になる、リチウム電池やUSBコネクタはありません。

というわけで、WP8(WinPRT)用とはなっているものの、WP8.1WinRTベースで使用できるようにできないかと、色々試してみました。

“WindowsPhone8/8.1 Game Pad/Controller” の続きを読む

WinRTで画面遷移の履歴スタックを削除する

WindowsRuntime(WinRT)アプリで画面遷移を行っている際に、一気にTOPページに戻したいけど、戻した後に戻ってこられては困るという時があります。

そこで下記のコードを「OnNavigatedTo/NavigationHelper_LoadState」に書いておきます。

Frame.BackStack.Clear();

このAPIで履歴スタックを一括で消せます。

また、あるページに到達した時点で、直前のページには戻したくなく、入力などを行ってるページまで戻したい場合などに、戻す件数を把握してBackKeyが押された際の制御を行うのもアプリの構成としてはありだと思います。

下記のように「Frame.BackStack.RemoveAt」を利用して指定したスタックを削除することもできるので、使い分けるといいでしょう。

            // 画面遷移の履歴スタック数を取得する
            int stackCount = Frame.BackStackDepth;
            for (int i = 0; i < stackCount; i++)
            {
                // 指定した位置のBackコレクションを削除
                Frame.BackStack.RemoveAt(0);
            }

WindowsPhone8.1でカメラ操作(MediaCapture)

WindowsPhone8.1でカメラ操作(MediaCapture)と銘打ちましたが、普通にMediaCaptureを使用したサンプルなどは良くあります。
にもかかわらず、なぜに?となりますが、よくサンプルが出ているのは「WindowsRuntime」ベースのMediaCaptureです。
そこで「WindowsPhone SilverLight 8.1(以下WPSL8.1)」ベースでの解説など行うことにしました。

なぜWPSLで「MediaCapture」なのかですが、「PhotoCaptureDevice」API群がWindowsPhone8.1では非推奨(VS上では使用不可と出る)なためです。

さて、大きな違いですが、WPSL8.1ではUIElementの「CaptureElement」が存在しません。

WPSL8.1では今までの方法同様「VideoBrush」にアタッチする形をとります。
その為のAPIとして「Windows.Phone.Media.Capture.MediaCapturePreviewSink」があります。

			<Rectangle x:Name="PreviewRectangle" Width="450" Height="450" VerticalAlignment="Top" Margin="0,40,0,12" Tap="PreviewRectangle_Tap" >
				<Rectangle.Fill>
					<VideoBrush x:Name="PreviewBrush">
						<VideoBrush.RelativeTransform>
							<CompositeTransform x:Name="previewTransform" CenterX=".5" CenterY=".5" Rotation="90" />
						</VideoBrush.RelativeTransform>
					</VideoBrush>
				</Rectangle.Fill>
			</Rectangle>

定番の方法で「Rectangle」に「VideoBrush」を設定します。
「Rotation=”90″」は入力が90度回転した状態で送られてくるためです。

次にコードの部分です。
基本構成としては「初期化」「プレビューの開始」「プレビューの停止」「解放」となっています。
また、基本以外のところでは「フォーカス」「カメラIDの取得」を行っています。

    public class CameraDevice : IDisposable
    {
        // キャプチャー本体
        private MediaCapture _captureManager;
        // プレビュー用
        private MediaCapturePreviewSink _previewSink;
        // プレビュー判定
        private bool _bPreview = false;

        /// <summary>
        /// Camera Device Initialize
        /// </summary>
        /// <returns></returns>
        public async Task CameraDeviceInitialize()
        {
            try
            {
                // Get DeviceID rear camera
                var devId = await GetCameraId(Panel.Back);

                // 初期化
                _captureManager = new MediaCapture();

                await _captureManager.InitializeAsync(new MediaCaptureInitializationSettings
                {
                    StreamingCaptureMode = StreamingCaptureMode.Video,
                    PhotoCaptureSource = PhotoCaptureSource.Photo,
                    VideoDeviceId = devId.Id
                });

            }
            catch (Exception ex)
            {
                throw new Exception("CameraDeviceInitialize : " + ex.Message);
            }
        }

        /// <summary>
        /// Start PreView
        /// </summary>
        /// <param name="capturePreview">Preview area VideoBrush</param>
        /// <returns></returns>
        public async Task StartPreView(VideoBrush capturePreview)
        {
            try
            {
                if (_captureManager != null)
                {
                    // Preview Sink Initialize
                    _previewSink = new MediaCapturePreviewSink();

                    // Photo Primary
                    _captureManager.VideoDeviceController.PrimaryUse = CaptureUse.Photo;

                    // List of supported video preview formats to be used by the default preview format selector.
                    var supportedVideoFormats = new List<string> { "nv12", "rgb32" };

                    // Find the supported preview format
                    var availableMediaStreamProperties =
                        _captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(
                            Windows.Media.Capture.MediaStreamType.VideoPreview)
                            .OfType<Windows.Media.MediaProperties.VideoEncodingProperties>()
                            .Where(p => p != null
                                        && !String.IsNullOrEmpty(p.Subtype)
                                        && supportedVideoFormats.Contains(p.Subtype.ToLower()))
                            .ToList();

                    var previewFormat = availableMediaStreamProperties.FirstOrDefault();

                    // Start Preview stream
                    await
                        _captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(
                            Windows.Media.Capture.MediaStreamType.VideoPreview, previewFormat);

                    await
                        _captureManager.StartPreviewToCustomSinkAsync(
                            new Windows.Media.MediaProperties.MediaEncodingProfile { Video = previewFormat }, _previewSink);

                    // Set the source of the VideoBrush used for your preview
                    Microsoft.Devices.CameraVideoBrushExtensions.SetSource(capturePreview, _previewSink);

                    _bPreview = true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("StartPreView : " + ex.Message);
            }
        }

        /// <summary>
        /// Stop Preview
        /// </summary>
        /// <returns></returns>
        public async Task StopPreView()
        {
            try
            {
                if (_captureManager != null && _bPreview)
                {
                    await _captureManager.StopPreviewAsync();

                    _bPreview = false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("StopPreView" + ex.Message);
            }
        }

        /// <summary>
        /// I explicitly free
        /// </summary>
        public async void Dispose()
        {
            if (_captureManager != null)
            {
                await StopPreView();
                _captureManager.Dispose();
            }
        }

        /// <summary>
        /// I will confirm the presence or absence rear camera, front camera
        /// </summary>
        /// <param name="desired"></param>
        /// <returns></returns>
        private static async Task<DeviceInformation> GetCameraId(Panel desired)
        {
            //var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

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

        /// <summary>
        /// Execution of focus
        /// </summary>
        /// <returns></returns>
        public async Task SetFocusTask()
        {
            try
            {
                if (_captureManager == null)
                {
                    return;
                }

                foreach (var variable in _captureManager.VideoDeviceController.FocusControl.SupportedFocusModes)
                {
                    Debug.WriteLine(variable.ToString());
                }

                if (_captureManager.VideoDeviceController.FocusControl.Supported)
                {
                    _captureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings { Mode = FocusMode.Auto, DisableDriverFallback = true });

                    await _captureManager.VideoDeviceController.FocusControl.FocusAsync();

                    Debug.WriteLine("focus supported");
                }
                else
                {
                    Debug.WriteLine("focus Not supported");
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("SetFocusTask" + ex.Message);
            }
        }
    }

使用の際は「CameraDeviceInitialize」行って「StartPreView(PreviewBrush)」すると開始されます。
「PreviewBrush」が表示されていない場合は例外が発生しますので注意してください。

「OnNavigatingFrom」でプレビューの停止と解放を行いましょう。
「OnNavigatedTo」に初期化を書いておくことで、復帰の際にも対処可能です。

フォーカスやその他の機能に関しては必ずサポートの有無を確認したうえで、操作を開始しないと未サポートの場合、例外が起きて停止します。

駆け足ではありますが、これでWPSL8.1環境下でもカメラが使用可能です。

ただ使用して思うのは、このAPIでは機能が制限される端末が存在しうることです。
「Lumia 1320」ではフォーカスが可能なのですが「Samsung ATIV S」では未サポートとなります。(旧APIでは使用可能)
これは、使用しているWindowsPhone8.1がDeveloperPreviewであることが原因の可能性もあります。

それでも、明らかに以前より機能が落ちるAPIを使用しなければいけないのは残念です。(「入力画素数」が指定できない等)
もっとも、自分がまだAPIを把握し切れていないために、使いきれていないということもあり得ます。

今後WPSL8.1はOSのバージョンアップなどに伴って、使用可能なAPIが制限されるのではないかと思いますので、アプリを作成する際は、ストアへの登録のしやすさなども考え見ると「universal Apps」を前提として「WindowsRuntime」ベースへ移行していったほうがよいと思います。

もっとも、WinRTでは使用できないAPIが多くあるのも事実ですので、そういったAPIを生かしたアプリを作るのであれば「WindowsPhone SilverLight 8.1」ベースで作りこむのがよいと思います。

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ストアアプリでも使用は可能なはずです。

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」は使用できません。

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

16進カラーコードをColorに変換する

WindowsPhone SilverLight 8.1(以下WPSL8.1)で「Brush」へカラーを設定するときがよくあります。
その際に下記のような形でコード上では設定すると思います。

Brush _brushColor = new SolidColorBrush(Colors.RED);
Brush _brushColor2 = new SolidColorBrush(Color.Color.FromArgb(255,255,0,0));

これで設定していると、HTMLでよくある「#FFFF0000」のような設定ができないことが、不満に感じる時があると思います。
そこで、変換コードを書いてみました。

        /// <summary>
        /// ARGB16進カラーcodeをColorに変換する
        /// </summary>
        /// <param name="colorCode">#00000000</param>
        /// <returns></returns>
        public static Color GetArbgColor(string colorCode)
        {
            try
            {
                // #で始まっているか
                var index = colorCode.IndexOf("#", StringComparison.Ordinal);
                // 文字数の確認と#がおかしな位置にいないか
                if (colorCode.Length != 9 || index != 0)
                {
                    // 例外を投げる
                    throw new ArgumentOutOfRangeException();
                }

                // 分解する
                var alpha = Convert.ToByte(Convert.ToInt32(colorCode.Substring(1, 2), 16));
                var red = Convert.ToByte(Convert.ToInt32(colorCode.Substring(3, 2), 16));
                var green = Convert.ToByte(Convert.ToInt32(colorCode.Substring(5, 2), 16));
                var blue = Convert.ToByte(Convert.ToInt32(colorCode.Substring(7, 2), 16));

                return Color.FromArgb(alpha, red, green, blue);
            }
            catch (ArgumentOutOfRangeException)
            {
                throw new ArgumentOutOfRangeException("GetArbgColor : colorCode OutOfRange");
            }
            catch (ArgumentNullException)
            {
                throw new ArgumentOutOfRangeException("GetArbgColor : \"#\" not found");
            }
            catch (AggregateException)
            {
                throw new ArgumentOutOfRangeException("GetArbgColor : \"#\" not found");
            }
        }

あまりきれいなコードとは言えませんが、上記コードで16進数カラーコードをColorで返すことができます。

Brush _brushColor = new SolidColorBrush(GetArbgColor("#FFFF0000"));

このように書けるので、HTMLで使いたいカラーを引っ張ってきたときには便利ではないかと思います。

今回のコードはWPSL8.1向けとしていますが、WPSL8.0でもWindows Runtimeでもそのまま使えるはずです。