Win2Dを使って2Dゲームを作る場合のメモ的な何か

 別にゲーム作る予定があるわけではないのだけど、ちょっと興味を持ったので調べてみた。Win2Dには、SpriteBatchという、昔のゲーム機やホビーパソコンで使われた「スプライト」に似た機能がある。まあこれ自体はDirect3DやDirect2Dに以前からあって、XNAなどでも便利に使われてたものだけど、UWPアプリ用のDirect2DライブラリであるWin2Dの発表時には含まれておらず、あとからサポートされた。なので、SpriteBatch関連のAPIは、Windows10 November update以降でしか使えないとなっている。

 Win2Dが描画を行うコントロールは、主にCanvasControlと、CanvasAnimatedControlだ。後者は前者にアニメーションのための機能を付けえくわえたものと考えていい。具体的には、一定間隔(デフォルトでは1/60秒間隔)で画面の更新が強制的に行われるようになっており、そのためのイベントハンドラが使える。ここにキャラクターの移動などの処理を描けば、無理なくアクションやシューティングゲームのためのゲームループが作成できるわけだ。というわけで、とりあえずXAML

xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"

と書いてから、Gridの下に

<canvas:CanvasAnimatedControl x:Name ="canvas" Margin="10" Update="canvas_Update" Draw="CanvasControl_Draw" CreateResources="OnCreateResources"  ClearColor="Black"/>

などのように書いて、CanvasAnimatedControlを作成する。CreateResourcesはリソース作成時に呼ばれるので、スプライト用の画像データを読み込むなどするために登録したほうがいい。Updateは1/60秒ごとに呼び出されるアップデートイベントで、これが呼ばれた直後にDrawメソッドも呼び出されるので、Invaridate()とか呼んで無理やり描画イベントを起こす必要もない。

 CanvasのDrawメソッドが呼び出されるとき、引数に

Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args

が入るので、

CanvasSpriteBatch  batch = args.DrawingSession.CreateSpriteBatch();

としてSpriteBatchを作成する。これがなにかというと、Canvasに乗ったレイヤーのようなものだ。スプライトと言っても、ビットマップのキャラクターを登録したら、あとは座標を指定するだけで動き回ってくれるようなものではなく、毎回更新のたびに全スプライトをこのSpriteBatchの上に書き込む必要がある。CanvasSpriteBatchクラスのDrawメソッドを使うのだが、これはあらかじめ用意したキャラクター単一のビットマップ、もしくは歩きパターンなどを複数並べた大きなビットマップ(SpriteSheet)の任意の矩形領域からSpriteBatchに転送することになる。単一ビットマップを使う場合は、CanvasBitmap.Draw()メソッド、SpriteSheetを使う場合はCanvasBitmap.DrawFromSpriteSheet()メソッドを使う。どちらも用途に応じて多くのオーバーロード関数が用意されている。「Draw」となってるから、この時点で画面に表示されそうな気がするが、これはあくまでオフスクリーンで画面を作っている段階で、実際のCanvasへの描画は

batch.Dispose();

で行われる。「え?」と思うでしょ。実際ドキュメントには
Finalizes the sprite batch and submits it to the CanvasDrawingSession.
と書いてあるのでこの理解で正しいはず。まあ、シューティングゲームとかで考えても、敵が数十機出たり、弾幕とで数百個のビットマップをSpriteBatchに書き込むことになる場合もあるのだろうけど、おそらくそのへんうまいことやってくれてあんまし遅くならないんじゃないかな。なんせDirectX系だし(甘いか?)

 それにしてもWin2D、日本語での解説がなかなか見つからないうえに、本家のドキュメントもあまりにシンプルでいろいろ試してみないとわからない。引数の説明がほぼなかったり、まあDirect2Dのドキュメントの該当部分読めってことなんだろうけど…


 とりあえず黒背景で自機を動かしてショットを打つところまでは作ってみた。SEやBGMはネットで拾ってきたフリー素材。

 なお、自機の画像は背景透過のアルファ付きPNGで用意した。2コマしかないが、一応これがSpriteSheetということになる。
f:id:juangotoh:20170619065431p:plain