接着上一篇继续~~~

6、动画显示增加分数

/// <summary>
/// 动画显示增加得分
/// </summary>
/// <param name="addScore"></param>
private void ShowAddScore(int addScore)
{
lblAddScore.Content = "+" + addScore.ToString(); DoubleAnimation top = new DoubleAnimation();
DoubleAnimation opacity = new DoubleAnimation();
opacity.AutoReverse = true;
opacity.From = ;
opacity.To = ;
top.From = ;
top.To = -;
Duration duration = new Duration(TimeSpan.FromMilliseconds());
top.Duration = duration;
opacity.Duration = duration; tt.BeginAnimation(TranslateTransform.YProperty, top);
lblAddScore.BeginAnimation(Label.OpacityProperty, opacity);
}

该动画通过位置向上移动和透明度变化实现。

7、移动操作
  7.1 移动操作方法
每按下一次上下左右键,则调用相应的移动操作方法。以前实现的,代码比较繁琐,这次没去精简清理,看看就好。这是左移操作方法:

/// <summary>
/// 左移
/// </summary>
private void MoveLeft()
{
int score = ; Storyboard sb1 = new Storyboard(); // 移去左侧和中间的空块(左移)
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
for (int i = x + ; i < ; i++)
{
if (gridData[y, i] != && gridData[y, x] == )
{
gridData[y, x] = gridData[y, i]; if (lblArray[y, i] == null)
{
lblArray[y, i] = new Label();
lblArray[y, i].SetValue(Canvas.LeftProperty, lblPadding * ((i) + ) + (double)((i) * lblWidth));
lblArray[y, i].SetValue(Canvas.TopProperty, lblPadding * (y + ) + (double)(y * lblWidth));
lblArray[y, i].SetValue(Label.ContentProperty, gridData[y, i].ToString());
lblArray[y, i].SetValue(Label.BackgroundProperty, SetBackground(gridData[y, i]));
lblArray[y, i].SetValue(Button.FontSizeProperty, (double)SetFontSize(gridData[y, i]));
} // 左移方块动画
DoubleAnimation da1 = null;
double from = (double)lblArray[y, i].GetValue(Canvas.LeftProperty);
double to = (x + ) * lblPadding + x * lblWidth;
da1 = new DoubleAnimation(
from,
to,
new Duration(TimeSpan.FromMilliseconds()));
da1.AccelerationRatio = 0.1;
da1.DecelerationRatio = 0.1; Storyboard.SetTarget(da1, lblArray[y, i]);
Storyboard.SetTargetProperty(da1, new PropertyPath("(Canvas.Left)"));
sb1.Children.Add(da1); gridData[y, i] = ;
}
}
}
} // 相邻相同方块合并后加到左侧
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
if (x + < && gridData[y, x] == gridData[y, x + ])
{
// 如果右侧的方块未及时生成
if (gridData[y, x + ] != )// && gridData[y,x]!=0)
{
if (lblArray[y, x + ] == null)
{
lblArray[y, x + ] = new Label();
lblArray[y, x + ].SetValue(Canvas.LeftProperty, lblPadding * ((x + ) + ) + (double)((x + ) * lblWidth));
lblArray[y, x + ].SetValue(Canvas.TopProperty, lblPadding * (y + ) + (double)(y * lblWidth));
lblArray[y, x + ].SetValue(Label.ContentProperty, gridData[y, x + ].ToString());
lblArray[y, x + ].SetValue(Label.BackgroundProperty, SetBackground(gridData[y, x + ]));
lblArray[y, x + ].SetValue(Button.FontSizeProperty, (double)SetFontSize(gridData[y, x + ]));
} // 左移动画
DoubleAnimation da2 = null;
double from = (double)lblArray[y, x + ].GetValue(Canvas.LeftProperty);
double to = from - lblWidth - lblPadding;
da2 = new DoubleAnimation(
from,
to,
new Duration(TimeSpan.FromMilliseconds()));
da2.AccelerationRatio = 0.1;
da2.DecelerationRatio = 0.1;
Storyboard.SetTarget(da2, lblArray[y, x + ]);
Storyboard.SetTargetProperty(da2, new PropertyPath("(Canvas.Left)"));
sb1.Children.Add(da2);
}
gridData[y, x] *= ;
gridData[y, x + ] = ; score += gridData[y, x];
}
}
} if (score != )
{
ShowAddScore(score);
currScore += score;
lblCurrScore.Content = currScore.ToString();
} // 将合并后出现的中间空方块移去(再次左移一次)
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
for (int i = x + ; i < ; i++)
{
if (gridData[y, i] != && gridData[y, x] == )
{
gridData[y, x] = gridData[y, i]; if (lblArray[y, i] == null)
{
lblArray[y, i] = new Label();
lblArray[y, i].SetValue(Canvas.LeftProperty, lblPadding * ((i) + ) + (double)((i) * lblWidth));
lblArray[y, i].SetValue(Canvas.TopProperty, lblPadding * (y + ) + (double)(y * lblWidth));
lblArray[y, i].SetValue(Label.ContentProperty, gridData[y, i].ToString());
lblArray[y, i].SetValue(Label.BackgroundProperty, SetBackground(gridData[y, i]));
lblArray[y, i].SetValue(Button.FontSizeProperty, (double)SetFontSize(gridData[y, i]));
} // 左移动画
DoubleAnimation da = null;
double from = (double)lblArray[y, i].GetValue(Canvas.LeftProperty);
double to = (x + ) * lblPadding + x * lblWidth;
da = new DoubleAnimation(
from,
to,
new Duration(TimeSpan.FromMilliseconds()));
da.AccelerationRatio = 0.1;
da.DecelerationRatio = 0.1;
Storyboard.SetTarget(da, lblArray[y, i]);
Storyboard.SetTargetProperty(da, new PropertyPath("(Canvas.Left)"));
sb1.Children.Add(da); gridData[y, i] = ; // isMove = true;
}
}
}
} sb1.Completed += Sb1_Completed; // 所有动画完成后执行事件
sb1.Begin();
} /// <summary>
/// 动画完成后运行事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Sb1_Completed(object sender, EventArgs e)
{
// 检查游戏是否结束
if (isGameOver())
{
ShowGameOver();
}
else
{
NewNum();
ShowAllLabel();
}
}

向右、向上和向下的方法类似。

  7.2 xaml文件中添加Window控件的keyDown事件
KeyDown="Window_KeyDown"
对应的cs代码如下:

private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (!isStarted)
return; switch (e.Key)
{
case Key.Left:
if (!isGameOver())
MoveLeft();
else
ShowGameOver();
break; case Key.Right:
if (!isGameOver())
MoveRight();
else
ShowGameOver(); break; case Key.Up:
if (!isGameOver())
MoveUp();
else
ShowGameOver(); break; case Key.Down:
if (!isGameOver())
MoveDown();
else
ShowGameOver();
break;
}
}

大致如此。最后看看效果图吧~~

练手WPF(二)——2048游戏的简易实现(下)的更多相关文章

  1. 练手WPF(三)——扫雷小游戏的简易实现(中)

    八.随机布雷 /// <summary> /// 随机布地雷 /// </summary> /// <param name="mineNum"> ...

  2. 练手WPF(一)——模拟时钟与数字时钟的制作(上)

    一.Visual Studio创建一个WPF项目. 简单调整一下MainWindow.xaml文件.主要使用了两个Canvas控件,分别用于显示模拟和数字时钟,命名为AnalogCanvas.digi ...

  3. 练手WPF(二)——2048游戏的简易实现(上)

    1.创建游戏界面编辑MainWindow.xaml,修改代码如下: <Window.Resources> <Style TargetType="Label"> ...

  4. 练手WPF(三)——扫雷小游戏的简易实现(上)

    一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resourc ...

  5. 练手WPF(四)——贪吃蛇小游戏的简易实现(上)

    一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...

  6. 练手WPF(三)——扫雷小游戏的简易实现(下)

    十四.响应鼠标点击事件    (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <para ...

  7. 练手WPF(四)——贪吃蛇小游戏的简易实现(下)

    八.生成新的单节蛇身我们这里先说说游戏小原理好了,游戏运行后,通过计时器事件不断生成新的单节蛇身类SnakeNode,添加到List中的0位置,原来的蛇头变成了第二节.该节新蛇头的坐标通过蛇头前进方向 ...

  8. 微信小程序框架分析小练手(二)——天气微信小程序制作

    简单的天气微信小程序. 一.首先,打开微信开发者工具,新建一个项目:weather.如下图: 二.进入app.json中,修改导航栏标题为“贵州天气网”. 三.进入index.wxml,进行当天天气情 ...

  9. 练手WPF(一)——模拟时钟与数字时钟的制作(中)

    今天接着制作数字时钟 数字时钟主要用到Path控件,主要用于定义数字笔划的形状. (1)添加一个DigitLine类 数字时钟的数字8由7笔组成,看如下定义的字段字符串数组PathDatas,每个st ...

随机推荐

  1. String substring(int start,int end)截取当前字符串中指定范围内的字符串

    package seday01;/** * String substring(int start,int end) * 截取当前字符串中指定范围内的字符串. * java api有一个特点:通常用两个 ...

  2. django8-django的中间件

    1.django的客户请求流程 之前登录功能 ,需要获取用户的sesssion ,但是每个视图函数都要加装饰器来校验很不合理 ,中间件就可以解决这个问题 用户客户端--->wsgi(封装了req ...

  3. 一文解读VR/AR/MR (转)

    1.VR=虚拟世界 VR,英文是Virtual Reality,中文是虚拟现实. VR眼镜 再细节一点来说,就是模拟一个三维的虚拟世界,在这个虚拟世界中,人们可以感受到视觉.听觉.触觉等方面的刺激. ...

  4. Day_04 面向对象

    概述 对于面向对象编程的支持,Go语言设计得非常简洁而优雅.因为,Go语言并没有沿袭传统 面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承). 虚函 ...

  5. CodeForces - 1007A (思维+双指针)

    题意 https://vjudge.net/problem/CodeForces-1007A 对一个序列重排,使得新的数比原来的数大对应的位置个数最多. 思路 举个栗子,比如1 2 2 3 3 3 3 ...

  6. KMP算法计算next值和nextVal值

    KMP算法: 给定一个主串S及一个模式串P,判断模式串是否为主串的子串:若是,返回匹配的第一个元素的位置(序号从1开始),否则返回0: 这里先不写算法,仅仅计算next和nextVal值 那么计算时只 ...

  7. vue操作select获取option值

    如何实时的获取你选中的值 只用@change件事 @change="changeProduct($event)" 动态传递参数 vue操作select获取option的ID值 如果 ...

  8. 线段树set,add基础

    UVA11992 Fast Matrix Operations https://www.luogu.org/problem/UVA11992 此类模板题建议随便打打就行了233....

  9. 201871010111-刘佳华《面向对象程序设计(java)》第八周学习总结

    201871010111-刘佳华<面向对象程序设计(java)>第八周学习总结 实验七 接口的定义与使用 实验时间 2019-10-18 第一部分:知识总结 接口的概念: ①java为了克 ...

  10. 面向对象程序设计(JAVA) 第11周学习指导及要求

    2019面向对象程序设计(Java)第11周学习指导及要求 (2019.11.8-2018.11.11)   学习目标 理解泛型概念: 掌握泛型类的定义与使用: 掌握泛型方法的声明与使用: 掌握泛型接 ...