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动画实现
endPoint = e.GetPosition(LayoutRoot);
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,实现动画。全部代码如下:

 

CompositionTarget动画实现
private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    
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);
    }
}
三. DispatcherTimer
动画实现的方法也是计时器动画,不过优点是可以自己设置事件的触发周期。从命名空间可以看出,DispatcherTimer是在System.Windows.Threading中的类,从它名字上也看的出,Dispatcher是调度,Timer是计时器。其实就是Timer In Dispatcher Queue,Timer可以响应固定的时间间隔,通过响应固定的时间间隔来修改DependencyProperty来实现动画。
这个比较简单,和Timer类似,这里直接给出代码:
DispatcherTimer distimer = new DispatcherTimer();
distimer.Tick 
+= new EventHandler(distimer_Tick);
distimer.Interval 
= TimeSpan.FromMilliseconds(50);
distimer.Start();

其中 distimer_Tick 这个事件中写入与CompositionTarget的Rendering一样的处理代码即可,可以说DispatcherTimer在功能上,相当于可以设置时间间隔的CompositionTarget。(原理不同,DispatcherTimer是线程计时队列,而CompositionTarget是界面刷新)

 

以上三种方法是SL中创建动画的最基本方法。

 

参考文献:

深蓝色右手之动画游戏教程

TerryLee的一步一步SL2

 

 

posted on 2010-08-12 01:41  寻雨  阅读(416)  评论(0编辑  收藏  举报

导航