Silverlight4深蓝游戏开发学习笔记(一) 基础动画方式
SL中提供三种动画的方法:1.Storyboard 2.CompositionTarget 3.DispatcherTimer
一. Storyboard
这是SL首推的动画实现方法,因为Storyboard内部已经为用户进行了一些处理,用户只要一个开始状态,一个结束状态,一个动画实现.就可以组建一个完整的动画.简单步骤:
1.实例化Storyboard对象.
Storyboard sb = neFillBehaviorw Storyboard(); ///这里Storyboard中的board是小写...我总容易打成大写....另外SB这个缩写确实很搞笑...
2.设置一种Timeline (第二个词又是小写..我一打快就容易打成大写....).Timeline直译为时间线,是用来描述在一段时间中对象的状态,它是一个抽象类,包括
Timeline{
AutoReverse bool 播放完后是否反转播放
BeginTime TimeSpan 开始播放时间
Duration Duration(这个类用来描述一段时间,不过重载了一些运算符,支持一些+-之类的运算,一般使用还是用它的构造函数,参数为TimeSpan) 描述动画执行的时间段
FillBehavior FillBehavior(这是个枚举,包括两个值,默认是HoldEnd:当自己这个Timeline执行完后,如果父级对象未终止,则自己保持进度跟着延续.另外一个值是Stop:当自己执行完后,立刻停止.) 这个属性指定当自己超出活动期但父级对象仍在活动时的行为方式.
RepeatBehavior RepeatBehavior(这是一个结构体,主要指定时间线的重复情况,可以用Count来指定重复执行的次数,可以用Forever来无限重复,还可以用一个Duration来设置重复播放总时间)
SpeedRatio double 这个值用来设置时间线的时间前进速度.如果是根时间线,则为设置默认速度.如果为子级时间线,则这个double值是一个比例.0.5表示父级的一半.注意,这个不是直接设置动画的移动速度,则是通过设置时间走的快慢,来调整动画状态.
Completed event 这个是时间线结束后的事件触发.
}
而抽象类Timeline的具体表现,有很多种,但这次主要讲动画方式,所以只拿其中一个DoubleAnimation做例.
DoubleAnimation{
From double? 默认null 这个值表示的是指定属性的开始值
By double? 默认是null 这个By表示的是增量,意思是,指定的属性从From开始插值计算到From+By的和.
To double? 默认是null 这个To表示的是结束值.意思是指定属性从From开始插值计算到To的值.
EasingFunction IEasingFunction(接口,通过一个double类型的参数来表示进度,转换为一个新的表示进度的double值) 这个缓动函数.其实也好理解,就是读取当前时间线进度,通过自定义计算,输出一个计算的新进度,从而实现一些特别的效果,比如忽快忽慢,先快后慢等.
}
3.设置好Timeline后,还要将Timeline绑定到指定属性
这主要依靠三个函数:
Storyboard.SetTargetName(Timeline,string); (时间线对象,如DoubleAnimation的实例,绑定对象的名称)
Storyboard.SetTarget(Timeline,DenpendencyObject); (时间线对象,要绑定的对象.) 注:只有依赖对象才可以进行Storyboard动画.
Storyboard.SetTargetProperty(Timeline, PropertyPath); (时间线对象,要绑定的属性的属性路径) 注:只有依赖属性才可以进行Storyboard动画.(插值引擎只负责通过计算来设置DenpendencyProperty,不负责更新显示工作,而依赖属性值改变后触发事件刷新显示区而更新显示.)
其中PropertyPath是一个密封类,我们一般通过其构造函数来设置要绑定动画的属性的路径.
4.将时间线添加到Storyboard中,并执行动画.
sb.Children.Add(Timeline); //将时间线添加到Storyboard实例
sb.Begin();
最后贴上1-4步的代码:
Storyboard sb = new Storyboard();
DoubleAnimation da = new DoubleAnimation()
{
From = Canvas.GetLeft(StoryB),
To = endPoint.X,
Duration = new Duration(TimeSpan.FromMilliseconds(2000))
};
Storyboard.SetTarget(da, StoryB);
Storyboard.SetTargetProperty(da, new PropertyPath("(Canvas.Left)"));
sb.Children.Add(da);
da = new DoubleAnimation()
{
From = Canvas.GetTop(StoryB),
To = endPoint.Y,
Duration = new Duration(TimeSpan.FromMilliseconds(2000))
};
Storyboard.SetTarget(da, StoryB);
Storyboard.SetTargetProperty(da, new PropertyPath("(Canvas.Top)"));
sb.Children.Add(da);
sb.Begin();
二. CompositionTarget
这个是通过注册界面刷新每一帧的Rendering事件来实现的,是在界面刷新的固有频率中增加动画.
实现起来很简单:
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); //增加一个事件处理
void CompositionTarget_Rendering(object sender, EventArgs e)
{
//动画实现逻辑
}
这样每次界面固定刷新时,都会执行事件,在事件处理中,我们可以进行增加动画:比如按一定规律设置一些对象的DenpendencyProperty来改变对象外观,实现动画。
下面给出实验代码,先在左键单击中计算目的位置坐标,用三角函数求得Tan值,来计算物理在X,Y方向的速度,并存入一个Point中,然后在Rendering中动态设置物理的Canvas.Left和Top,实现动画。全部代码如下:
{
double dX = Math.Abs(Canvas.GetLeft(CompositionT) - e.GetPosition(LayoutRoot).X);
double dY = Math.Abs(Canvas.GetTop(CompositionT) - e.GetPosition(LayoutRoot).Y);
double dXY = dX > dY ? dX : dY;
speedPoint = new Point(dX / dXY, dY / dXY);
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (Canvas.GetLeft(CompositionT) < endPoint.X)
{
Canvas.SetLeft(CompositionT, Canvas.GetLeft(CompositionT) + speedPoint.X);
}
else
{
Canvas.SetLeft(CompositionT, Canvas.GetLeft(CompositionT) - speedPoint.X);
}
if (Canvas.GetTop(CompositionT) < endPoint.Y)
{
Canvas.SetTop(CompositionT, Canvas.GetTop(CompositionT) + speedPoint.Y);
}
else
{
Canvas.SetTop(CompositionT, Canvas.GetTop(CompositionT) - speedPoint.Y);
}
}
distimer.Tick += new EventHandler(distimer_Tick);
distimer.Interval = TimeSpan.FromMilliseconds(50);
distimer.Start();
其中 distimer_Tick 这个事件中写入与CompositionTarget的Rendering一样的处理代码即可,可以说DispatcherTimer在功能上,相当于可以设置时间间隔的CompositionTarget。(原理不同,DispatcherTimer是线程计时队列,而CompositionTarget是界面刷新)
以上三种方法是SL中创建动画的最基本方法。
参考文献:
深蓝色右手之动画游戏教程
TerryLee的一步一步SL2