UWPでMonoGame - 仮想環境ではうまく動かず2021年05月13日 18:48

リリースに向け、ネイティブにコンパイルし、テスト用の環境で動作確認を行うと、画面生成が妙に遅くなったり、止まったままになったりする。XAMLのページから、MonoGameのページに遷移するところ、または、その逆のあたりが怪しい。

別の環境、新しく作り直した環境、仮想環境でない実機、で試してみるが、問題なく動く環境とそうでない環境がある。当たっているKBの違いかと、これも試してみるが、不発。

仮想ハードのCPU設定

このタイミングに依存するような不安定さは、やはり、ハードウェア周りかと、仮想環境のCPU周りを見直すと、「ハードウェアアシストによる仮想化をゲストOSで公開」の項が怪しい。これにチェックを入れると、少し動作が安定する。また、コア数が2よりも4の環境の方が安定する。

仮想環境は、開発に便利だが、ハードウェアに近い操作を行うDirectXなどのアプリでは、落とし穴があると言うことか。リリース版をBuildしてはじめて気がつくので、なかなか厄介。

HubSectionのDataTemplate定義内のRadioButtonやComboBoxの初期設定2021年04月19日 16:27


Hubで構築した設定画面

Hubで構築した設定パネル。設定のHubSectionにおいて、RadioButtonで設定を指定する。HubSectionは、DataTemplateで定義するので、x:Nameで指定した名前を使っては、RadioButtonなどの初期設定を行えない。

そのため、Bindを用いて、コードの値を反映させるのだが、XAMLの初期化時に、初期値(デフォルトの値)でもってCheckedのイベントが発生し、Bindすべき変数の値を、別の値で上書きしてしまう。RadioButtonのほか、ComboBoxなども同様。

ここは、Checkedのイベントの発生を、本来設定したい値をBindしてからにしたいところ。

XAML定義

巷の記事では、XAMLのTreeをたどって初期設定する力業なども紹介されているが、個々のコントロールのLoadedイベントを受けての処理で対処できそう(L.111)。

イベントハンドラ

RadioButtonのLoadedイベントを受けるコードで、IsCheckedを設定して、roamingSettingsなどから読み取った値を初期値として設定(L.200)。その後、Checkedのイベントが発生するが、先ほど設定した初期値でのイベントなので、別の値で上書きされない。

UWPでMonoGame - 日本語表示でSurrogate Pairに苦戦2021年04月13日 16:14

MonoGameで日本語を表示する方法は、あちこちに記事がある。

FontProcessor

MGCB EditorでSpriteFont定義に設定するProcessorをDLLとして作成。漢字やかなの入ったテキストファイルから一文字ずつ取り出し、FontDescriptionに登録。,NET Core 3.1のDLLのプロジェクトで作成したもので登録成功。

SpriteFont生成

常用漢字について実施したもの。左の"Processor"欄で、作成したProcessorを登録する。規格が合っていないと候補に出てこない。実行には、そこそこ時間を要す。

Surrogate Pair生成失敗

それではと、難読漢字の入ったテキストファイルを取り込んでみると、エラー。
Surrogate Pair (2バイトのコード2つで一文字を表現)
をバラバラに登録しないでね、Char配列で渡してね、と。

ところが、FontDescriptionに登録できるのは、Char型のみ。MonoGameのForumなどを覗いても、影響が大きいので対応は難しそう、とのこと。

LoadContent

それではと、先のForumでも触れられていた、FontStashSharp(SpriteFontPlus)を試してみる。コメントアウト済みだが、L.190あたり。LoadContent()では、フォントファイルを登録。

DynamicSpriteFont

Draw()では、DynamicSpriteFontを定義して、描画(L.566-567)。Surrogate Pairは試さなかったが、日本語表示は問題なくできる。

問題は、配布Packageにフォントファイルを同梱しなければいけないこと。IPAフォントのライセンスを読むと可能ではあるが、サイズも大きくなるし、どうしよう。UWPでなく、WPFにすれば、システムフォントを読み込めるかも。そもそも、今まで使ってきたUDデジタル教科書体を使いたい。

Win2DでTexture2D生成

結局、実行時に、Win2DでCanvasDeviceに日本語文字を書き込み(L.164)、Stream経由でTexture2Dを生成(L.182)することで対処。PutText()は縦書き表示のためのもの。

MGCB Editorで事前生成するわけではないので、実行時、それなりに時間を要する。ゲーム実行時のスコア表示などには向かないが、ゲーム開始前に作っておけば済むものなら使える。

UWPでMonoGame - GameからXAML Pageへの復帰2021年04月08日 18:42

UWPでXAMLのPage(GamePage)から、引数付きでMonoGameのGameを起動することができた。次は、Gameから元のXAMLのPageに復帰する。

例外発生

Gameの終了は、Dispose()を呼び出せばよいようだが、UnhandledExceptionが発生し、アプリが終了してしまう。OnNavigatedFrom()に記述したデバッグ文が呼び出されているところから、XAMLのPageに戻ってはいる様子。

ログを見ると、Gameオブジェクトがなくなったのに、Mouse周りのイベントが刈り取られず、イベントの宛先がNullであると言っている(Disposeしたから当然だが)。これが致命傷になり、アプリの継続が不可になっている。

ちなみに、Exit()を呼び出すと、GamePageに戻ることなく、アプリが終了する。

イベント受信

本来は、MonoGame側の対処を望みたいところだが、何とか先に進めてみる。まず、Gameの終了をGamePage側から行うため、イベントを自作し、ゲームの終了をGameからGamePageに伝える。

そこで、GamePageを起動したMainPageにGoBack()で遷移する(L.70)。UIとは別Threadに居るので、Dispatcher.RunAsync() 経由。念のため、例外発生前に遷移指示を済ませる。

その上で、GameをDispose()する(L.84)。一つ前のSuppressDraw()は例外抑止に効果なし。発生するUnhandledExceptionは、ここのtry/catchでは拾えない。

例外ハンドラ登録

UnhandledExceptionを拾うために、App.xaml.csにハンドラを登録(L.32,33)。2つ登録しているが、MonoGameの例外を拾うのは、CoreApplication.UnhandledErrorDetectedの方。

例外ハンドラ

ハンドラの実体。CoreApplication.UnhandledErrorDetectedを受けるのは、CatchCoreUnhandledException()の方(L.133)。引数のargsには、Messageがないので、Propagate()で改めてThrow(L.147)。このあたりは、atmarkitの記事を参考に。

記事にあるように、VisualStudioのプロジェクトのPropertyで、条件付きコンパイルシンボルを設定しないと、Debugモードの実行では、アプリのハンドラの代わりにVisualStudioのデバッガが例外を捕まえるので注意。

Null Reference例外

すると、例外の実体が、NullReferenceExceptionであることがわかる。

こうして、UnhandledExceptionを受けとめると、例外でアプリが落ちることなく、GamePageから遷移したMainPageが無事に表示される。とりあえずは、これで先に進める。

UWPでMonoGame - Gameオブジェクトへの引数渡し2021年04月08日 13:58

以前作成したXAMLベースのゲームアプリ(UWP)の使い勝手を改善しようと、ゲームエンジンの導入を考える。一度アプリ構築に使用したUnityが第一候補になるが、もう少し手軽で、XAMLページとの連携ができそうなMonoGameを試してみる。

引数の設定

MonoGameのUWP対応のプロジェクトを作成すると、生成されるコード群に、GamePage.xaml.csがあり、MonoGameの環境を生成するコードがある(L.40)。XamlGame<T>.Create() の部分。

最初の引数に parameter がある。設定のしかたは、"key:value"の形。複数ある場合は、空白で区切る。このあたり、MonoGameの文書に説明がなく、試行錯誤。

引数の取込

parameterの受け取りは、ゲーム本体のClass(Gameを継承)のConstrucorで行う(L.85)。Game.LaunchParameter(L.91)というCollectionに入っているので、foreachで取り出す。こちらは、Gameクラスの説明にある。

Navigateでの引数設定

実際の活用は、App.xaml.csからGamePageを呼び出す処理を変更し、別に用意するMainPageを介してGamePageに遷移するようにする。この時、MainPage→GamePage→MonoGameに引数を渡す。こうすれば、MainPageにゲーム選択や各種設定などのUIを担わせることができる。

MonoGameで各種UIを作成することもできなくはないが、いろいろな部品は手作りになる。

The Fourteenth Labのアプリ一覧2021年03月18日 09:00

●Windows Storeで配信中のアプリ

Storeの運営により、予告なく配信が停止される場合があります。

UPnP音楽再生指示
UPnP音楽再生指示

UPnP(若しくはDLNA)の仕組みを利用して、楽曲を管理するサーバ(コンテンツのディレクトリ)上のプレイリストについて、音楽を再生する機器(メディアレンダラー)に再生を指示するアプリです。これにより、Windows10が動作する機器(主にmobileを想定)を一種のリモコンのように利用することができます。


お散歩コンパス
お散歩コンパス

散歩などに持ち歩くコンパスと傾斜計の機能を提供します。インターネットが利用できる環境では、今いる位置を中心に国土地理院地図を開くことができます。また、適宜、現在位置を記録することで、簡易ですが、経路を表示できます。


ながら見Web
ながら見Web

常時、見ておきたいWebサイトを、主たる作業の妨げにならないように、小さな画面にまとめて表示します。天気概況や地震速報のように、ざっくりとした状況を把握できればよいサイトの表示を想定しています。


ほそ道まっぷ
ほそ道まっぷ

紀行文に記された地名を一覧から選択し、地理院地図とGoogle Mapで地形や史跡を確認しながら、読書を支援するアプリです。地形を合わせ見ることで、山あいを旅したのか、川沿いに進んだのか、荒野を縦断したのか、など、旅の風景が見えてきます。

奥の細道、東関紀行、海道記、を掲載します。


和書体
和書体

UWPアプリで利用できる日本語フォントを一覧し、例文を見ながら、実際の見え方を確認します。


四則演算パズルU
四則演算パズルU

四則演算ボタンと計算順ボタンを組み合わせて、0から9までの整数を求めるパズルです。


漢字合わせパズル
漢字合わせパズル

同じ漢字の書かれた二枚のカードを見つけていくパズルです。学年別の漢字のほか、部首別の漢字、県別の駅名を合わせるゲームがあります。


火山壁紙
火山壁紙

気象庁の火山監視カメラが提供する火山画像をWindowsの壁紙に設定します。

一覧に用意しているのは、サイトが提供する全ての火山についてではなく、解像度が高く、空が広く、電線などの障害物が少ないものを抜き出しています。


献血記録
献血記録

献血のあとに送付される検査成績を記録し、次回の献血の予定を立てたり、検査結果の推移を体調管理に役立てることを意図しています。


画像微調整
画像微調整

写真やイラストなどの画像について、サイズ変更、回転、鏡像変換、切り抜き、任意の4点からなる四辺形からの長方形への変形、明度と彩度の調整、選択した矩形のモザイク化など、ブログ記事作成などで必要となる簡易な画像調整機能を提供します。


画面属性と制御
画面属性と制御

モニタに関する情報取得と電源制御(オフ)を行うユーティリティです。
マルチディスプレイ環境では、全てのモニタの電源を切ります。


直角取り
直角取り

麻雀牌を使った一人遊びを元にしたゲームです。36牌(4x9漢字牌)、72牌(6x12漢字牌)、144牌(8x18漢字牌)、136牌(8x17麻雀牌)、4つの盤があります。漢字牌では、画数が多く紛らわしい漢字を用いて、ちょっと意地悪になっています。

条件を満たす同じ表示の牌を取っていき、盤上から全ての牌を取り除けば、ゲームクリアです。取れるのは、隣り合う場合、同じ直線上にある場合、一度だけ直角に曲がって四辺のいずれかを接することが出来る場合、の3つです。ただし、2つの牌の経路上に邪魔する牌があってはいけません。


統計電卓
統計電卓

キーパッドから登録した数値や、タブ区切りテキストから読み込んだ数値について、平均や分散などの記述統計と、2次元データの相関および回帰の分析を行います。


音量一覧選択
音量一覧選択

システムボリュームを一覧から選択して設定するユーティリティです。

動画や音声の配信では、番組毎に音量のレベルがまちまちですが、都度、システムのボリュームを調整するのではなく、あらかじめ登録してある設定を一覧から選択できるようにします。


●配信を停止したアプリ

Windows Storeで配信をしていましたが、現在、配信を停止しています。

Network Time
Network Time

ネットワーク時刻を提供するサーバから時刻情報を取得し、本機の時刻とのずれを確認します。


部屋の中の水分量U
部屋の中の水分量U

部屋の室温、湿度、容積から空気中の水分量を求めます。また、加湿する場合に必要な水分量、除湿する場合に取り除く水分量を求めます。


SubnetDesigner
Subnet Designer U

IPv4のSubnetの設計において、必要なSubnetの数と1つのSubnetが収容するホスト数をもとに、最適なSubnetを求める作業を支援します。


からだを動かすリズム計
からだを動かすリズム計

身体を動かす際などにリズムを取るためのものです。ストレッチ運動などをする際に、リズムを崩さないようにする手助けとなることを想定しています。

一回の動作の拍数(1~4)と、目標の動作数を設定すると、図形の動きと音でリズムを取ります。たとえば、1回の動作を2拍で行い、30回を動作数に設定すると、2拍のリズムを30回の区切りで実行します。1拍の時間は、0.5~3秒の間で設定できます。


トーンと色の見本帳
トーンと色の見本帳

Windowsアプリの色デザインの補助のために、Windowsの定義色について、PCCSのトーン、色相、明度、彩度を概算し、トーンマップ上の位置を示します。また、PCCSの色について、RGB(ARGB)値を算出し、それに近いWindowsの定義色を求めます。


●Windows8.1向けのアプリ

2021年3月18日、配信を停止しました。

Windows10でも動作するため、配信が継続されていますが、安定性を考え、Windows10向けに作成した版をご利用ください。

四則演算パズル
四則演算パズル


部屋の中の水分量
部屋の中の水分量


.NET5.0 の WPF App - Bind、UWPやWindowsForms APIの利用2021年02月20日 16:31

LogoVistaの辞書アプリを利用しているが、ブラウザの文書からコピーして、貼り付けて、検索ボタンを押す、という一連の作業が、少々面倒。手間を省くために、UI Automationを利用してみようと、WPFアプリに着手。

WPF App

プロジェクトを追加しようとダイアログを開くと、.NET Framework用のWPFと、.NET用のWPFが出てくる。後者は、.NET5.0からのもの。UWPの改善点がフィードバックされているとのことで、後者を選んでみる。

Binding

まずは、便利だけど、いつも悩ましいBind。"x:Bind"は使えない。

DataContextの設定

ただし、ListViewなどにCollectionをBindするのに、XAMLにCollectionViewSourceの定義は、必ずしも要らなくなった。コードで、ListViewなどのDataSourceを設定すれば済む。このあたり、MSの文書にもいろいろあるが、このやり方が素直に思う(L81~)。

Resorucesの参照

次に、Resourcesの参照。UWPのx:UidでLocalizationも含めて対応、というのはまだ。ただ、"x:Static"で簡単に参照できるようになっている。

プロジェクトの定義

UWP APIの利用方法も進化中。これまでは、プロジェクトの参照に各種設定していたが、プロジェクトの定義に一行追加するだけでよくなった。"<TargetFramework>"の箇所。ただし、Windows10 1809以上の対応になる。また、GUIで設定はできない。

WindowsForms APIの利用

同じように、WindowsForms APIの利用は、"<UseWindowsFroms>"を設定する。これなしでは、Build時に名前解決に失敗する。SendKeysの利用で嵌まった。

GUIのプロジェクト定義

なお、これらの設定をすると、プロジェクト定義のGUIのフレームワークの箇所は、未選択状態になる。

MergedDictionaries

他には、"MergedDictionaries"の定義ができるようになった。これで、Styleの定義などがやりやすくなる。

UWPでバックグラウンド処理を時間間隔で起動2021年02月09日 11:41

UWPでバックグラウンド処理を用意し、一定時間間隔で起動する手順は、MSやStack Overflowあたりでも、かなり詳しく説明されている。とはいえ、あちこちの情報を整理して実装する必要があるので、備忘までに。

Register

バックグラウンド処理の登録。
・時間間隔起動なのでTimeTriggerの用意。(L.166)
・サイトから画像を取り込むので、インターネットが使えることを条件に設定。(L.171)
・UIが開いているときは、情報を更新する必要があるので、完了時のハンドラを登録。(L.178)
・バックグラウンド処理に渡す情報を、ApplicationData.Current.LocalSettingsを介して渡す。ここでは壁紙に設定する火山のコード。(L.180)

BG Run

バックグラウンド処理の本体。起動するとRunが呼び出される。

OnCompleted

バックグラウンド処理が完了したときに、ハンドラから呼び出される処理。別スレッドにいるので、Dispatcher.RunAsyncで処理。UIを更新。

AppResuming

アプリのUIが最小化されているときは、フォアグランドの処理は中断(Suspend)されているので、上のOnCompletedでは、処理されない。中断が解除されたときにハンドラから呼び出される処理にて、改めてUIを更新。

UpdateUI

UIの更新処理。バックグラウンド処理が更新した情報をApplicationData.Current.LocalSettingsを介して返してもらう。基本的な型しかサポートされていないので、Classの中身をバラして設定。ここでは、ダウンロードして保存した、壁紙に用いる画像ファイルの情報。フォアグラウンドとバックグラウンドでは、同じClassでも異なるobjectになっているので、情報を同期する。