解説(後半)
描画
描画については今回はSpriteを利用します。このスプライトは「Device」の作成後にあらかじめ作っておいてください。
sprite_ =new Sprite(device_);
「Device」を引数にとります。その他の細かい設定はありません。ただし、デバイスの消失時には、解放、再取得が必要です。サンプルではそもそもデバイスの消失に対応していないので考えないことにします。
描画については以下のコードで行っています。
/// <summary> /// 描画処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void video__TextureReadyToRender( object sender, TextureRenderEventArgs e) { //クリア処理 device_.Clear(ClearFlags.Target,Color.Black,1.0f,0); //シーンのスタート device_.BeginScene(); //スプライトのスタート sprite_.Begin(SpriteFlags.None); //テクスチャを描画するの時のセンター座標 Vector3 center = new Vector3(0,0,0); for(int i=0;i<puzzleSize;i++) { for(int j=0;j<puzzleSize;j++) { //nowPositionの部分は描画してはいけないのでif文でチェック if(nowPosition.X != i || nowPosition.Y != j) { //描画する位置を求める Vector3 pos = new Vector3( videoSize.Width * j / (float)puzzleSize ,videoSize.Height * i / (float)puzzleSize ,0); //mapに入っている座標を利用してテクスチャから //指定の部分だけ抜き出して描画する sprite_.Draw(e.Texture,map[i,j], center,pos,Color.Transparent); } } } //スプライト終了 sprite_.End(); //描画終了 device_.EndScene(); //プレゼント device_.Present(); }
描画は宣言通り「Sprite」で行っています。Sprite#Draw()は次のように引数をとります。
public void Draw( //描画するテクスチャ Texture srcTexture, //テクスチャを抜き出す範囲(UV座標ではなくピクセル単位) Rectangle srcRectangle, //スプライトの中心。今回は『左上隅を表す(0,0,0)』 Vector3 center, //スプライトの位置。16パズルなので、それぞれの場所の座標をセット Vector3 position, //色とアルファ値を調整する。『Color.Transparent』を選択すると //元のアルファ値と色で表示する Color color );
このとおりです。描画位置のposはpuzzleSizeに応じた値に計算しておきます。それと、centerはすべて(0, 0, 0)なので、あらかじめループ外で作っておきます。
再生処理
今回のゲームは動画1回転分で終わるとは限りません。そのため、動画をエンドレスで再生します。この動作は簡単に書けます。
まず、「Video.Ending」というイベントにメソッドを追加します。
video_.Ending +=new EventHandler(video__Ending);
再生が終わると、これが呼び出されるようになります。ここで巻き戻し処理と再生処理を行います。
private void video__Ending(object sender, EventArgs e) { Video vid = (Video)sender; vid.Stop(); vid.Play(); }
一度ストップするとビデオは巻き戻しされます。その後はPlay()で再び再生します。
ここではくれぐれもRenderToTexture()を呼び出さないでください。これは、指定したデバイスにテクスチャの出力を指示するためのメソッドなので、一回呼び出せば次の再生時にも適用されます。
後処理
ビデオの再生はフォームが閉じただけでは終了しないので、しっかりと処理を書く必要があります。
private void Form1_Closed(object sender, System.EventArgs e) { if(video_ !=null) { video_.Stop(); video_.Dispose(); } if(sprite_ !=null) { sprite_.Dispose(); } if(device_ !=null) { device_.Dispose(); } }
ついでに「Sprite」と「Device」の処理もしておきましょう。
その他
- フォームは固定サイズにしておいてください。再生中にフォームのサイズが変わるとビデオの再生が止まります。
- ビデオの初期サイズは
Video.DefaultSizeに入っています。 - Deviceを作る際、
DeviceTypeが「NullReference」や「Reference」だと上手くいかないようです。素直に「Hardware」を選択してください(厳密に確認したわけではないので、成功する可能性もあります)。
まとめ
詳しくはソースコードのコメントを参照してください。データ構造がちょっとおかしいかもしれないので、1から作ってみるのも良いと思います。
これができたら次はジグソーパズルです。マウスでつかんでぐりぐり動かせるようなすごいものをぜひ作ってみてください。
参考資料
- DirectX 9.0 SDK Update (October 2004)日本語
