练手WPF(二)——2048游戏的简易实现(下)
接着上一篇继续~~~
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游戏的简易实现(下)的更多相关文章
- 练手WPF(三)——扫雷小游戏的简易实现(中)
八.随机布雷 /// <summary> /// 随机布地雷 /// </summary> /// <param name="mineNum"> ...
- 练手WPF(一)——模拟时钟与数字时钟的制作(上)
一.Visual Studio创建一个WPF项目. 简单调整一下MainWindow.xaml文件.主要使用了两个Canvas控件,分别用于显示模拟和数字时钟,命名为AnalogCanvas.digi ...
- 练手WPF(二)——2048游戏的简易实现(上)
1.创建游戏界面编辑MainWindow.xaml,修改代码如下: <Window.Resources> <Style TargetType="Label"> ...
- 练手WPF(三)——扫雷小游戏的简易实现(上)
一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resourc ...
- 练手WPF(四)——贪吃蛇小游戏的简易实现(上)
一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...
- 练手WPF(三)——扫雷小游戏的简易实现(下)
十四.响应鼠标点击事件 (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <para ...
- 练手WPF(四)——贪吃蛇小游戏的简易实现(下)
八.生成新的单节蛇身我们这里先说说游戏小原理好了,游戏运行后,通过计时器事件不断生成新的单节蛇身类SnakeNode,添加到List中的0位置,原来的蛇头变成了第二节.该节新蛇头的坐标通过蛇头前进方向 ...
- 微信小程序框架分析小练手(二)——天气微信小程序制作
简单的天气微信小程序. 一.首先,打开微信开发者工具,新建一个项目:weather.如下图: 二.进入app.json中,修改导航栏标题为“贵州天气网”. 三.进入index.wxml,进行当天天气情 ...
- 练手WPF(一)——模拟时钟与数字时钟的制作(中)
今天接着制作数字时钟 数字时钟主要用到Path控件,主要用于定义数字笔划的形状. (1)添加一个DigitLine类 数字时钟的数字8由7笔组成,看如下定义的字段字符串数组PathDatas,每个st ...
随机推荐
- python基础(30):黏包、socket的其他方法
1. 黏包 1.1 黏包现象 让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd) 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接 ...
- 多线程学习三:Thread API,ThreadLocal,synchronized,volatile和Condition
一.Thread API: setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 首先要了解什么是Thread. ...
- 爬取动态html网页,requests+execjs
请求地址:https://g.hongshu.com/content/99269/15382723.html 网页内容为动态执行js所得 1.直接浏览器模拟 不用考虑页面的业务逻辑什么的,直接得到结果 ...
- 安全意识第三期丨关于高速ETC办理的这些新骗局,速看!
近期,最火爆的莫过于ETC了. 不仅各大银行,甚至微信和支付宝都推出了办理服务. 虽说更加便捷了,却也带来了安全隐患. 下面这个案例,大家一定要注意,已经有很多车主“中招”,落入了骗子的圈套. 注意: ...
- Flutter 你需要知道的那些事 01
公众号「AndroidTraveler」首发. 1. width 属性 对于设置控件宽度填充父控件这件事情,在 Android 里面,只需要设置 MATCH_PARENT 即可. 但是在 Flutte ...
- springboot整合spring Data JPA
今天敲代码,一连串的错误,我也是服气~果然,我们不是在出bug,就是在找bug的路上…… 今天完成的是springboot整合spring data JPA ,出了一连串的错,真是头大 java.sq ...
- 运行java程序
使用方式: java类名 硬盘上有HelloWorld.class,那么类名就是HelloWorld java HelloWorld[运行先到class路径下] 一定要注意:java命令后面跟的不是文 ...
- Html学习之十九(表格与表单学习--邮箱注册页面设计)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 史上最全的LaTeX特殊符号语法
史上最全的LaTeX特殊符号语法 运算符 语法 效果 语法 效果 语法 效果 + \(+\) - \(-\) \triangleleft \(\triangleleft\) \pm \(\pm\) \ ...
- Python __slots__
Python 类的特殊变量:__slots__ 使用 __slots__ 后,类中 __weakref__ 和 __dict__ 消失,同时阻止动态属性绑定 由于 __dict__ 记录着类中所有的属 ...