如果前两篇的博客太为普通,那么接下来的内容将让你动画实在是太厉害了。本文将会介绍两个关于纯手工实现动画的形式,当然动画效果就不用我多说了。

基于帧的动画:

此处的帧并不是之前介绍的Animation这样的动画,之所以称之为帧,那是因为它控制范围更加精细。也就是说,在有些应用程序方案中,你需要根据每个帧控制呈现,使那么就可以基于每个帧回调来创建自定义动画。基于帧的动画主要使用CompositionTarget 对象的一个回调函数来实现,CompositionTarget表示应用程序的显示图面,其回调函数将会在1秒之内被访问60次,所以也就可以实现动画的过程(一般来说此种动画会在游戏的时候使用,因为它每一帧都是会执行一次回调函数,可以创建出逼真的效果和动画)。
接下来我们的例子是实现一个Ellipse从上往下坠落的过程(数量是从20--100不等,通过随机),当所有的图形坠落到底部之后则结束动画。

效果图如上,待我慢慢讲解代码。
EllipseInfo(可以理解为Ellipse信息类):

public class EllipseInfo
{
public Ellipse Ellipse
{
get;
set;
}
public double VelocityY
{
get;
set;
}
public EllipseInfo(Ellipse ellipse, double velocityY)
{
VelocityY = velocityY;
Ellipse = ellipse;
}
}

Ellipse表示一个Ellipse对象,VeloctyY表示动画向下时所使用的值。

XAML:

<Window x:Class="WpfApplication3.Window4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window4" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button Height="30" Width="30" Content="开始" Margin="5" Name="btnStart" Click="btnStart_Click"></Button>
<Button Height="30" Width="30" Content="停止" Margin="5" Canvas.Left="50" Name="btnStop" Click="btnStop_Click"></Button>
</StackPanel>
<Canvas Name="ellipseCanvas" Height="Auto" Width="Auto" Background="LightBlue" Grid.Row="1">
</Canvas>
</Grid>
</Window>

两个按钮,一个Canvas,没什么说的。

Xaml.cs:

   private void btnStart_Click(object sender, RoutedEventArgs e)
{
if (!rendering)
{
//清楚集合汇中的Ellipse
ellipses.Clear();
//清楚Canvas中的元素
ellipseCanvas.Children.Clear();
//添加自定义呈现过程
CompositionTarget.Rendering += CompositionTarget_Rendering;
//标示进入呈现过程
rendering = true;
}
}

开始按钮事件,事件中清空集合和页面集合,然后添加呈现过程。

呈现事件:

 private void CompositionTarget_Rendering(object sender, EventArgs e)
{
//没有图形,则随机创建
if (ellipses.Count == )
{
//得到Canvas的宽度的一半,用于随机得到Ellipse的Left值
int halfCanvasWidth = (int)ellipseCanvas.ActualWidth / ; Random random = new Random();
//随机创建Ellipse的数量
int ellipseCount = random.Next(minEllipses, maxEllipses);
for (int i = ; i < ellipseCount; i++)
{
//创建Ellipse
Ellipse ellipse = new Ellipse();
ellipse.Fill = Brushes.LimeGreen;
ellipse.Width = ellipseRadius;
ellipse.Height = ellipseRadius; //设置Left属性,Left的值为0--Canvas.ActualWidth
Canvas.SetLeft(ellipse, halfCanvasWidth + random.Next(-halfCanvasWidth, halfCanvasWidth));
//Top值为0,因为当创建完毕Ellipse之后才处理Top的动画效果
Canvas.SetTop(ellipse, );
//将Ellipse放入Canvas
ellipseCanvas.Children.Add(ellipse); //创建EllipseInfo,用于保存Ellipse对象,以及每个对象的向下速度
EllipseInfo ellipseInfo = new EllipseInfo(ellipse, speedRatio * random.Next(minStartingSpeed, maxStartingSpeed));
ellipses.Add(ellipseInfo);
}
}
else
{ for (int i = ellipses.Count - ; i >= ; i--)
{
EllipseInfo info = ellipses[i];
//根据Ellipse得到Top
double top = Canvas.GetTop(info.Ellipse);
//设置Ellipse的Top为初始时的速度值
Canvas.SetTop(info.Ellipse, info.VelocityY);
//如果Top到达了Canvas的底部
if (top >= (ellipseCanvas.ActualHeight - ellipseRadius * ))
{
//图形到了底层,则从集合移除
ellipses.Remove(info);
}
else
{
//否则继续增加高度
info.VelocityY += accelerationY;
}
//如果元素全部从Canvas中移除,则停止呈现过程
if (ellipses.Count == )
{
CompositionTarget.Rendering -= CompositionTarget_Rendering;
rendering = false;
}
}
}
}

代码注释非常清楚了,但是还是要说一句,为什么可以用if和else这么做。因为我上文提到,呈现过程是1秒钟被执行60次的,所以我们的事件也是这样的,所以这样反复的过程就形成了你看到的动画。

结束事件:

  private void btnStop_Click(object sender, RoutedEventArgs e)
{
CompositionTarget.Rendering -= CompositionTarget_Rendering;
rendering = false;
}

赶紧运行程序,将会看到很有趣的效果哦。

地雷下坠游戏:
如果上述的效果让你觉得没什么可玩性,那么接下来这个可是完整的一个游戏。

此游戏属于考验反应速度类的,左边一直有地雷下降,并且速度越来越快,你必须点击地雷使地雷消失,否则当地雷坠落超过5个,则视为游戏结束。

代码构成部分:主要为主窗体和一个用户控件,用户控件就是放了一个使用Path实现的地雷形状(当然不是我做的,我可没那么厉害)。
用户控件Bomb:
代码有点长,不过不用去关注,就是使用Path绘制的图形。

<UserControl x:Class="WpfApplication3.Bomb"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<UserControl.RenderTransform>
<TransformGroup>
<RotateTransform Angle="20" CenterX="50" CenterY="50"></RotateTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"></ScaleTransform>
</TransformGroup>
</UserControl.RenderTransform>
<Canvas> <Path Data="M 11.989,50.026 L 24.381,37.08 L 19.097,53.862 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path Data="M 0.46098,31.997 L 17.945,28.449 L 4.1114,39.19 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path Data="M 9.9713,7.3517 L 22.075,20.49 L 5.7445,14.16 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path Data="M 58.484,29.408 L 40.712,31.997 L 57.523,37.367 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path Data="M 51.663,10.229 L 38.694,22.408 L 55.506,17.325 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path Data="M 32.354,0.25535 L 31.682,18.092 L 40.039,2.7487 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFF2CC0C"/>
</Path.Fill>
</Path>
<Path
Data="M 105.84,186.87 L 110.84,183.99 L 115.45,180.64 L 119.58,176.9 L 123.33,172.77 L 126.69,168.36 L 129.47,163.76 L 131.88,158.87 L 133.8,153.79 L 135.14,148.51 L 136.01,143.14 L 136.39,137.77 L 136.3,132.21 L 135.53,126.74 L 134.28,121.37 L 132.45,116 L 130.05,110.73 L 128.61,108.14 L 127.17,105.74 L 125.54,103.34 L 123.81,101.14 L 121.98,99.029 L 120.06,97.015 L 118.04,95.097 L 115.93,93.275 L 113.82,91.549 L 111.61,89.919 L 109.3,88.481 L 106.9,87.138 L 104.5,85.891 L 102,84.741 L 99.503,83.782 L 96.909,82.823 L 94.316,82.055 L 91.722,81.48 L 89.032,81.001 L 86.342,80.617 L 83.556,80.329 L 80.867,80.233 L 78.081,80.233 L 75.391,80.329 L 72.605,80.617 L 69.915,81.096 L 67.129,81.672 L 64.44,82.343 L 61.75,83.206 L 59.06,84.165 L 56.37,85.316 L 53.777,86.563 L 48.781,89.44 L 44.17,92.796 L 40.039,96.536 L 36.293,100.66 L 33.027,104.97 L 30.145,109.67 L 27.743,114.56 L 25.918,119.65 L 24.477,124.83 L 23.612,130.2 L 23.324,135.66 L 23.42,141.13 L 24.189,146.59 L 25.438,152.06 L 27.263,157.43 L 29.664,162.7 L 31.105,165.29 L 32.546,167.69 L 34.179,170.09 L 35.909,172.29 L 37.734,174.4 L 39.655,176.42 L 41.672,178.34 L 43.69,180.16 L 45.899,181.88 L 48.109,183.51 L 50.414,184.95 L 52.72,186.3 L 55.217,187.54 L 57.619,188.69 L 60.213,189.65 L 62.71,190.61 L 65.304,191.38 L 67.994,191.95 L 70.684,192.43 L 73.374,192.82 L 76.063,193.1 L 78.753,193.2 L 81.539,193.2 L 84.325,193.1 L 87.015,192.82 L 89.801,192.34 L 92.49,191.76 L 95.18,191.09 L 97.87,190.23 L 100.56,189.27 L 103.25,188.12 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="F 1 M 125.92,112.84 L 125.92,112.84 L 128.13,117.63 L 129.86,122.62 L 131.01,127.51 L 131.68,132.5 L 131.78,137.68 L 131.4,142.66 L 130.63,147.65 L 129.38,152.44 L 127.65,157.05 L 125.44,161.55 L 122.94,165.77 L 119.77,169.9 L 116.31,173.64 L 112.57,177.09 L 108.34,180.16 L 103.73,182.75 L 107.96,190.99 L 113.34,187.83 L 118.33,184.19 L 122.85,180.16 L 126.88,175.65 L 130.44,170.95 L 133.51,165.97 L 136.1,160.69 L 138.22,155.13 L 139.66,149.38 L 140.62,143.62 L 141,137.87 L 140.91,131.92 L 140.04,125.98 L 138.7,120.13 L 136.78,114.37 L 134.18,108.62 L 134.18,108.62 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="F 1 M 55.89,90.686 L 55.89,90.686 L 58.195,89.44 L 60.693,88.481 L 63.191,87.522 L 65.688,86.754 L 68.09,86.179 L 70.78,85.604 L 73.181,85.124 L 75.679,84.932 L 78.081,84.836 L 80.867,84.836 L 83.268,84.932 L 85.862,85.22 L 88.36,85.508 L 90.857,85.987 L 93.163,86.467 L 95.468,87.138 L 97.87,88.097 L 100.27,88.96 L 102.48,90.015 L 104.79,91.166 L 107,92.412 L 109.01,93.659 L 111.03,95.193 L 112.95,96.728 L 114.97,98.454 L 116.79,100.28 L 118.62,102.1 L 120.25,104.02 L 121.79,106.03 L 123.33,108.14 L 124.67,110.44 L 125.92,112.84 L 134.18,108.62 L 132.55,105.84 L 131.01,103.34 L 129.28,100.66 L 127.36,98.262 L 125.34,95.961 L 123.33,93.755 L 121.12,91.741 L 118.91,89.823 L 116.6,87.905 L 114.2,86.179 L 111.61,84.549 L 109.01,83.11 L 106.52,81.768 L 103.73,80.521 L 101.14,79.466 L 98.35,78.507 L 95.468,77.644 L 92.586,76.973 L 89.704,76.493 L 86.823,76.014 L 83.845,75.726 L 80.867,75.63 L 78.081,75.63 L 75.103,75.726 L 72.029,76.11 L 69.051,76.589 L 66.169,77.165 L 63.191,77.932 L 60.309,78.891 L 57.427,79.85 L 54.545,81.192 L 51.663,82.439 L 51.663,82.439 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="F 1 M 33.795,160.6 L 33.795,160.6 L 31.586,155.8 L 29.857,150.81 L 28.704,145.83 L 28.031,140.84 L 27.935,135.66 L 28.223,130.68 L 28.992,125.78 L 30.337,120.99 L 31.97,116.29 L 34.179,111.88 L 36.773,107.56 L 39.847,103.54 L 43.306,99.796 L 47.052,96.344 L 51.279,93.275 L 55.89,90.686 L 51.663,82.439 L 46.284,85.604 L 41.288,89.248 L 36.773,93.275 L 32.738,97.783 L 29.28,102.39 L 26.11,107.47 L 23.516,112.84 L 21.499,118.3 L 19.962,123.87 L 19.001,129.72 L 18.713,135.66 L 18.809,141.42 L 19.674,147.36 L 21.019,153.31 L 22.94,159.06 L 25.534,164.81 L 25.534,164.81 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="F 1 M 103.73,182.75 L 103.73,182.75 L 101.42,183.99 L 98.927,184.95 L 96.429,185.91 L 93.931,186.68 L 91.53,187.25 L 88.936,187.83 L 86.438,188.31 L 84.037,188.5 L 81.539,188.6 L 78.753,188.6 L 76.352,188.5 L 73.854,188.21 L 71.356,187.93 L 68.859,187.45 L 66.361,186.97 L 64.151,186.3 L 61.846,185.34 L 59.348,184.47 L 57.235,183.42 L 54.833,182.27 L 52.816,181.02 L 50.702,179.77 L 48.685,178.24 L 46.668,176.71 L 44.746,174.98 L 42.921,173.16 L 41.096,171.34 L 39.463,169.42 L 37.926,167.4 L 36.389,165.29 L 35.044,162.99 L 33.795,160.6 L 25.534,164.81 L 27.167,167.6 L 28.704,170.09 L 30.433,172.77 L 32.354,175.17 L 34.372,177.47 L 36.389,179.68 L 38.598,181.69 L 40.712,183.61 L 43.113,185.53 L 45.515,187.25 L 48.013,188.88 L 50.606,190.32 L 53.2,191.67 L 55.89,192.91 L 58.58,193.97 L 61.27,194.93 L 64.248,195.79 L 67.129,196.46 L 70.011,196.94 L 72.893,197.42 L 75.775,197.71 L 78.753,197.8 L 81.539,197.8 L 84.613,197.71 L 87.591,197.32 L 90.665,196.84 L 93.451,196.27 L 96.429,195.5 L 99.311,194.54 L 102.19,193.58 L 105.07,192.24 L 107.96,190.99 L 107.96,190.99 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 105.84,186.87 L 110.84,183.99 L 115.45,180.64 L 119.58,176.9 L 123.33,172.77 L 126.69,168.36 L 129.47,163.76 L 131.88,158.87 L 133.8,153.79 L 135.14,148.51 L 136.01,143.14 L 136.39,137.77 L 136.3,132.21 L 135.53,126.74 L 134.28,121.37 L 132.45,116 L 130.05,110.73 L 128.61,108.14 L 127.17,105.74 L 125.54,103.34 L 123.81,101.14 L 121.98,99.029 L 120.06,97.015 L 118.04,95.097 L 115.93,93.275 L 113.82,91.549 L 111.61,89.919 L 109.3,88.481 L 106.9,87.138 L 104.5,85.891 L 102,84.741 L 99.503,83.782 L 96.909,82.823 L 94.316,82.055 L 91.722,81.48 L 89.032,81.001 L 86.342,80.617 L 83.556,80.329 L 80.867,80.233 L 78.081,80.233 L 75.391,80.329 L 72.605,80.617 L 69.915,81.096 L 67.129,81.672 L 64.44,82.343 L 61.75,83.206 L 59.06,84.165 L 56.37,85.316 L 53.777,86.563 L 48.781,89.44 L 44.17,92.796 L 40.039,96.536 L 36.293,100.66 L 33.027,104.97 L 30.145,109.67 L 27.743,114.56 L 25.918,119.65 L 24.477,124.83 L 23.612,130.2 L 23.324,135.66 L 23.42,141.13 L 24.189,146.59 L 25.438,152.06 L 27.263,157.43 L 29.664,162.7 L 31.105,165.29 L 32.546,167.69 L 34.179,170.09 L 35.909,172.29 L 37.734,174.4 L 39.655,176.42 L 41.672,178.34 L 43.69,180.16 L 45.899,181.88 L 48.109,183.51 L 50.414,184.95 L 52.72,186.3 L 55.217,187.54 L 57.619,188.69 L 60.213,189.65 L 62.71,190.61 L 65.304,191.38 L 67.994,191.95 L 70.684,192.43 L 73.374,192.82 L 76.063,193.1 L 78.753,193.2 L 81.539,193.2 L 84.325,193.1 L 87.015,192.82 L 89.801,192.34 L 92.49,191.76 L 95.18,191.09 L 97.87,190.23 L 100.56,189.27 L 103.25,188.12 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF000000"/>
</Path.Fill>
</Path>
<Path
Data="M 58.195,51.081 L 20.538,70.548 L 18.809,71.507 L 19.674,73.233 L 37.734,107.85 L 38.022,108.52 L 38.791,108.71 L 38.983,108.81 L 39.367,108.91 L 40.039,109.1 L 40.808,109.19 L 41.769,109.39 L 42.921,109.48 L 44.266,109.58 L 45.707,109.67 L 47.34,109.58 L 49.069,109.48 L 50.991,109.19 L 52.912,108.81 L 55.025,108.24 L 57.139,107.56 L 59.444,106.7 L 61.75,105.55 L 64.632,103.92 L 67.129,102.39 L 69.339,100.76 L 71.26,99.221 L 72.989,97.687 L 74.334,96.248 L 75.487,94.906 L 76.448,93.563 L 77.216,92.316 L 77.889,91.262 L 78.273,90.207 L 78.657,89.44 L 78.849,88.672 L 78.945,88.193 L 79.041,87.809 L 79.041,87.617 L 79.041,87.042 L 78.849,86.467 L 60.789,51.848 L 59.925,50.218 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 60.021,102.1 L 58.292,102.96 L 56.562,103.63 L 54.929,104.21 L 53.392,104.69 L 51.855,105.07 L 50.414,105.36 L 49.069,105.55 L 47.724,105.65 L 46.476,105.74 L 45.419,105.74 L 44.362,105.74 L 43.402,105.65 L 42.537,105.55 L 41.865,105.45 L 41.192,105.36 L 40.712,105.26 L 23.997,73.137 L 58.292,55.396 L 75.103,87.713 L 74.815,88.576 L 74.238,89.823 L 73.278,91.357 L 71.933,93.18 L 70.011,95.193 L 67.418,97.399 L 64.151,99.7 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF000000"/>
</Path.Fill>
</Path>
<Path
Data="M 50.222,155.32 L 47.917,150.33 L 46.284,145.16 L 45.323,140.07 L 44.939,134.89 L 45.131,129.81 L 45.995,124.92 L 47.34,120.22 L 49.262,115.72 L 47.532,116 L 45.995,116.19 L 44.458,116.19 L 43.017,116.19 L 41.672,116.1 L 40.424,115.81 L 39.271,115.52 L 38.214,115.24 L 36.101,119.74 L 34.564,124.44 L 33.699,129.43 L 33.315,134.51 L 33.603,139.79 L 34.564,144.96 L 36.197,150.14 L 38.406,155.22 L 40.135,158.2 L 41.961,160.98 L 44.074,163.66 L 46.284,166.06 L 48.589,168.27 L 51.087,170.28 L 53.68,172.1 L 56.37,173.73 L 59.156,175.17 L 61.942,176.32 L 64.92,177.28 L 67.898,178.05 L 70.876,178.53 L 73.854,178.72 L 76.928,178.72 L 79.906,178.53 L 77.696,177.95 L 75.391,177.28 L 73.181,176.51 L 71.068,175.55 L 68.955,174.5 L 66.937,173.35 L 64.92,172.01 L 62.903,170.57 L 61.077,169.03 L 59.252,167.4 L 57.523,165.68 L 55.89,163.76 L 54.353,161.84 L 52.816,159.73 L 51.471,157.62 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 102.87,110.63 L 98.35,116.29 L 98.734,116.87 L 99.215,117.54 L 99.599,118.11 L 100.08,118.78 L 100.46,119.36 L 100.85,120.03 L 101.14,120.61 L 101.52,121.28 L 101.81,121.76 L 102,122.24 L 102.29,122.72 L 102.48,123.2 L 104.02,122.72 L 108.15,120.7 L 107.67,119.26 L 107.09,117.92 L 106.42,116.58 L 105.84,115.33 L 105.07,114.09 L 104.4,112.84 L 103.63,111.69 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 116.12,113.8 L 115.35,112.45 L 114.59,111.02 L 113.72,109.77 L 112.95,108.43 L 111.99,107.18 L 111.03,105.93 L 110.07,104.69 L 109.11,103.54 L 105.27,108.24 L 106.13,109.39 L 107,110.63 L 107.86,111.98 L 108.63,113.32 L 109.4,114.66 L 110.07,116.19 L 110.74,117.63 L 111.32,119.26 L 117.37,116.48 L 117.08,115.81 L 116.79,115.14 L 116.51,114.47 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 101.71,104.21 L 105.36,99.7 L 104.02,98.742 L 102.58,97.783 L 101.14,96.919 L 99.599,96.056 L 98.062,95.289 L 96.525,94.618 L 94.988,93.947 L 93.355,93.275 L 90.473,98.837 L 91.722,99.221 L 93.067,99.796 L 94.508,100.28 L 95.853,100.95 L 97.294,101.62 L 98.734,102.39 L 100.27,103.25 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 88.744,102.29 L 85.574,108.43 L 86.823,108.81 L 88.167,109.29 L 89.416,109.77 L 90.569,110.35 L 91.818,110.92 L 92.971,111.59 L 94.123,112.26 L 95.18,113.03 L 99.695,107.37 L 98.254,106.41 L 96.813,105.65 L 95.372,104.88 L 94.027,104.21 L 92.586,103.63 L 91.338,103.15 L 89.993,102.67 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 112.95,97.974 L 114.39,99.413 L 115.83,100.95 L 117.18,102.48 L 118.43,104.11 L 119.68,105.84 L 120.93,107.66 L 121.98,109.48 L 123.04,111.4 L 125.15,116.1 L 126.79,120.89 L 127.94,125.69 L 128.61,130.58 L 128.71,135.47 L 128.42,140.36 L 127.55,145.06 L 126.4,149.76 L 124.67,154.27 L 122.56,158.68 L 119.96,162.8 L 117.08,166.73 L 113.72,170.38 L 109.97,173.73 L 105.94,176.71 L 101.42,179.29 L 97.966,180.93 L 94.508,182.27 L 90.953,183.32 L 87.399,184.09 L 83.845,184.67 L 80.29,184.95 L 76.64,184.95 L 73.085,184.67 L 69.627,184.19 L 66.169,183.51 L 62.71,182.56 L 59.348,181.31 L 56.082,179.87 L 53.008,178.24 L 49.934,176.32 L 47.052,174.21 L 50.03,176.8 L 53.104,179.1 L 56.37,181.12 L 59.732,182.94 L 63.287,184.47 L 66.841,185.72 L 70.588,186.68 L 74.334,187.45 L 78.177,187.83 L 82.019,188.02 L 85.958,187.83 L 89.801,187.35 L 93.643,186.58 L 97.486,185.53 L 101.23,184.09 L 104.98,182.36 L 109.49,179.77 L 113.53,176.8 L 117.27,173.45 L 120.64,169.8 L 123.52,165.87 L 126.11,161.75 L 128.23,157.33 L 129.86,152.83 L 131.11,148.13 L 131.88,143.33 L 132.26,138.44 L 132.07,133.55 L 131.49,128.66 L 130.34,123.87 L 128.71,119.07 L 126.59,114.37 L 125.25,111.98 L 123.81,109.67 L 122.17,107.47 L 120.54,105.36 L 118.72,103.34 L 116.89,101.43 L 114.97,99.605 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF383838"/>
</Path.Fill>
</Path>
<Path
Data="M 52.624,63.739 L 69.243,95.865 L 69.723,95.385 L 70.203,95.002 L 70.588,94.522 L 71.068,94.138 L 71.452,93.659 L 71.74,93.275 L 72.125,92.892 L 72.413,92.508 L 56.466,61.725 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF383838"/>
</Path.Fill>
</Path>
<Path
Data="M 47.628,66.328 L 64.728,99.317 L 65.4,98.837 L 66.073,98.358 L 66.649,97.974 L 67.225,97.495 L 50.318,64.89 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF383838"/>
</Path.Fill>
</Path>
<Path
Data="M 44.554,70.26 L 46.187,69.397 L 47.724,68.438 L 49.262,67.575 L 50.702,66.616 L 52.143,65.657 L 53.392,64.698 L 54.641,63.739 L 55.794,62.78 L 56.851,61.821 L 57.811,60.862 L 58.676,59.903 L 59.444,58.944 L 60.117,58.081 L 60.693,57.218 L 61.173,56.355 L 61.462,55.492 L 61.75,54.245 L 61.75,53.19 L 61.558,52.327 L 61.27,51.656 L 61.077,51.368 L 60.885,51.081 L 60.597,50.697 L 60.309,50.409 L 59.925,50.122 L 59.444,49.834 L 58.868,49.546 L 58.292,49.355 L 57.427,49.163 L 56.466,48.971 L 55.41,48.875 L 54.257,48.971 L 53.008,48.971 L 51.759,49.163 L 50.414,49.45 L 49.069,49.738 L 47.532,50.122 L 46.091,50.601 L 44.554,51.081 L 42.921,51.656 L 41.384,52.327 L 39.751,52.999 L 38.022,53.766 L 36.389,54.629 L 34.564,55.588 L 32.642,56.739 L 30.913,57.794 L 29.184,58.944 L 27.551,60.191 L 26.014,61.342 L 24.573,62.588 L 23.228,63.835 L 22.075,65.082 L 21.115,66.328 L 20.346,67.575 L 19.674,68.822 L 19.29,69.972 L 19.193,71.123 L 19.29,72.178 L 19.674,73.233 L 19.866,73.521 L 20.058,73.808 L 20.346,74.096 L 20.634,74.384 L 21.115,74.767 L 21.595,75.055 L 22.075,75.343 L 22.748,75.534 L 23.612,75.726 L 24.573,75.918 L 25.63,75.918 L 26.686,75.918 L 27.935,75.822 L 29.184,75.63 L 30.529,75.439 L 31.97,75.151 L 33.411,74.767 L 34.852,74.288 L 36.389,73.808 L 38.022,73.233 L 39.559,72.562 L 41.192,71.89 L 42.921,71.123 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF777777"/>
</Path.Fill>
</Path>
<Path
Data="M 23.132,71.411 L 23.132,71.219 L 23.132,71.027 L 23.132,70.836 L 23.228,70.548 L 23.805,69.397 L 24.765,68.055 L 26.11,66.616 L 27.839,64.986 L 29.857,63.26 L 32.354,61.534 L 35.14,59.807 L 38.214,58.081 L 39.847,57.314 L 41.384,56.547 L 42.921,55.876 L 44.458,55.3 L 45.803,54.725 L 47.244,54.245 L 48.589,53.862 L 49.838,53.478 L 50.991,53.286 L 52.143,52.999 L 53.2,52.903 L 54.161,52.807 L 55.025,52.807 L 55.794,52.807 L 56.466,52.903 L 57.043,52.999 L 57.331,53.095 L 57.523,53.19 L 57.715,53.382 L 57.811,53.478 L 57.907,53.766 L 57.811,54.149 L 57.619,54.629 L 57.331,55.204 L 56.947,55.971 L 56.37,56.643 L 55.602,57.506 L 54.833,58.369 L 53.873,59.328 L 52.72,60.287 L 51.471,61.342 L 50.03,62.397 L 48.397,63.451 L 46.668,64.602 L 44.746,65.657 L 42.729,66.808 L 41.096,67.575 L 39.559,68.342 L 38.022,69.013 L 36.485,69.589 L 35.14,70.164 L 33.699,70.644 L 32.354,71.027 L 31.105,71.315 L 29.953,71.603 L 28.8,71.794 L 27.743,71.986 L 26.783,72.082 L 25.918,72.082 L 25.149,72.082 L 24.477,71.986 L 23.901,71.794 L 23.612,71.699 L 23.42,71.603 L 23.228,71.507 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF000000"/>
</Path.Fill>
</Path>
<Path
Data="M 41.769,58.752 L 40.52,57.698 L 39.079,56.451 L 37.542,54.917 L 36.197,53.286 L 35.044,51.56 L 34.179,49.93 L 33.891,48.396 L 34.083,46.957 L 35.332,43.697 L 36.101,41.012 L 36.389,38.614 L 36.197,36.504 L 35.62,34.586 L 34.66,32.86 L 33.507,31.038 L 32.066,29.12 L 31.586,28.545 L 31.105,27.874 L 30.625,27.298 L 30.145,26.627 L 30.145,26.627 L 29.568,26.148 L 28.896,25.86 L 28.127,25.86 L 27.455,26.243 L 26.975,26.819 L 26.686,27.49 L 26.686,28.257 L 26.975,28.929 L 26.975,28.929 L 27.551,29.6 L 28.031,30.271 L 28.512,30.942 L 28.992,31.518 L 30.241,33.052 L 31.201,34.491 L 31.97,35.833 L 32.354,37.272 L 32.45,38.806 L 32.162,40.628 L 31.586,42.834 L 30.529,45.423 L 29.953,48.204 L 30.433,51.081 L 31.778,53.766 L 33.603,56.259 L 35.524,58.369 L 37.446,60.095 L 38.791,61.342 L 39.463,61.821 L 39.463,61.821 L 40.135,62.205 L 40.904,62.205 L 41.576,61.917 L 42.153,61.438 L 42.537,60.766 L 42.537,59.999 L 42.249,59.328 L 41.769,58.752 Z ">
<Path.Fill>
<SolidColorBrush Color="#FFFF1900"/>
</Path.Fill>
</Path>
<Path
Data="M 59.925,139.59 L 60.597,130.2 L 27.167,127.61 L 26.398,137 Z ">
<Path.Fill>
<SolidColorBrush Color="#FF000000"/>
</Path.Fill>
</Path>
</Canvas> </UserControl>

CS:

  public bool IsFalling
{
get;
set;
}

后置代码中主要就是一个属性,用于标示地雷是坠落了还是被点中了。
主窗体:

  <Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="280"></ColumnDefinition>
</Grid.ColumnDefinitions> <Border BorderBrush="SteelBlue" BorderThickness="1" Margin="5">
<Grid>
<Canvas x:Name="canvasBackground" SizeChanged="canvasBackground_SizeChanged" MinWidth="50">
<Canvas.Background>
<RadialGradientBrush>
<GradientStop Color="AliceBlue" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="0.7"></GradientStop>
</RadialGradientBrush>
</Canvas.Background>
</Canvas>
</Grid>
</Border> <Border Grid.Column="1" BorderBrush="SteelBlue" BorderThickness="1" Margin="5">
<Border.Background>
<RadialGradientBrush GradientOrigin="1,0.7" Center="1,0.7" RadiusX="1" RadiusY="1">
<GradientStop Color="Orange" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="1"></GradientStop>
</RadialGradientBrush>
</Border.Background>
<StackPanel Margin="15" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock FontFamily="微软雅黑" FontSize="35" Foreground="LightSteelBlue">地雷下坠</TextBlock>
<TextBlock x:Name="lblRate" Margin="0,30,0,0" TextWrapping="Wrap" FontFamily="Georgia" FontSize="14"></TextBlock>
<TextBlock x:Name="lblSpeed" Margin="0,30" TextWrapping="Wrap" FontFamily="Georgia" FontSize="14"></TextBlock>
<TextBlock x:Name="lblStatus"
TextWrapping="Wrap" FontFamily="微软雅黑" FontSize="20">没有地雷落地.</TextBlock>
<Button x:Name="cmdStart" Padding="5" Margin="0,30" Width="80" Content="Start Game" Click="cmdStart_Click"></Button>
</StackPanel>
</Border>
</Grid>

主窗体主要是两列的一个Grid,左边为地雷区域(主要是一个Canvas容器),右边为操作和显示信息的区域。
CS--字段:

       //存放Bomb和动画的键值对
private Dictionary<Bomb, Storyboard> storyboards = new Dictionary<Bomb, Storyboard>();
//运行于UI线程的Timer,用于定时绘制图形到UI
private DispatcherTimer bombTimer = new DispatcherTimer();
#region 图形相关
//坠落的图形数量
private int droppedCount = ;
//点中的图形数量
private int savedCount = ;
//初始时候每1.3秒执行一次动画
private double initialSecondsBetweenBombs = 1.3;
//图形的降落时间
private double initialSecondsToFall = 3.5;
//Bomp动画周期
private double secondsToFall;
#endregion #region Timer
//Timer执行周期
private double secondsBetweenBombs;
#endregion #region 调节相关
//Timer的调节时间间距,默认为每15秒调节一次
private double secondsBetweenAdjustments = ;
//记录最后一次的调节时间
private DateTime lastAdjustmentTime = DateTime.MinValue;
//用于减少Timer运行周期的值
private double secondsBetweenBombsReduction = 0.1;
//用于减少动画执行的周期的值
private double secondsToFallReduction = 0.1;
#endregion //最大降落数量,如果超出则结束游戏
private int maxDropped = ;

CS--Timer事件和动画:

       private void bombTimer_Tick(object sender, EventArgs e)
{
//创建Bomb
Bomb bomb = new Bomb();
bomb.IsFalling = true;
canvasBackground.Children.Add(bomb); //随机计算Bomb的Left值
Random random = new Random();
Canvas.SetLeft(bomb, random.Next(, (int)canvasBackground.ActualWidth - ));
Canvas.SetTop(bomb, -); //添加点击时的动画
bomb.MouseLeftButtonDown += bomb_MouseLeftButtonDown; Storyboard sbBomb = new Storyboard(); #region 创建下坠的动画
//创建下坠的动画
DoubleAnimation fallAnimation = new DoubleAnimation();
//设置动画的目标位Canvas的高度
fallAnimation.To = canvasBackground.ActualHeight;
//设置运行时间
fallAnimation.Duration = TimeSpan.FromSeconds(secondsToFall);
Storyboard.SetTarget(fallAnimation, bomb);
Storyboard.SetTargetProperty(fallAnimation, new PropertyPath("(Canvas.Top)"));
sbBomb.Children.Add(fallAnimation);
#endregion #region 创建Bomb左右摇摆动画
//创建Bomb左右摇摆动画
DoubleAnimation wiggleAnimation = new DoubleAnimation();
wiggleAnimation.To = ;
wiggleAnimation.Duration = TimeSpan.FromSeconds(0.2);
wiggleAnimation.RepeatBehavior = RepeatBehavior.Forever;
wiggleAnimation.AutoReverse = true;
Storyboard.SetTarget(wiggleAnimation, bomb);
Storyboard.SetTargetProperty(wiggleAnimation, new PropertyPath("RenderTransform.Children[0].Angle"));
sbBomb.Children.Add(wiggleAnimation);
#endregion sbBomb.Duration = fallAnimation.Duration;
//动画完成事件
sbBomb.Completed += sbBomb_Completed;
//开始动画
sbBomb.Begin(); //将动画和Bomb对象放入键值对集合
storyboards.Add(bomb, sbBomb); //如果当前时间和最后一次调整的时间差大于指定的间隔
if ((DateTime.Now.Subtract(lastAdjustmentTime).TotalSeconds > secondsBetweenAdjustments))
{
lastAdjustmentTime = DateTime.Now; //每调整一次都要减少Timer的运行周期
secondsBetweenBombs -= secondsBetweenBombsReduction;
//调整Bomb动画结束的周期值
secondsToFall -= secondsToFallReduction;
//重新设置Timer的运行周期
bombTimer.Interval = TimeSpan.FromSeconds(secondsBetweenBombs); lblRate.Text = String.Format("每{0}秒出现一个地雷.", secondsBetweenBombs);
lblSpeed.Text = String.Format("每个地雷{0}秒降落到底部.", secondsToFall);
}
} void sbBomb_Completed(object sender, EventArgs e)
{
ClockGroup clockGroup = sender as ClockGroup;
//得到下坠动画对象
DoubleAnimation completedAnimation = clockGroup.Children[].Timeline as DoubleAnimation;
//得到当前动画的关联对象
Bomb completedBomb = Storyboard.GetTarget(completedAnimation) as Bomb;
if (completedBomb.IsFalling)
{
droppedCount++;
}
else
{
savedCount++;
} lblStatus.Text = String.Format("坠落了{0}个炸弹,解救了{1}个炸弹.", droppedCount, savedCount);
//如果坠落的数量大于了最大允许坠落数量
if (droppedCount > maxDropped)
{
bombTimer.Stop();
lblStatus.Text += "\r\n\r\n游戏结束."; foreach (KeyValuePair<Bomb, Storyboard> item in storyboards)
{
Bomb bomb = item.Key;
Storyboard story = item.Value;
//将图形从Canvas中移除
canvasBackground.Children.Remove(bomb);
//停止动画
story.Stop();
} storyboards.Clear();
cmdStart.IsEnabled = true;
}
//否则则对动画对象和Bomb做清理工作
else
{
//结束动画
Storyboard storyBoard = clockGroup.Timeline as Storyboard;
storyBoard.Stop(); //从动画集合中移除
storyboards.Remove(completedBomb);
//将Bomb从Canvas中移除
canvasBackground.Children.Remove(completedBomb);
}
}

CS--地雷点击事件(让地雷消失):

  private void bomb_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Bomb bomb = sender as Bomb;
bomb.IsFalling = false; //记录下Bomb的当前位置
double currentTop = Canvas.GetTop(bomb);
double currentLeft = Canvas.GetLeft(bomb); //找到Bomb对应的动画,并结束
Storyboard sbBomb = storyboards[bomb];
sbBomb.Stop();
sbBomb.Children.Clear(); //创建上升动画,使Bomb消失
DoubleAnimation riseAnimation = new DoubleAnimation();
riseAnimation.From = currentTop;
riseAnimation.To = ;
riseAnimation.Duration = TimeSpan.FromSeconds();
Storyboard.SetTarget(riseAnimation, bomb);
Storyboard.SetTargetProperty(riseAnimation, new PropertyPath("(Canvas.Top)"));
sbBomb.Children.Add(riseAnimation); //水平移除的动画
DoubleAnimation slideAnimation = new DoubleAnimation();
//如果当前Bomb不在中间位置,则直接移出到左边
if (currentLeft < canvasBackground.ActualWidth / )
{
slideAnimation.To = -;
}
//否则直接移出到右边
else
{
slideAnimation.To = canvasBackground.ActualWidth + ;
} slideAnimation.Duration = TimeSpan.FromSeconds();
Storyboard.SetTarget(slideAnimation, bomb);
Storyboard.SetTargetProperty(slideAnimation, new PropertyPath("(Canvas.Left)"));
sbBomb.Children.Add(slideAnimation); sbBomb.Duration = slideAnimation.Duration;
sbBomb.Begin();
}

CS--开始事件:

   private void cmdStart_Click(object sender, RoutedEventArgs e)
{
cmdStart.IsEnabled = false; //清空数据
droppedCount = ;
savedCount = ;
//设置Timer的周期
secondsBetweenBombs = initialSecondsBetweenBombs;
//设置动画完成的时间
secondsToFall = initialSecondsToFall;
//设置Timer时间
bombTimer.Interval = TimeSpan.FromSeconds(secondsBetweenBombs);
//开始Timer
bombTimer.Start();
}

CS--窗体大小改变事件:
只所以写此事件是为了防止地雷显示在了Canvas区域之外。

        private void canvasBackground_SizeChanged(object sender, SizeChangedEventArgs e)
{
//窗体改变大小后要动态的裁剪Canvas,防止图形超出Left范围
RectangleGeometry rect = new RectangleGeometry();
rect.Rect = new Rect(, ,
canvasBackground.ActualWidth, canvasBackground.ActualHeight);
canvasBackground.Clip = rect;
}

执行过程:
1.点击开始按钮开始一个Timer的动作,根据设置的初始值每x秒执行一次Timer。
2.在Timer中创建Bomb控件,同时给其创建两个动画,一个负责向下坠落,一个负责左右摇摆,这样就加大了点击的难度。另外在动画过程中会动态的调整Timer的周期时间以及Bomb的动画时间,也是为了加大难度。
3.在每个动画的完成事件中得到当前的Bomb对象和动画对象,判断Bomb是自然坠落了还是点击了;如果是自然坠落则累加坠落的地雷数量,同时将Bomb对象从页面中移除,也从集合中移除动画;如果是点击,则将他们从集合中移除即可。每次动画结束都检测坠落的地雷是否已经达到了最大数量限制,然后决定是游戏结束还是继续执行。
4.当点击了一个Bomb之后,执行两个动画,一个控制Bomb的Top直到消失,一个控制Bomb的Left直到消失(Left要根据当前Bomb的所在位置判断是向右移动还是向左移动),并且标示为点击消失(即IsFalling为false)。

为了方便大家,我把动画的Demo源码贴出来,戳我

希望大家多多交流和指出错误之处。

WPF之小动画三的更多相关文章

  1. WPF之小动画二

    上一篇文章简单介绍了动画的定义方法和一些控制动画的方法,并没有涉及复杂属性的动画处理方式,本文将继续动画的其它方面的使用. 写在前面(对于一些动画操作时候的建议): 1.如果希望某个元素从显示到消失, ...

  2. WPF之小动画一

    定义动画: 直接使用Element进行BeginAnimation DoubleAnimation animation = new DoubleAnimation(); animation.By = ...

  3. WPF中的动画——(三)时间线(TimeLine)

    WPF中的动画——(三)时间线(TimeLine) 时间线(TimeLine)表示时间段. 它提供的属性可以让控制该时间段的长度.开始时间.重复次数.该时间段内时间进度的快慢等等.在WPF中内置了如下 ...

  4. 三个loading小动画实例

    直接贴代码: <!DOCTYPE html><html><head>    <meta charset="utf-8">    &l ...

  5. 如何制作网页小动画?——gif or png

    一.场景与动画 为了拉动网站氛围,或者吸引用户浏览焦点,需要使用一些小动画.这种动画不是(gif)单纯的重复,而是需要需要一些控制和交互,比如在动画完成后打开一个对话框.动画有几个基本要素(时间控制, ...

  6. WPF编程学习——动画

    前言 使用动画,是增强用户体验的一种有效的手段.合理的动画,可以让应用程序的界面看起来更加自然.真实.流畅.舒适,更有效地向用户展现信息,用户也更容易接受.同时也增加了软件使用的乐趣,提高用户粘度.( ...

  7. WPF 有趣的动画效果

    WPF 有趣的动画效果         这一次我要呈上一个简单的文章,关于给你的WPF apps加入美丽的光线动画,可是我对动画这东西可能有点入迷了.         实际上.我对动画如此的入迷,以至 ...

  8. WPF 画线动画效果实现

    原文:WPF 画线动画效果实现 弄了将近三天才搞定的,真是艰辛的实现. 看了很多博客,都太高深了,而且想要实现的功能都太强大了,结果基础部分一直实现不了,郁闷啊~ 千辛万苦终于找到了一个Demo,打开 ...

  9. WPF特效-粒子动画

    原文:WPF特效-粒子动画 WPF实现泡泡龙小游戏效果.     /// -Ball to Ball Collision - Detection and Handling    /// http:// ...

随机推荐

  1. L010-oldboy-mysql-dba-lesson10

    L010-oldboy-mysql-dba-lesson10 来自为知笔记(Wiz)

  2. WinForm C#全局错误捕捉处理【整理】

    static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...

  3. xml直接读取节点

    <root> <books> <book id="one"></book> <book id="two"& ...

  4. PHP去掉转义后字符串中的反斜杠\函数stripslashes

    addslashes函数主要是在字符串中添加反斜杠对特殊字符进行转义,stripslashes则是去掉转义后字符串中的反斜杠\,比如当你提交一段 json数据到PHP端的时候可能会遇到json字符串中 ...

  5. liger grid loadData

    function fn_Search() { var beginDt = $("#txtBegin").val(); var endDt = $("#txtEnd&quo ...

  6. 正则表达式模块re

    正则表达式通过特定的式子匹配某种类型的字符串.对字符串进行匹配验证或者从大量的字符串里提取出特定的信息. 正则表达式包含普通字符和特殊字符.大部分的普通字符如‘A’或‘0’可以简单的来匹配自己.如te ...

  7. WebApp之 apple-touch-icon

    在iPhone,iPad,iTouch的safari上可以使用添加到主屏按钮将网站添加到主屏幕上.apple-touch-icon是IOS设备的私有标签,如果设置了相应apple-touch-icon ...

  8. Web前端框架学习成本比较及学习方法

    就项目中自己用过的前端框架的学习成本比较与学习心得分享 刚工作时间不长只用过这几个框架下面是难易程度比较: 不论哪个web前端框架, 究其本质都是把页面的数据传递给后台服务器语言(如java)进行处理 ...

  9. HttpClient抓取网页内容简单介绍

    版本HttpClient3.1 1.GET方式 第一步.创建一个客户端,类似于你用浏览器打开一个网页 HttpClient httpClient = new HttpClient(); 第二步.创建一 ...

  10. Datatables中文API——回调函数

    fnCookieCallback:还没有使用过 $(document).ready(function () { $('#example').dataTable({ "fnCookieCall ...