Silverlight:手把手教你写俄罗斯方块(五)(完)
/// <summary> /// 构造固定砖块 /// </summary> /// <param name="high">高度</param> private void Paintguding(int high) { for (int h = 0; h < high; h++) { for (int i = 0; i < width; i++) { staticRect[i, height - 1 - h] = true; } Random rd = new Random(); int len = rd.Next(1, 5); for (int l = 0; l < len; l++) { int ii = rd.Next(0, 9); staticRect[ii, 19 - h] = false; } System.Threading.Thread.Sleep(20); } this.PaintBack(); }
原理就是,我们根据高度,先把指定高度的所有方块全部填满(即赋值为true),然后取1-4的随机数作为len的值,len表示一行中有几个方块被挖掉,也就是所谓的空白,然后遍历这个长度,在这一行中随机取len个方块,将它们挖掉(即赋值为false)。这里使线程暂停了20毫米,这样做可以防止随机数产生重复数的概率过高。然后绘制画板。
二.游戏开始的方法:
public void StartGame() { this.Clear(); this.Paintguding(12); runBlock = GetBlock(4, 0); runBlock.Show(board); System.Threading.Thread.Sleep(200); //防止移动方块和准备方块一样 readyBlock = GetBlock(1, 1); readyBlock.Show(readyBoard); status = GameStatus.Ready; }
Clear方法相当于把画板和积分全部清空,或许您觉得这个方法好像并没有必要,但是在游戏结束后,重新开始的时候,我们就需要执行这个方法重新初始化一遍了。具体代码如下:
private void Clear() { this.score.Text = "0"; //清空积分 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { staticRect[i, j] = false; board[i, j].Color = null; } } this.PaintReadyBack(); }
继续游戏与暂停游戏,代码如下:
/// <summary> /// 继续游戏(启动计时器) /// </summary> public void Play() { status = GameStatus.Play; timer.Start(); } /// <summary> /// 暂停游戏(停止计时器) /// </summary> public void Pause() { status = GameStatus.Pause; timer.Stop(); }
游戏结束,我们采用的是.net的事件机制,这样的好处是,由UI层去捕获这个事件,然后决定做什么事情。上一节中,当游戏结束时,我们执行了这个OnGameOver方法,这个方法用于把GameOver事件fire出去,具体代码如下:
private void OnGameOver(EventArgs e) { //游戏结束 status = GameStatus.Over; timer.Stop(); EventHandler handler = GameOver; if (handler != null) { handler(this, e); } }
三.至此,Control类已经构建完毕,接下来我们打开MainPage.xaml,接着添加一个Canvas作为准备方块画板,添加TextBlock作为显示积分,添加一个Button,然后为UserControl添加一个x:Name属性,命名为“uc”,具体xaml代码如下:
<Border Width="95" Height="95" BorderThickness="2" BorderBrush="Black" Background="#FFFAF0F0" CornerRadius="10" Canvas.Left="380" Canvas.Top="83"> <Canvas x:Name="readyBoard" Height="80" Width="80" Background="Black" Canvas.Left="300" Canvas.Top="43"/> </Border> <Button x:Name="btnPlay" Content="开始游戏" Width="75" Click="Button_Click" Canvas.Left="394" Canvas.Top="241"/> <TextBlock Text="你的积分:" TextWrapping="Wrap" Canvas.Left="390" Canvas.Top="200" Width="84" FontSize="14"/> <TextBlock x:Name="txtScore" Width="40" Canvas.Left="460" Canvas.Top="200" FontSize="14" Text="0" TextWrapping="Wrap" Foreground="Red"/>
打开MainPage.xaml.cs,在load事件中,构建一个Control类,把Control类的board添加到我们的画板中:
private Control ctrl; void MainPage_Loaded(object sender, RoutedEventArgs e) { uc.Focus(); ctrl = new Control(this.txtScore); for (int i = 0; i < 10; i++) { for (int j = 0; j < 20; j++) { this.playBoard.Children.Add(ctrl.board[i, j]); } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { this.readyBoard.Children.Add(ctrl.readyBoard[i, j]); } } ctrl.GameOver += new EventHandler(ctrl_GameOver); }
我们为uc的KeyDown事件添加如下代码:
private void uc_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Left) { ctrl.MoveLeft(); } else if (e.Key == Key.Right) { ctrl.MoveRight(); } else if (e.Key == Key.Up) { ctrl.Change(); } else if (e.Key == Key.Down) { ctrl.CheckAndOverBlock(); ctrl.MoveDown(); } else if (e.Key == Key.Ctrl) { ctrl.Drop(); } }
通过方向键和Ctrl键来进行游戏。
为按钮添加点击事件:
private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { string text = this.btnPlay.Content.ToString(); if (text == "开始游戏" || text == "重新开始") { ctrl.StartGame(); ctrl.Play(); this.btnPlay.Content = "暂停游戏"; } else if (text == "暂停游戏") { ctrl.Pause(); this.btnPlay.Content = "继续游戏"; } else if (text == "继续游戏") { ctrl.Play(); this.btnPlay.Content = "暂停游戏"; } }
游戏结束事件:
void ctrl_GameOver(object sender, EventArgs e) { this.btnPlay.Content = "重新开始"; MessageBox.Show("游戏结束"); }
当然游戏结束后,您可以执行任何自定义代码。
好了,Ctrl+F5,一个单机版的俄罗斯方块游戏已经产生了,玩着自己写出的游戏,会不会有成就感呢?如果您还想了解silverlight与服务器通信的方式,实现英雄板的功能,请继续关注接下来的文章。