Windows Phone XNAでアニメーション – ぐるぐる


この投稿では、Windows PhoneでGameなどの高機能なグラフィックスを必要とするアプリケーション開発に最適な、XNA Frameworkを使って、テクスチャイメージを一定の速さで変形させる方法を解説します。

ここでは図のテクスチャを一定速度で回転させるアニメーションをベースに説明を行います。

この画像は、PowerPoint 2010で、フリーハンドでぐるぐるを描いて、図としてPNGで保存したものです。背景が透明なので他の描画に重ねることができます。好きな画像を用意してください。

次に、Windows Phone SDKをインストールしたVisual Studioを起動して、XNA Game Studio 4.0のWindows Phone ゲーム(4.0)という名前のテンプレートで新しくプロジェクトを作成します。名前を仮にWPGuruGuruとしておきます。

作っておいた図を、新しく作成されたプロジェクトのフォルダーWPGuruGuruContentにコピーします。

そして、WPGuruGuruのソリューションエクスプローラーで、新しく作成されたソリューションの2つのプロジェクトのうち、お尻にContentがついたプロジェクト(ここではWPGuruGuruContent)をマウスで右クリックし、”追加”→”既存の項目”を選択して、この画像ファイルをこのプロジェクトに追加します。画像ファイル名は、GuruGuru.pngとしておきますね。

WPGuruGuruプロジェクトのGame1.csのGame1クラスのメンバー変数として、

private Texture2D guruguruTexture;    // 画像を保持する為のメンバー変数
private float angle;                                // 画像を描画する時の角度
private float deltaAngle;                        // 画像角度を更新する際の単位角度

を追加します。

そして、Game1クラスのLoadContentメソッドに、以下のコードを加えます。

guruguruTexture = Content.Load<Texture2D>("GuruGuru");

XNAの場合、(デフォルトで)毎秒30回、描画内容の更新(Updateメソッド)、描画(Drawメソッド)がコールされます。Updateメソッドで、angleにdeltaAngleを足して、360度を超えたら、360度の剰余を代入して、angleを順次更新していきます。そして、Drawメソッドで、そのangleの角度でテクスチャ画像を描画すれば、ぐるぐる回っているアニメーションの出来上がりです。なので、Initializeメソッドでangleを0、deltaAngleを10で、初期化しておいて、

Updateメソッドで、

angle += deltaAngle;
if (angle >= 360) angle %=360;

と描いておき、Drawメソッドで、

Vector2 origin = new Vector(guruguruTexture.Width / 2, guruguruTexture.Height / 2);
spriteBatch.Draw(guruguruTexture, Position, null, Color.White, angle, origin, 1f, SpriteEffects.None, 0f);

とすると、更新された角度でぐるぐるが描画されます。spriteBatchのDrawメソッドの引数のうち、このポストに絡むものを説明すると、

1番目: アニメーションしたいテクスチャ画像
2番目: 描画する場所(適当に描画する場所を決めておく)
5番目: テクスチャ画像を描画する角度
6番目: 回転中心。ここではテクスチャ画像の真ん中を指定
7番目: 描画する際の拡大縮小率。1にすると同じサイズで描画

です。もし、テクスチャをブルブルさせたければ、Positionにぶるぶるを与えた様な変動をUpdateメソッドで代入すればよいし、大きくしたり小さくしたりしたい場合には、7番目の引数をUpdateで適宜設定してやれば、OKです。

例えばゲームを開発する場合など、複数の場所に対してこのぐるぐるアニメーションを適用したい場合もあるでしょう。ですから実用を考えて、以下のようなクラスを作ると便利。

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;

    class RotateAnimation
    {
        Texture2D spriteStrip;
        float scale;
        Color color;
        public bool Active;
        public Vector2 Position;
        public float deltaRotateAngle;
        private Vector2 origin;
        private int frameCount;

        private int currentFrame;

        public void Initialize(Texture2D texture, Vector2 position,
            float deltaRotateAngle,
            int frameCount,
            Color color, float scale)
        {
            this.color = color;
            this.scale = scale;
            this.Position = position;
            this.deltaRotateAngle = deltaRotateAngle;
            this.frameCount = frameCount;

            spriteStrip = texture;
            elapsedTime = 0;

            Active = true;

            origin.X = spriteStrip.Width / 2;
            origin.Y = spriteStrip.Height / 2;

            currentFrame = 0;
        }

        private float rotateAngle = 0;

        public void Update(TimeSpan elapsedGameTime)
        {
            rotateAngle += deltaRotateAngle * (float)elapsedGameTime.TotalSeconds;
            if (rotateAngle > System.Math.PI * 2)
            {
                rotateAngle -= (float)(System.Math.PI * 2);
            }
            if (frameCount > 0)
            {
                currentFrame++;
                if (currentFrame >= frameCount)
                {
                    Active = false;
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            if (Active)
            {
                spriteBatch.Draw(spriteStrip, Position, null, Color.White, rotateAngle,
                    origin, scale, SpriteEffects.None, 0f);
            }
        }
    }

このクラスは、Initializeメソッドの引数でframeCountを0にすると、ずっと回転し、1以上にすると、Updateがその指定回数だけコールされると、Activeがfalseに設定し、規定回数分アニメーションを実行したことがわかるようになっています。

Game1クラスのメンバーに、このクラス用のコンテナを宣言し、

private List<RotateAnimation> rotateAnimations = new List<RotateAnimation>();

Game1のUpdateメソッドの中で、このリストに登録されたぐるぐるアニメのUpdateメソッドをコールし、このぐるぐるアニメーションが必要と条件判断がなされたところで、リストに追加するという処理を加えます。

foreach (var guruguruA in guruguruAnimation)
{
    guruguruA.Update();
}


// 以下適切な場所で、
RotateAnimation guruguru = new RotateAnimation();
guruguru.Initialize(guruguruTexture, position, 20, 100, Color.White, 1.0f);
guruguruAnimations.Add(guruguru);

とし、Game1クラスのDrawの中で、

for (int i = guruguruAnimations.Count ; i >= 0 ; i--)
{
    if (guruguruAnimations[i].Active)
    {
        guruguruAnimations[i].Draw(spriteBatch);
    }
    else
    {
        guruguruAnimations.RemoveAt(i);
    }
}

と書けば、Activeなぐるぐるのみ描画して、既に規定回数描画したものは、リストから削除される訳です。
ゲーム等の色づけでのワンポイントアクセントとしてお使いください。

 

Comments (0)

Skip to main content