在GDE-X开发过程中需要对有的动画片段进行集中管理——可以归类到任务池结构。
一些动画需要启动后,按照一定的帧顺序展现,在展现完毕之后从画布中清除并释放所占用资源。
silverlight中对于storyboard等提供completed事件,在动画结束的时候回调。
若这种动画会同时出现很多个,则回调的时候需要拿到具体其对应的那个释放函数。这样若单独维护其成员变量就行不通了。
如何让每个动画都在完成时找到自己对应的那个completed回调呢?用一个类封装一下就行了。 请看我封装的一个 AttackInfo 类,其功能为在某点出现一个攻击信息的动画,慢慢上浮并且消失。用于角色在受到攻击的时候头顶浮现数字或者其他信息。
效果如下图所示(Damage 1)
/// <summary> /// 攻击信息类 /// </summary> class AttackInfo { /// <summary> /// 构造函数,将自动启动动画 /// </summary> /// <param name="rootCanvas">根画布</param> /// <param name="x">逻辑x</param> /// <param name="y">逻辑y</param> /// <param name="ID">角色ID</param> /// <param name="Info">内容</param> public AttackInfo(Canvas rootCanvas, int x, int y, int ID, string Info) { this.Info = Info; X = x; Y = y; RootCanvas = rootCanvas; this.ID = ID; this.Start(); } private void Start() { int FromX = Battle.Transfer_X(X) + 6; int FromY = Battle.Transfer_Y(Y) - 40; int TargetY = FromY - 30; AttackInfoText = new TextBlock(); AttackInfoText.Text = Info.ToString(); AttackInfoText.FontSize = 20; AttackInfoText.Foreground = new SolidColorBrush(Colors.Red); RootCanvas.Children.Add(AttackInfoText); Canvas.SetLeft(AttackInfoText, FromX); Canvas.SetTop(AttackInfoText, FromY); Canvas.SetZIndex(AttackInfoText, Battle.AttackInfoTextOffsetBase); //创建动画 DoubleAnimation MoveAnimY = new DoubleAnimation(); MoveAnimY.From = FromY; MoveAnimY.To = TargetY; MoveAnimY.Duration = new Duration(new TimeSpan(0, 0, 0, 1, 0)); DoubleAnimation AnimOpc = new DoubleAnimation(); AnimOpc.From = 1; AnimOpc.To = 0; AnimOpc.Duration = new Duration(new TimeSpan(0, 0, 0, 1, 0)); Storyboard Sb = new Storyboard(); Sb.Duration = new Duration(new TimeSpan(0, 0, 0, 1, 0)); Sb.AutoReverse = false; Sb.Children.Add(MoveAnimY); Sb.Children.Add(AnimOpc); Storyboard.SetTarget(MoveAnimY, AttackInfoText); Storyboard.SetTarget(AnimOpc, AttackInfoText); Storyboard.SetTargetProperty(MoveAnimY, new PropertyPath("(Canvas.Top)")); Storyboard.SetTargetProperty(AnimOpc, new PropertyPath("Opacity")); RootCanvas.Resources.Add("AttackInfoAnimation" + ID, Sb); Sb.Completed += new EventHandler(this.AttackInfoAnimationFinish); Sb.Begin(); } /// <summary> /// 显示攻击信息动画结束 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void AttackInfoAnimationFinish(object sender, EventArgs e) { RootCanvas.Children.Remove(AttackInfoText); RootCanvas.Resources.Remove("AttackInfoAnimation" + ID); } private string Info; private int X { get; set; } private int Y { get; set; } private TextBlock AttackInfoText; private int ID;//角色ID private Canvas RootCanvas { get; set; } }
调用的时候传入其绘图根信息及其他具体的一些参数,就能实现这个动画的自管理了:
AttackInfo InfoAnimation = new AttackInfo(BattleInstance.Carrier, X, Y, ID, Info);
同理,比如DispatcherTimer等也可以这么用。