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