がりらぼ

WindowsRuntimeの応援ブログ

Raspberry piでDDNSのIPアドレスを自動更新する何かを作った

VPN接続したかったのでIPの更新をなんとかしたかった。固定IPやBuffalo DDNSに契約するほどのお金はなかった。

Windowsが常時起動してればDiceみたいなソフトでいけるっぽいけどWindowsを常時起動させる電気料金を払うにはお金がなかった。

ラズパイがほこりかぶってたけど消費電力すくなそうだしこいつにDDNSのIPを更新してもらうことにしました。

とりあえずフリーのDDNSドメインを取得できるサイトということで今回はMydnsでドメインを頂きました。

あとはラズパイから定期的にAPIを叩けばいいだけ

とりあえずイーサネットにつなげたラズパイにこのシェルスクリプトを入れます。

#!/bin/bash
user=yourid
pass=yourpass
wget --http-user=${user} --http-passwd=${pass} http://www.mydns.jp/login.html

mydnsはHttpGetするだけでアクセスしてきたIPを打ち込んでくれるすばらしいAPIがあったのでwgetだけで出来ました。

そんでもってシェルスクリプトに実行権限を付与

$ chmod u+x シェルスクリプトのパス

crontabに登録。今回は6時間毎にしてみました。

* */6 * * * root シェルスクリプトのパス

ほこりかぶってたラズパイが生きる意味を見つけれたので結構よかったんじゃないかと思います。がんばれラズパイ

f:id:garicchi:20150520001207j:plain

C#のクロスプラットフォームゲームライブラリっぽいものを作りました

このタイトルだとまるで僕がクロスプラットフォームに対応させた見たいに見えますが簡単に言うとMonoGameでもっとゲーム作りやすく(なるかもしれない)フレームワークです。

機能

今のところこんな感じの機能を持っています

  • 画面管理
  • ゲームオブジェクト管理
  • クロスプラットフォームコード共通化
  • マルチデバイス解像度対応
  • セーブデータ管理
  • リソースロード管理
  • アニメーション管理
  • 入力管理
  • ゲームUI
  • 画面遷移トランジション
  • ビットマップフォント
  • 通知管理

使い方

ドキュメントを頑張って書きました。

CobaltFrameによるクロスプラットフォームゲームプログラミング入門 | Shiztex

ある程度C#を知っている人と、MonoGame(XNA GameFramework)についてある程度の知識が無いと読むのが難しいかもしれません(かなりいそいで書いたので)

そのうちサンプルもたくさん出していきたい。

クロスプラットフォーム

一応MonoGameのフレームワークなのでMonoGameが対応しているiOS,Andoird,WindowsStore, WindowsDesktop,Linuxなどに対応しているはずです。

VS2013ではXamarin拡張機能が必要です。 XamarinStudioさえ入れればMacでも動きます。

ただしWindowsPhoneだけは謎のエラーが出るのでWindows10を待つことにしました。

リポジトリ

まだまだバグがたくさんあります。

一緒に開発するよ!って人いたらぜひプルリク送ってくれたらうれしいです。

github.com

第三回CenterCLRでちょこっと話してきました

CenterCLRさんにお邪魔するのは初でしたが自宅から(比較的)近いのでちょっと遊びに行ってきました。

centerclr.doorkeeper.jp

もっとドライな勉強会かとおもいきや、登壇者だけでなく参加者同士が活発にディスカッションがされたり勉強会中にチョコが飛び交ったり深い闇に触れる面白い勉強会でした。

今回はLTということで発表させてもらいました。

今後のWindowsAppsのインディーズゲームプログラマのプラットフォームとしての可能性を伝えれたと思います。

WindowsRuntimeのIAsyncInfo非同期メソッドサンプル

WIndowsRuntimeの非同期メソッド

非同期メソッドといえば.NetのTaskがわかりやすいのでストアアプリでもよく使うけどそういえばWindowsRuntimeには特有の非同期メソッド用のインターフェースがある。

それがこの4つ

f:id:garicchi:20150509194332p:plain

  • IAsyncAction
  • IAsyncActionWithProgress
  • IAsyncOperation
  • IAsyncOperationWithProgress<TProgress,TResult>

4つすべてがIAsyncInfoというインターフェースを継承している。
IAsyncInfoは非同期処理をキャンセルすることをサポートしている。

よって、4つの非同期メソッド用のインターフェースはすべてキャンセル処理をサポートしていることになる。
個々の機能は上の画像のとおり。Actionがつくと戻り値なし、Operationがつくと戻り値あり、WithProgressで進捗サポートという感じ

非同期メソッドの作成方法

.NetのTaskで非同期メソッドを作る場合、Task.Runメソッドを使って非同期処理を作る。

private Task StartTaskAsync()
{
    return Task.Run(() =>
    {
        //すごく重い処理
    });
}

ではIAsyncではどうするのかというとAsyncInfo.Runメソッドを使う。
内部でTaskを内包する形になるのでイメージとしては.NetのTaskにキャンセルや進捗報告をサポートした奴という認識のほうがいいかもしれない。

private IAsyncAction StartAsyncActionAsync()
{
    return AsyncInfo.Run((token) =>
    {
        return Task.Run(() =>
        {
            //すごく重い処理
        });
    });
}

実行時はSystem.WindowsRuntimeSystemExtensionsクラスにあるGetAwaiterメソッドとやらのおかげで非同期メソッドとしてTaskと同じようにawaitすることができる。

await StartAsyncActionAsync();

キャンセル方法

IAsync非同期メソッドをキャンセルさせるにはキャンセルリクエストを受け取って自分でキャンセル処理を書く必要がある

たとえばこんなHttpClientで20回google先生をダウンロードする非同期メソッドの場合
キャンセルリクエストが発行されていることを確認したならreturn非同期メソッドを中断する。

private IAsyncActionWithProgress<int> StartAsyncActionWithProgress()
{
    return AsyncInfo.Run<int>((token,progress) =>
    {
        return Task.Run(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                //キャンセルリクエストが発行されているなら
                if (token.IsCancellationRequested)
                {
                    //終了
                    return;
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                    //進捗報告await
                    progress.Report(i);
                }
            }
            
        });
    });
}

キャンセルしたい場合は実行中にIAsyncInfoのCancelメソッドを呼べばいい

var asyncTask = StartAsyncActionAsync();

//キャンセル
asyncTask.Cancel();

await asyncTask;

進捗報告方法

WithProgress系の非同期メソッドを作ったなら進捗報告ができる(する必要がある)

AsyncInfo.RunのTには進捗報告をする値の型を指定する するとIProgressがもらえるのでReportメソッドを実行すると進捗報告ができる

private IAsyncActionWithProgress<int> StartAsyncActionWithProgress()
{
    return AsyncInfo.Run<int>((token,progress) =>
    {
        return Task.Run(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                    //進捗報告
                    progress.Report(i);
                }
            }
            
        });
    });
}

進捗報告を確認するには呼び出し側でAsyncOperationProgressHandlerを用意する

var asyncTask = StartAsyncOperationWithProgress();
asyncTask.Progress = new AsyncOperationProgressHandler<string,int>((asyncInfo, progress) =>
{
    //Progress.Reportが呼ばれた時
    Debug.WriteLine(string.Format("進捗{0}%です!",progress));
});

var result = await asyncTask;

非同期メソッドサンプル

ということでWindowsRuntimeの4つの非同期メソッドを作ってみた例。
使いたいときはTask.Run内をテキトーに変更すればOKなはず。

/// 返却値なし、進捗報告なし非同期メソッド(IAsyncAction)
private IAsyncAction StartAsyncActionAsync()
{
    return AsyncInfo.Run((token) =>
    {
        return Task.Run(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                }
            }
            
        });
    });
}

/// 返却値なし、進捗報告あり非同期メソッド(IAsyncActionWithProgress)
private IAsyncActionWithProgress<int> StartAsyncActionWithProgress()
{
    return AsyncInfo.Run<int>((token,progress) =>
    {
        return Task.Run(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                    //進捗報告
                    progress.Report(i);
                }
            }
            
        });
    });
}

/// 返却値あり、進捗報告なし非同期メソッド(IAsyncOperation)
private IAsyncOperation<string> StartAsyncOperationAsync()
{
    return AsyncInfo.Run<string>((token) =>
    {
        return Task.Run<string>(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return "キャンセルされました";
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                }
            }
            return "返却値";
        });
    });
}

/// 返却値あり、進捗報告あり非同期メソッド(IAsyncOperationWithProgress)
private IAsyncOperationWithProgress<string,int> StartAsyncOperationWithProgress()
{
    return AsyncInfo.Run<string,int>((token, progress) =>
    {
        return Task.Run<string>(() =>
        {
            //すごく重い処理
            for (int i = 0; i < 20; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return "キャンセルされました";
                }
                else
                {
                    var client = new HttpClient();
                    client.GetStringAsync("http://google.co.jp").Wait();
                    //進捗報告
                    progress.Report(i);
                }
            }
            return "返却値";
        });
    });
}

サンプルアプリ

ついでにサンプルアプリもつくっといた

f:id:garicchi:20150509200607p:plain

IAsyncSample.zip

VisualStudioのサンプルコードをアップロードするときに余計なファイルを削除してサイズを小さくするPowerShellスクリプト

Gitとかなら.gitignoreでフィルタリングしてくれるんですけどね。

自分でzipで圧縮したサンプルコードを公開したいと思った時とかDebugフォルダとかipchとか削除しないと数100MBになります。

というわけで余計っぽいファイルを削除してくれるPowerShellスクリプトをつくった

Get-ChildItem $args[0] -Recurse | Where-Object{($_.Name -eq "Debug") -or ($_.Name -eq "bin") -or ($_.Name -eq "obj") -or ($_.Extension -eq ".sdf") -or ($_.Name -eq "ipch")} | ForEach-Object{Remove-Item $_.FullName -Recurse -Force}

Where-Object内の条件を変更すれば好きな邪魔ファイルを削除できます。

Windows10 Build10074に新しい日本語合成音声が2つ出来て、将来の日本語Cortanaさんの声候補かもしれない件

新しい合成音声

Windows10のInsider Preview、かなりさくさく動くのでBootcampに入れて遊んでたら、設定の音声合成に見たことない名前の音声合成が加わっていました。

f:id:garicchi:20150508162252p:plain

加わったのは以下の2つ

今まで日本語音声合成は「Haruka」という合成音声が担っていました。

しかし今回、Harukaはなくなり*1、新たにAyumiちゃん*2とIchiroくんが加わりました。

Ayumiの声はこんな感じ

Ichiroはこんな感じ

今までと何が違うんだ?って感じの方が結構いると思うのでHarukaの声はこんな感じです。

若干劣化した?Ayumiちゃんの声高い声でサイコーっす。

まあでも、新しく音声合成が加わったということは、Cortanaさんの声がこれになる可能性が大いにあるということですね。*3

Windows10では音声アシスタントも売りの一つとするっぽいので頑張ってほしいところです。

おまけ

SpeechSynsesizer API使えました。

好きな声を喋らせることができます。Windows10 Build10074入れてる人は是非VS2015入れてアプリ作ってみてね!

XAML

<Page
    x:Class="SampleSynthesizer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SampleSynthesizer"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Button x:Name="button_speech" Content="話す" HorizontalAlignment="Left" Margin="511,327,0,0" VerticalAlignment="Top" Height="29" Width="63" Click="button_speech_Click"/>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="131,165,0,0" TextWrapping="Wrap" Text="こんにちは、私はWindows10 の新しい日本語音声合成です。どうぞよろしく" VerticalAlignment="Top" Width="342" AcceptsReturn="True" Height="184"/>
        <ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="232,97,0,0" VerticalAlignment="Top" Width="203"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="131,98,0,0" TextWrapping="Wrap" Text="音声を選択" VerticalAlignment="Top"/>

    </Grid>
</Page>

C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.SpeechRecognition;
using Windows.Media.SpeechSynthesis;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace SampleSynthesizer
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        MediaElement _mediaElement;

        public MainPage()
        {
            this.InitializeComponent();

            _mediaElement = new MediaElement();

            comboBox.ItemsSource = SpeechSynthesizer.AllVoices.Where(q => q.Language == "ja-JP").Select(q => q.DisplayName).ToList();
            
        }

        private async void button_speech_Click(object sender, RoutedEventArgs e)
        {
            
            var synthesizer = new SpeechSynthesizer();
            synthesizer.Voice = SpeechSynthesizer.AllVoices.ElementAt(comboBox.SelectedIndex);

            var stream = await synthesizer.SynthesizeTextToStreamAsync(textBox.Text);

            _mediaElement.SetSource(stream, stream.ContentType);

        }

        
    }
}

*1:Harukaちゃんェ...

*2:擬人化はよ

*3:Cotranaが日本に来ればの話

MonoGame3.4でWindows10UAP用のゲームを作る

MonoGame3.4がBuildの日にリリースされたらしくもうWindows10UAPに対応してました。

MonoGame 3.4 | MonoGame

公式より速いってどういうことだってばよ...

ってかんじですがもう公式ゲーム開発環境でもいいんじゃないですかねMonoGame。

とりあえず試してみましょう。

以下からMonoGame3.4 for VisualStudioをWindows10 Insider Preview Build10074に入れます。

MonoGame 3.4 | MonoGame

そして新規プロジェクトのMonoGameのところを見るとWindows10 UAP*1があります。

f:id:garicchi:20150507020345p:plain

プロジェクト構造を見るといつもどおりのMonoGameの構造でした。

f:id:garicchi:20150507020454p:plain

ただGamePageのSwapChainPanelのタグ構造がちょっと変わってました。

実行してみるとちゃんとできた。*2

f:id:garicchi:20150507020514p:plain

Windows8.1のShardProjectでユニバーサルアプリつくってたら結構めんどくさかったので早くWindows10リリースされて欲しいですね。

*1:UAPよりWindowsAppsって名前がいいなぁ

*2:WindowsPhoneもやりたかったけどHyper-Vの入れ子でプロセッサ足りなくて死んだ