SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

ビデオファイルを基にした16パズルの作成

スプライトを利用して動画の一部分だけを描画する

解説(後半)

描画

 描画については今回は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()は次のように引数をとります。

 オーバーロードされているので1つだけ説明しています。
public void Draw(
    //描画するテクスチャ
    Texture srcTexture,
    //テクスチャを抜き出す範囲(UV座標ではなくピクセル単位)
    Rectangle srcRectangle,
    //スプライトの中心。今回は『左上隅を表す(0,0,0)』
    Vector3 center,
    //スプライトの位置。16パズルなので、それぞれの場所の座標をセット
    Vector3 position,
    //色とアルファ値を調整する。『Color.Transparent』を選択すると
    //元のアルファ値と色で表示する
    Color color
);

 このとおりです。描画位置のpospuzzleSizeに応じた値に計算しておきます。それと、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から作ってみるのも良いと思います。

 これができたら次はジグソーパズルです。マウスでつかんでぐりぐり動かせるようなすごいものをぜひ作ってみてください。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

利都(りと)

陸奥でプログラムをしている学生。LOGOからVB6.0へ。現在は主にC系言語を利用。Atelier BlueにてManaged DirectXについてのTipsを書いている。http://www.atelier-blue.com/IL(CIL,MSIL)もしているのでそちらに興味がある方もどうぞ。Manag...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/350 2006/05/15 12:58

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー