FlasherのためのSilverlight入門(8) Spriteクラスを作る[2]
前回のソースの中から解説の続きです。
今回は、Tween部分について。SilverlightでオブジェクトをTweenさせるのにはStoryboardというクラスがありますが、これを使う上でのショートカットを作成します。Sprite.moveTo(x,y,0.5)みたいなものですね。
Storyboardクラスの使い方
alphaToのメイン関数を抜き出しました。
public void alphaTo(double ta, double duration, double delay, EasingFunctionBase ease, SpriteTweenFeedBack tfback)
{
this.tfback_alphato = tfback;
Storyboard stalpha = new Storyboard();
DoubleAnimation stalpha_dbl = new DoubleAnimation();
stalpha_dbl.From = this.alpha;
stalpha_dbl.To = ta;
stalpha_dbl.Duration = TimeSpan.FromMilliseconds(1000 * duration);
stalpha_dbl.BeginTime = TimeSpan.FromMilliseconds(1000 * delay);
if (ease == null)
{
//デフォルトのイージング
ease = new CircleEase();
ease.EasingMode = EasingMode.EaseOut;
}
else
{
stalpha_dbl.EasingFunction = ease;
}
Storyboard.SetTarget(stalpha_dbl, this);
Storyboard.SetTargetProperty(stalpha_dbl, new PropertyPath(Sprite.dp_alpha));
stalpha.Children.Add(stalpha_dbl);
stalpha.Completed += this.onAlphaToEnd;
stalpha.Begin();
}
private void onAlphaToEnd(object sender, EventArgs e)
{
Storyboard stalpha = (Storyboard)sender;
stalpha.Completed -= this.onAlphaToEnd;
System.Diagnostics.Debug.WriteLine("onAlphaToEnd");
if (this.tfback_alphato != null)
{
this.tfback_alphato(Sprite.T_ALPHA, this);
}
}
この関数はSpriteクラスのインスタンスに対して、sprite.alphaTo(ターゲットの値, tween時間, Tween開始までの遅延時間, イージングの関数, Tween終了時に呼び出す関数) という形で呼び出します。
処理の流れは、まずStoryboardのクラスを生成します(stalpha)。そして、アニメーションの種類を指定します。色々あるのですが、doubleの数字をTweenさせるのに、DoubleAnimationクラスを使っています。このDoubleAnimationクラスのインスタンス(stalpha_dbl ) に、スタート値、終了値、時間、開始時間(開始までの遅延)を設定します。(7~11行目)
さらに、stalphaにアニメーションさせるインスタンスを指定、ターゲットとするプロパティを指定します。(23,24行目)
このDoubleAnimationインスタンスをStoryboardクラスのインスタンスのChild.Addして、開始しています。(25~27行目)これがざっくりとした流れです。
DoubleAnimationに相当する他のアニメーションクラスには、ColorAnimationなどがあります。またTweenのEasingにはBounceEase、CircleEase、ElasticEaseなど一通りそろっています。これらは、System.Windows.Media.Animation 名前空間に定義されているので詳しくはそちらを見てください。
というわけなのですが、実はこれだけでは動かないのです。実はこのアニメーションの対象になったプロパティのDependency設定とかいうのが必要になります。このため、このSpriteクラスもDependencyObjectというクラスを継承することになります。
Dependency設定
Dependencyがなぜ必要かはよくわかりません。まぁそういう仕様になっているということです。
先ほどの
Storyboard.SetTargetProperty(stalpha_dbl, new PropertyPath(Sprite.dp_alpha));
この24行目を見てください。変化させたい値はalphaなのですが、dp_alphaという値をstaticな指定でプロパティとして指定しています。実はこの先で、以下のような設定をしています。
public double alpha
{
set
{
this._layer.Opacity = value;
}
get
{
return this._layer.Opacity;
}
}
/**
* alphaのアニメーションのためのDependency設定など
**/
public static readonly DependencyProperty dp_alpha = DependencyProperty.RegisterAttached("alpha", typeof(double), typeof(Sprite), new PropertyMetadata(new PropertyChangedCallback(alphaChanged)));
private static void alphaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Sprite s = (Sprite)d;
s.alphaChanged(e);
}
protected virtual void alphaChanged(DependencyPropertyChangedEventArgs e)
{
double value = (double)e.NewValue;
this.alpha = value;
}
最初に、alphaに対するgetter/setterがあり、そのあとに、DependencyProperty dp_alphaの定義があります。
アニメーションの変化はまず、Sprite.alphaChangedというStaticが呼ばれます。この引数で渡されるDependencyObjectが今回定義しているSpriteクラスのインスタンスです。これを元に、そのインスタンスのalphaChangedクラスを呼び出してようやく、alphaが変わるという、やたらめんどくさい流れになっています。
なんか無駄な仕様だなぁと思いますが、これはこういうもんだとおもってください。
関数を、関数の引数にする
さて、関数の処理が終わったあとに、別のクラスの中のフィードバック関数を呼びたいことがあると思います。イベントで処理することもできますが、ここではDelegateを使っています。
public delegate void SpriteTweenFeedBack(string type, object instance);
実はこのクラスの外(名前空間定義の後)で、このようなdelegate宣言をしています。
これはこのような形の引数を持った関数を参照渡しするのに必要なものです。alphaToの引数の中で、
public void alphaTo(double ta, double duration, double delay, EasingFunctionBase ease, SpriteTweenFeedBack tfback)
{
this.tfback_alphato = tfback;
このような処理をしています。引数として指定されたSpriteTweenFeedBack型のtfbackをクラスプロパティに渡しています。delegate宣言された関数はこのように、通常の変数のように扱うことができます。
このクラスを実行するには、onAlphaToEnd関数の中で行っているように、
this.tfback_alphato(Sprite.T_ALPHA, this);
このようにすることで、他のクラスの関数を実行することができます。
さて、最後に、このSpriteのalphaToクラスがどのように呼ばれているかというと、次のようになっています。
private void doAnimation(Sprite man)
{
BounceEase ease = new BounceEase();
ease.Bounces = 3;
ease.EasingMode = EasingMode.EaseOut;
SpriteTweenFeedBack bg2 = onAlphaEnd;
man.alphaTo(1, 1, 2, ease, bg2);
}
private void onAlphaEnd(string type, object instance)
{
System.Diagnostics.Debug.WriteLine("onAlphaEnd2 " + type);
}
ここまでのソースをZIPにしておきます。 VariousTest8.zip
| カテゴリー | : | silverlight,tech&programming |
| タグ | : | silverlight |
| トラックバックURL | : | http://blog.tokyoace4.com/cgi-bin/mt/mt-tb.cgi/156 |
トラックバックURL: http://blog.tokyoace4.com/cgi-bin/mt/mt-tb.cgi/156