介绍

使用 Silverlight 2.0(c#) 开发一个七彩俄罗斯方块

在线游戏





关键

1、每个形状都是由4个“块”组成的,也就是“块”是俄罗斯方块的最小单位,所以首先来写一个“块”的用户控件。要求可以设置“块”的位置和颜色

Block.xaml
  1. <UserControl x:Class="YYTetris.Piece.Block"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  4.     <Canvas>

  5.         <Rectangle x:Name="rectangle" Width="20" Height="20" RadiusX="2" RadiusY="2" Stroke="AntiqueWhite">
  6.             <Rectangle.Fill>
  7.                 <RadialGradientBrush SpreadMethod="Reflect">
  8.                     <GradientStop Color="White" Offset="0" />
  9.                     <GradientStop x:Name="gradientStop" Color="#26F" Offset="1" />
  10.                 </RadialGradientBrush>
  11.             </Rectangle.Fill>
  12.         </Rectangle>

  13.     </Canvas>
  14. </UserControl>
复制代码
Block.xaml.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Documents;
  8. using System.Windows.Input;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Animation;
  11. using System.Windows.Shapes;

  12. namespace YYTetris.Piece
  13. {
  14.     public partial class Block : UserControl
  15.     {
  16.         public Block()
  17.         {
  18.             InitializeComponent();
  19.         }

  20.         public double Top
  21.         {
  22.             set
  23.             {
  24.                 rectangle.SetValue(Canvas.TopProperty, value);
  25.             }
  26.         }

  27.         public double Left
  28.         {
  29.             set
  30.             {
  31.                 rectangle.SetValue(Canvas.LeftProperty, value);
  32.             }
  33.         }

  34.         public Color? Color
  35.         {
  36.             set
  37.             {
  38.                 if (value == null)
  39.                 {
  40.                     rectangle.Visibility = Visibility.Collapsed;
  41.                 }
  42.                 else
  43.                 {
  44.                     gradientStop.Color = (Color)value;
  45.                     rectangle.Visibility = Visibility.Visible;
  46.                 }
  47.             }
  48.             get
  49.             {
  50.                 if (rectangle.Visibility == Visibility.Collapsed)
  51.                     return null;
  52.                 else
  53.                     return gradientStop.Color;
  54.             }
  55.         }
  56.     }
  57. }
复制代码
2、经典俄罗斯方块一共7种形状,把每种形状所需要的功能抽象出来写一个抽象类,需要每个形状去重写的方法为形状的初始化、旋转和颜色的初始化设置

PieceBase.cs
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;

  11. namespace YYTetris.Piece
  12. {
  13.     public abstract class PieceBase
  14.     {
  15.         public PieceBase()
  16.         {
  17.             InitPiece();
  18.         }

  19.         // 形状的矩阵
  20.         public int[,] Matrix { get; set; }

  21.         // 形状的索引
  22.         private int _index = 0;

  23.         // 形状的最大索引
  24.         public int MaxIndex { get; set; }

  25.         /**//// <summary>
  26.         /// 初始化形状,需要设置 Matrix 和 MaxIndex
  27.         /// </summary>
  28.         public abstract void InitPiece();

  29.         /**//// <summary>
  30.         /// 变形
  31.         /// </summary>
  32.         /// <returns>变形后的矩阵</returns>
  33.         public abstract int[,] GetRotate();

  34.         /**//// <summary>
  35.         /// 形状的颜色
  36.         /// </summary>
  37.         public abstract Color Color { get; }

  38.         /**//// <summary>
  39.         /// 获取下一个形状的索引。如果超过最大索引则返回最初索引
  40.         /// </summary>
  41.         /// <returns></returns>
  42.         public int GetNextIndex()
  43.         {
  44.             int nextIndex = _index >= MaxIndex ? 0 : _index + 1;

  45.             return nextIndex;
  46.         }

  47.         /**//// <summary>
  48.         /// 变形。设置 Matrix 为变形后的矩阵
  49.         /// </summary>
  50.         public void Rotate()
  51.         {
  52.             Matrix = GetRotate();

  53.             _index = GetNextIndex();
  54.         }
  55.     }
  56. }
复制代码
3、继承PieceBase类,实现7种形状的各自的逻辑,以“L”为例。每种形状均为一个4×4矩阵,1代表有“块”,0代表空

L.cs
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;

  11. namespace YYTetris.Piece
  12. {
  13.     public class L : PieceBase
  14.     {
  15.         public override void InitPiece()
  16.         {
  17.             Matrix = new int[,]
  18.             {
  19.                 {0,1,0,0},
  20.                 {0,1,0,0},
  21.                 {0,1,1,0},
  22.                 {0,0,0,0}
  23.             };

  24.             MaxIndex = 3;
  25.         }

  26.         public override int[,] GetRotate()
  27.         {
  28.             switch (GetNextIndex())
  29.             {
  30.                 case 0:
  31.                     return new int[,]
  32.                     {
  33.                         {0,1,0,0},
  34.                         {0,1,0,0},
  35.                         {0,1,1,0},
  36.                         {0,0,0,0}
  37.                     };
  38.                 case 1:
  39.                     return new int[,]
  40.                     {
  41.                         {0,0,0,0},
  42.                         {1,1,1,0},
  43.                         {1,0,0,0},
  44.                         {0,0,0,0}
  45.                     };
  46.                 case 2:
  47.                     return new int[,]
  48.                     {
  49.                         {1,1,0,0},
  50.                         {0,1,0,0},
  51.                         {0,1,0,0},
  52.                         {0,0,0,0}
  53.                     };
  54.                 case 3:
  55.                     return new int[,]
  56.                     {
  57.                         {0,0,1,0},
  58.                         {1,1,1,0},
  59.                         {0,0,0,0},
  60.                         {0,0,0,0}
  61.                     };
  62.                 default:
  63.                     return Matrix;
  64.             }
  65.         }

  66.         public override Color Color
  67.         {
  68.             get { return Helper.GetColor("#339933"); }
  69.         }
  70.     }
  71. }
复制代码
4、核心控制类,用于控制形状的生成,上/下/左/右/变形,消行,积分等

UIControl.cs
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;

  11. using YYTetris.Piece;
  12. using System.Windows.Threading;
  13. using System.Collections.Generic;
  14. using System.ComponentModel;

  15. namespace YYTetris
  16. {
  17.     public class UIControl : INotifyPropertyChanged
  18.     {
  19.         /**//// <summary>
  20.         /// 俄罗斯方块容器
  21.         /// </summary>
  22.         public Block[,] Container { get; set; }

  23.         /**//// <summary>
  24.         /// 下一个形状的容器(4×4)
  25.         /// </summary>
  26.         public Block[,] NextContainer { get; set; }

  27.         /**//// <summary>
  28.         /// 游戏状态(Ready, Play, Pause, Over)
  29.         /// </summary>
  30.         public GameStatus GameStatus { get; set; }

  31.         private int _rows = 20; // 行数(Y 方向)
  32.         private int _columns = 10; // 列数(X 方向)
  33.         private int _positionX = 3; // 形状所属的 4×4 容器的 X 坐标
  34.         private int _positionY = 0; // 形状所属的 4×4 容器的 Y 坐标

  35.         private List<PieceBase> _pieces; // 形状集合

  36.         private PieceBase _currentPiece; // 当前形状
  37.         private PieceBase _nextPiece; // 下一个形状

  38.         private int _initSpeed = 400; // 初始速率(毫秒)
  39.         private int _levelSpeed = 50; // 每增加一个级别所需增加的速率(毫秒)

  40.         private DispatcherTimer _timer;

  41.         /**//// <summary>
  42.         /// 构造函数
  43.         /// </summary>
  44.         public UIControl()
  45.         {
  46.             // 初始化形状集合,共七种形状
  47.             _pieces = new List<PieceBase>() { new I(), new L(), new L2(), new N(), new N2(), new O(), new T() };

  48.             // 初始化方块容器(用 Block 对象填满整个容器)
  49.             Container = new Block[_rows, _columns];
  50.             for (int i = 0; i < _rows; i++)
  51.             {
  52.                 for (int j = 0; j < _columns; j++)
  53.                 {
  54.                     var block = new Block();
  55.                     block.Top = i * block.rectangle.ActualHeight;
  56.                     block.Left = j * block.rectangle.ActualWidth;
  57.                     block.Color = null;

  58.                     Container[i, j] = block;
  59.                 }
  60.             }

  61.             // 初始化下一个形状的容器(用 Block 对象将其填满)
  62.             NextContainer = new Block[4, 4];
  63.             for (int i = 0; i < 4; i++)
  64.             {
  65.                 for (int j = 0; j < 4; j++)
  66.                 {
  67.                     var block = new Block();
  68.                     block.Top = i * block.rectangle.ActualHeight;
  69.                     block.Left = j * block.rectangle.ActualWidth;
  70.                     block.Color = null;

  71.                     NextContainer[i, j] = block;
  72.                 }
  73.             }

  74.             // 创建一个新的形状
  75.             CreatePiece();
  76.             // 呈现当前创建出的形状
  77.             AddPiece(0, 0);

  78.             // Timer 用于定时向下移动形状
  79.             _timer = new DispatcherTimer();
  80.             _timer.Interval = TimeSpan.FromMilliseconds(_initSpeed);
  81.             _timer.Tick += new EventHandler(_timer_Tick);

  82.             GameStatus = GameStatus.Ready;
  83.         }

  84.         /**//// <summary>
  85.         /// 开始游戏(启动计时器)
  86.         /// </summary>
  87.         public void Play()
  88.         {
  89.             GameStatus = GameStatus.Play;
  90.             _timer.Start();
  91.         }

  92.         /**//// <summary>
  93.         /// 暂停游戏(停止计时器)
  94.         /// </summary>
  95.         public void Pause()
  96.         {
  97.             GameStatus = GameStatus.Pause;
  98.             _timer.Stop();
  99.         }

  100.         /**//// <summary>
  101.         /// 创建一个新的形状
  102.         /// </summary>
  103.         private void CreatePiece()
  104.         {
  105.             // 逻辑移到 下坠后 的逻辑内
  106.             for (int x = 0; x < _columns; x++)
  107.             {
  108.                 if (Container[0, x].Color != null)
  109.                 {
  110.                     OnGameOver(null);
  111.                     break;
  112.                 }
  113.             }

  114.             // 计算 当前形状 和 下一个形状
  115.             Random random = new Random();
  116.             _currentPiece = _nextPiece == null ? _pieces[random.Next(0, 7)] : _nextPiece;
  117.             _nextPiece = _pieces[random.Next(0, 7)];

  118.             // 形状所属的 4×4 容器的 X 坐标和 Y 坐标
  119.             _positionX = 3;
  120.             _positionY = 0;

  121.             // 设置“下一个形状的容器”的 UI
  122.             SetNextContainerUI();
  123.         }

  124.         private void _timer_Tick(object sender, EventArgs e)
  125.         {
  126.             MoveToDown();
  127.         }

  128.         /**//// <summary>
  129.         /// 向左移动
  130.         /// </summary>
  131.         public void MoveToLeft()
  132.         {
  133.             if (GameStatus != GameStatus.Play) return;

  134.             if (!IsBoundary(_currentPiece.Matrix, -1, 0))
  135.             {
  136.                 RemovePiece();
  137.                 AddPiece(-1, 0);
  138.             }
  139.         }

  140.         /**//// <summary>
  141.         /// 向右移动
  142.         /// </summary>
  143.         public void MoveToRight()
  144.         {
  145.             if (GameStatus != GameStatus.Play) return;

  146.             if (!IsBoundary(_currentPiece.Matrix, 1, 0))
  147.             {
  148.                 RemovePiece();
  149.                 AddPiece(1, 0);
  150.             }
  151.         }

  152.         /**//// <summary>
  153.         /// 向下移动
  154.         /// </summary>
  155.         public void MoveToDown()
  156.         {
  157.             if (GameStatus != GameStatus.Play) return;

  158.             if (!IsBoundary(_currentPiece.Matrix, 0, 1))
  159.             {
  160.                 RemovePiece();
  161.                 AddPiece(0, 1);
  162.             }
  163.             else
  164.             {
  165.                 // 如果触及底边了,则消除可消的行并且创建新的形状
  166.                 RemoveRow();
  167.                 CreatePiece();

  168.                 // 每落下一个形状加 1 分
  169.                 Score++;
  170.             }
  171.         }

  172.         /**//// <summary>
  173.         /// 变形
  174.         /// </summary>
  175.         public void Rotate()
  176.         {
  177.             if (GameStatus != GameStatus.Play) return;

  178.             if (!IsBoundary(_currentPiece.GetRotate(), 0, 0))
  179.             {
  180.                 RemovePiece();
  181.                 _currentPiece.Rotate();
  182.                 AddPiece(0, 0);
  183.             }
  184.         }

  185.         /**//// <summary>
  186.         /// 清除俄罗斯方块容器
  187.         /// </summary>
  188.         public void Clear()
  189.         {
  190.             for (int x = 0; x < _columns; x++)
  191.             {
  192.                 for (int y = 0; y < _rows; y++)
  193.                 {
  194.                     Container[y, x].Color = null;
  195.                 }
  196.             }
  197.         }

  198.         /**//// <summary>
  199.         /// 边界判断(是否超过边界)
  200.         /// </summary>
  201.         /// <param name="matrix">当前操作的形状的4×4矩阵</param>
  202.         /// <param name="offsetX">矩阵 X 方向的偏移量</param>
  203.         /// <param name="offsetY">矩阵 Y 方向的偏移量</param>
  204.         /// <returns></returns>
  205.         private bool IsBoundary(int[,] matrix, int offsetX, int offsetY)
  206.         {
  207.             RemovePiece();

  208.             for (int i = 0; i < 4; i++)
  209.             {
  210.                 for (int j = 0; j < 4; j++)
  211.                 {
  212.                     if (matrix[i, j] == 1)
  213.                     {
  214.                         if (j + _positionX + offsetX > _columns - 1 // 超过列的右边界
  215.                             || i + _positionY + offsetY > _rows - 1 // 超过行的下边界
  216.                             || j + _positionX + offsetX < 0 // 超过列的左边界
  217.                             || Container[i + _positionY + offsetY, j + _positionX + offsetX].Color != null) // matrix 所需偏移的地方已经有 Block 占着了
  218.                         {
  219.                             AddPiece(0, 0);
  220.                             return true;
  221.                         }                     
  222.                     }
  223.                 }
  224.             }

  225.             AddPiece(0, 0);
  226.             return false;
  227.         }

  228.         /**//// <summary>
  229.         /// 设置“下一个形状的容器”的 UI
  230.         /// </summary>
  231.         private void SetNextContainerUI()
  232.         {
  233.             // 清空
  234.             foreach (Block block in NextContainer)
  235.             {
  236.                 block.Color = null;
  237.             }

  238.             // 根据 _nextPiece 的矩阵设置相对应的 Block 对象的呈现
  239.             for (int x = 0; x < 4; x++)
  240.             {
  241.                 for (int y = 0; y < 4; y++)
  242.                 {
  243.                     if (_nextPiece.Matrix[x, y] == 1)
  244.                     {
  245.                         NextContainer[x, y].Color = _nextPiece.Color;
  246.                     }
  247.                 }
  248.             }
  249.         }

  250.         /**//// <summary>
  251.         /// 移除 _currentPiece 在界面上的呈现
  252.         /// </summary>
  253.         private void RemovePiece()
  254.         {
  255.             for (int i = 0; i < 4; i++)
  256.             {
  257.                 for (int j = 0; j < 4; j++)
  258.                 {
  259.                     if (_currentPiece.Matrix[i, j] == 1)
  260.                     {
  261.                         Container[i + _positionY, j + _positionX].Color = null;
  262.                     }
  263.                 }
  264.             }
  265.         }

  266.         /**//// <summary>
  267.         /// 增加 _currentPiece 在界面上的呈现
  268.         /// </summary>
  269.         /// <param name="offsetX">X 方向上的偏移量</param>
  270.         /// <param name="offsetY">Y 方向上的偏移量</param>
  271.         private void AddPiece(int offsetX, int offsetY)
  272.         {
  273.             for (int i = 0; i < 4; i++)
  274.             {
  275.                 for (int j = 0; j < 4; j++)
  276.                 {
  277.                     if (_currentPiece.Matrix[i, j] == 1)
  278.                     {
  279.                         Container[i + _positionY + offsetY, j + _positionX + offsetX].Color = _currentPiece.Color;
  280.                     }
  281.                 }
  282.             }

  283.             _positionX += offsetX;
  284.             _positionY += offsetY;
  285.         }

  286.         /**//// <summary>
  287.         /// 根据游戏规则,如果某行出现连续的直线则将其删除,该线以上的部分依次向下移动
  288.         /// </summary>
  289.         private void RemoveRow()
  290.         {
  291.             // 删除的行数
  292.             int removeRowCount = 0;

  293.             // 行的遍历(Y 方向)
  294.             for (int y = 0; y < _rows; y++)
  295.             {
  296.                 // 该行是否是一条连续的直线
  297.                 bool isLine = true;

  298.                 // 列的遍历(X 方向)
  299.                 for (int x = 0; x < _columns; x++)
  300.                 {
  301.                     if (Container[y, x].Color == null)
  302.                     {
  303.                         // 出现断行,则继续遍历下一行
  304.                         isLine = false;
  305.                         break;
  306.                     }
  307.                 }

  308.                 // 该行是一条连续的直线则将其删除,并将该行以上的部分依次向下移动
  309.                 if (isLine)
  310.                 {
  311.                     removeRowCount++;

  312.                     // 删除该行
  313.                     for (int x = 0; x < _columns; x++)
  314.                     {
  315.                         Container[y, x].Color = null;
  316.                     }

  317.                     // 将被删除行的以上行依次向下移动
  318.                     for (int i = y; i > 0; i--)
  319.                     {
  320.                         for (int x = 0; x < _columns; x++)
  321.                         {
  322.                             Container[i, x].Color = Container[i - 1, x].Color;
  323.                         }
  324.                     }
  325.                 }
  326.             }

  327.             // 加分,计算方法: 2 的 removeRowCount 次幂 乘以 10
  328.             if (removeRowCount > 0)
  329.                 Score += 10 * (int)Math.Pow(2, removeRowCount);               

  330.             // 更新总的已消行数
  331.             RemoveRowCount += removeRowCount;

  332.             // 根据已消行数计算级别,依据丁学的建议,计算方法: 已消行数/5 的平方根 取整
  333.             Level = (int)Math.Sqrt(RemoveRowCount / 5);

  334.             // 根据级别计算速率,计算方法: 初始速率 减 (每多一个级别所需增加的速率 乘以 当前级别)
  335.             _timer.Interval = TimeSpan.FromMilliseconds(_initSpeed - _levelSpeed * Level > _levelSpeed ? _initSpeed - _levelSpeed * Level : _levelSpeed);
  336.         }

  337.         private int _score = 0;
  338.         /**//// <summary>
  339.         /// 得分
  340.         /// </summary>
  341.         public int Score
  342.         {
  343.             get { return _score; }
  344.             set
  345.             {
  346.                 _score = value;
  347.                 if (PropertyChanged != null)
  348.                 {
  349.                     PropertyChanged(this, new PropertyChangedEventArgs("Score"));
  350.                 }
  351.             }
  352.         }

  353.         private int _removeRowCount = 0;
  354.         /**//// <summary>
  355.         /// 总共被消除的行数
  356.         /// </summary>
  357.         public int RemoveRowCount
  358.         {
  359.             get { return _removeRowCount; }
  360.             set
  361.             {
  362.                 _removeRowCount = value;
  363.                 if (PropertyChanged != null)
  364.                 {
  365.                     PropertyChanged(this, new PropertyChangedEventArgs("RemoveRowCount"));
  366.                 }
  367.             }
  368.         }

  369.         private int _level = 0;
  370.         /**//// <summary>
  371.         /// 级别(游戏难度)
  372.         /// </summary>
  373.         public int Level
  374.         {
  375.             get { return _level; }
  376.             set
  377.             {
  378.                 _level = value;
  379.                 if (PropertyChanged != null)
  380.                 {
  381.                     PropertyChanged(this, new PropertyChangedEventArgs("Level"));
  382.                 }
  383.             }
  384.         }

  385.         public event PropertyChangedEventHandler PropertyChanged;

  386.         /**//// <summary>
  387.         /// 游戏结束的事件委托
  388.         /// </summary>
  389.         public event EventHandler GameOver;

  390.         /**//// <summary>
  391.         /// 游戏结束事件所调用的方法
  392.         /// </summary>
  393.         /// <param name="e"></param>
  394.         private void OnGameOver(EventArgs e)
  395.         {
  396.             GameStatus = GameStatus.Over;
  397.             _timer.Interval = TimeSpan.FromMilliseconds(_initSpeed);
  398.             _timer.Stop();

  399.             EventHandler handler = GameOver;
  400.             if (handler != null)
  401.                 handler(this, e);
  402.         }
  403.     }
  404. }
复制代码
5、通过对UIControl对象的使用完成俄罗斯方块的开发

Page.xaml
  1. <UserControl x:Class="YYTetris.Page"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     x:Name="uc" KeyDown="uc_KeyDown">
  5.     <Canvas x:Name="LayoutRoot" Width="640" Height="480" Background="Gray">
  6.         <HyperlinkButton Content="作者:webabcd" NavigateUri="http://webabcd.cnblogs.com" TargetName="_blank" />
  7.         <Canvas Canvas.Top="30" Canvas.Left="160">
  8.             <Border BorderBrush="AliceBlue" BorderThickness="3" CornerRadius="6" Padding="6">
  9.                 <Border BorderBrush="AliceBlue" BorderThickness="1" CornerRadius="1">
  10.                     <Canvas x:Name="canvasBox" Background="Black" Width="200" Height="400" />
  11.                 </Border>
  12.             </Border>
  13.             <Border BorderBrush="AliceBlue" BorderThickness="1" CornerRadius="1" Canvas.Top="0" Canvas.Left="240" >
  14.                 <Canvas x:Name="canvasBoxPrev" Width="80" Height="80" />
  15.             </Border>
  16.             <StackPanel Canvas.Top="100" Canvas.Left="240">
  17.                 <TextBlock Text="级别" Width="80" TextAlignment="Center" Margin="0 1" />
  18.                 <TextBlock Text="{Binding Level}"  Width="80" TextAlignment="Center" Margin="0 1" Foreground="Firebrick" />
  19.                 <TextBlock Text="行数" Width="80" TextAlignment="Center" Margin="0 1" />
  20.                 <TextBlock Text="{Binding RemoveRowCount}"  Width="80" TextAlignment="Center" Margin="0 1" Foreground="Firebrick" />
  21.                 <TextBlock Text="得分" Width="80" TextAlignment="Center" Margin="0 1" />
  22.                 <TextBlock Text="{Binding Score}"  Width="80" TextAlignment="Center" Margin="0 1" Foreground="Firebrick" />
  23.                 <Button x:Name="play" Content="开始游戏" Margin="0 20"  Click="start_Click" />
  24.                 <TextBlock x:Name="gameOver" Text="Game Over" Width="80" TextAlignment="Center" Margin="0 1" Foreground="Firebrick" Visibility="Collapsed" />
  25.             </StackPanel>
  26.         </Canvas>

  27.     </Canvas>
  28. </UserControl>
复制代码
Page.xaml.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Documents;
  8. using System.Windows.Input;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Animation;
  11. using System.Windows.Shapes;

  12. using YYTetris.Piece;
  13. using System.Windows.Threading;

  14. namespace YYTetris
  15. {
  16.     public partial class Page : UserControl
  17.     {
  18.         UIControl _control;

  19.         public Page()
  20.         {
  21.             InitializeComponent();

  22.             this.Loaded += new RoutedEventHandler(Page_Loaded);
  23.         }

  24.         void Page_Loaded(object sender, RoutedEventArgs e)
  25.         {
  26.             uc.Focus();

  27.             _control = new UIControl();
  28.             _control.GameOver += new EventHandler(_control_GameOver);
  29.             uc.DataContext = _control;

  30.             foreach (Block block in _control.Container)
  31.             {
  32.                 canvasBox.Children.Add(block);
  33.             }

  34.             foreach (Block block in _control.NextContainer)
  35.             {
  36.                 canvasBoxPrev.Children.Add(block);
  37.             }
  38.         }

  39.         void _control_GameOver(object sender, EventArgs e)
  40.         {
  41.             gameOver.Visibility = Visibility.Visible;
  42.             play.Content = "开始游戏";
  43.         }

  44.         private void uc_KeyDown(object sender, KeyEventArgs e)
  45.         {
  46.             if (_control.GameStatus != GameStatus.Play) return;

  47.             if (e.Key == Key.Left)
  48.             {
  49.                 _control.MoveToLeft();
  50.             }
  51.             else if (e.Key == Key.Right)
  52.             {
  53.                 _control.MoveToRight();
  54.             }
  55.             else if (e.Key == Key.Up)
  56.             {
  57.                 _control.Rotate();
  58.             }
  59.             else if (e.Key == Key.Down)
  60.             {
  61.                 _control.MoveToDown();
  62.             }
  63.         }

  64.         private void start_Click(object sender, RoutedEventArgs e)
  65.         {
  66.             if (play.Content.ToString() == "开始游戏")
  67.             {
  68.                 if (_control.GameStatus == GameStatus.Over)
  69.                 {
  70.                     _control.Clear();
  71.                     gameOver.Visibility = Visibility.Collapsed;
  72.                     _control.Score = 0;
  73.                     _control.Level = 0;
  74.                     _control.RemoveRowCount = 0;
  75.                 }

  76.                 _control.Play();
  77.                 play.Content = "暂停游戏";
  78.             }
  79.             else
  80.             {
  81.                 _control.Pause();
  82.                 play.Content = "开始游戏";
  83.             }
  84.         }
  85.     }
  86. }
复制代码
源码下载:
附件: 亲,您没有权限下载或查看附件喔:-) 试试登录注册吧!
TOP

回复: 游戏人生Silverlight(1) - 七彩俄罗斯方块[Silverlight 2.0]

学习一下!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP