1、WPF游戏 菜鸟版俄罗斯方块 时间:2010-09-20 05:42来源:博客园 作者:lipan 点击: 822次 在以前的MFC、winform中实现一个游戏程序是一件相当困难的事情,自从WPF诞生后,富客户端设计工作变得相对简单。本人刚学WPF不久,写写劣质代码望大侠莫见笑。自于这个游戏本身的实现方式我并未去研究,这里只是根据自己的理解来做。 代码下载: 主要思想: 一、提供一个容器 在以前的MFC、winform中实现一个游戏程序是一件相当困难的事情,自从WPF诞生后,富客户端设计工作变得相对简单。本人刚学WPF不久,写写劣质代码望大侠莫见笑。自于这个游戏本身的实现
2、方式我并未去研究,这里只是根据自己的理解来做。 代码下载: 主要思想: 一、提供一个容器类(Container),用来作为方块活动的网格状区域。由于WPF自带Grid控件支持网格,因此就直接利用了。 1.Container类需要关联到Grid,活动区域;和waitingGrid等候区域(下一个出现的方块) 2.在Container类中实现消层的逻辑 二、提供一个方块基类(Box),7中方块全部从其派生。 1.每个方块包含4个Rectangle(小方格) 2.通过一个工厂类随机产生某个方块的实例 3.基类实现方块移动、变形、等逻辑、子类定义方
3、块颜色、初始化方式,确定每个方格相对坐标。 4.在方块下降到底部触发OnBottom事件,Container接受此事件触发消行逻辑。Container类中OnGameover事件被界面层接受处理。 运行效果: 代码部分: Box方块基类 abstract class Box { public Box() { for (int i = 0; i < 4; i++) { rectangles.Add(new Rec
4、tangle()); rectangles[i].Width = 24.0; rectangles[i].Height = 24.0; } dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal); dispatcherTimer.Tick += new EventHandler(Timer_Tick); dispatcherTimer.Interv
5、al = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50);
}
protected Grid grid;
///
6、rTimer;
///
7、Children) { if (r is Rectangle) { if (this.rectangles.Contains(r as Rectangle)) return false; if (Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty)) == x && Convert.ToInt32((r as Rectangle).GetValu
8、e(Grid.RowProperty)) == y)
{
return true;
}
}
}
return false;
}
///
9、 { foreach (var r in rectangles) { int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty)); int y = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)); if (Existence(x, y)) return true;
10、 }
return false;
}
///
11、}
///
12、 dispatcherTimer.Stop(); OnBottom(this, null); } } public abstract void Ready(); public abstract void ShowWating(ref Grid WaingGrid); protected bool Move(int _x, int _y) { if (IsPause) return false;
13、 for (int i = 0; i < 4; i++) { int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x; int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y; if (Existence(x, y)) return false;
14、 if (!InGrid(x, y)) return false; } for (int i = 0; i < 4; i++) { rectangles[i].SetValue(Grid.ColumnProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x); rectangles[i].SetValue(Grid.RowProperty, Conver
15、t.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y); } return true; } public bool MoveUp() { return Move(0, -1); } public bool MoveDown() { return Move(0, 1); } pub
16、lic bool MoveLeft()
{
return Move(-1, 0);
}
public bool MoveRight()
{
return Move(1, 0);
}
///
17、return false; bool mark = false; int j = 0; while (!mark) { j++; for (int i = 0; i < 4; i++) { int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty));
18、 int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j; if (Existence(x, y) || !InGrid(x, y)) { j--; mark = true; } } }
19、 for (int i = 0; i < 4; i++)
{
rectangles[i].SetValue(Grid.RowProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j);
}
//OnBottom(this, null);
return mark;
}
///
20、否处于暂停状态 /// private bool IsPause = false; public void Pause() { dispatcherTimer.IsEnabled = false; IsPause = true; } public void UnPause() { dispatcherTimer.IsEnabled = true;
21、 IsPause = false;
}
public void StopAction()
{
dispatcherTimer.Stop();
}
/// 22、ry>
public bool ChangeShape()
{
if (IsPause) return false;
IList 23、ivityStatus.NextRelativeposition[0].x;
P[0].y = Convert.ToInt32(rectangles[0].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[0].y;
if (ActivityStatus.NeedCheck[0]) if (Existence(P[0].x, P[0].y) || !InGrid(P[0].x, P[0].y)) return false;
P[1] 24、x = Convert.ToInt32(rectangles[1].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[1].x;
P[1].y = Convert.ToInt32(rectangles[1].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[1].y;
if (ActivityStatus.NeedCheck[1]) if (Existence(P[1].x 25、 P[1].y) || !InGrid(P[1].x, P[1].y)) return false;
P[2].x = Convert.ToInt32(rectangles[2].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[2].x;
P[2].y = Convert.ToInt32(rectangles[2].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[2 26、].y;
if (ActivityStatus.NeedCheck[2]) if (Existence(P[2].x, P[2].y) || !InGrid(P[2].x, P[2].y)) return false;
P[3].x = Convert.ToInt32(rectangles[3].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[3].x;
P[3].y = Convert.ToInt32(rectangles 27、[3].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[3].y;
if (ActivityStatus.NeedCheck[3]) if (Existence(P[3].x, P[3].y) || !InGrid(P[3].x, P[3].y)) return false;
for (int i = 0; i < 4; i++)
{
rectangles[i].SetValue(Grid.Col 28、umnProperty, P[i].x);
rectangles[i].SetValue(Grid.RowProperty, P[i].y);
}
ActivityStatus = ActivityStatus.Next;
return true;
}
}
“Z”形方块子类
class Box_Z : Box
{
public Box_Z(ref Grid grid)
{
29、 this.grid = grid;
for (int i = 0; i < 4; i++) rectangles[i].Fill = new SolidColorBrush(Colors.DarkOrange);
}
private void ShowAt(Position P, ref Grid grid)
{
rectangles[0].SetValue(Grid.ColumnProperty, P.x + 0);
rectangles[0].S 30、etValue(Grid.RowProperty, P.y + 0);
rectangles[1].SetValue(Grid.ColumnProperty, P.x + 1);
rectangles[1].SetValue(Grid.RowProperty, P.y + 0);
rectangles[2].SetValue(Grid.ColumnProperty, P.x + 1);
rectangles[2].SetValue(Grid.RowProperty, P.y + 1) 31、
rectangles[3].SetValue(Grid.ColumnProperty, P.x + 2);
rectangles[3].SetValue(Grid.RowProperty, P.y + 1);
for (int i = 0; i < 4; i++) grid.Children.Add(rectangles[i]);
}
public override void ShowWating(ref Grid WaingGrid)
{
32、 ShowAt(new Position(1, 1), ref WaingGrid);
}
public override void Ready()
{
ShowAt(new Position(4, 0), ref grid);
ActivityStatus = new Status();
ActivityStatus.NextRelativeposition.Add(new Position(1, 2));
33、 ActivityStatus.NextRelativeposition.Add(new Position(0, 1));
ActivityStatus.NextRelativeposition.Add(new Position(1, 0));
ActivityStatus.NextRelativeposition.Add(new Position(0, -1));
ActivityStatus.NeedCheck.Add(true);
ActivityStatus.NeedCheck.Ad 34、d(false);
ActivityStatus.NeedCheck.Add(false);
ActivityStatus.NeedCheck.Add(true);
ActivityStatus.Next = new Status();
ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, -2));
ActivityStatus.Next.NextRelativeposition.Add(n 35、ew Position(0, -1));
ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, 0));
ActivityStatus.Next.NextRelativeposition.Add(new Position(0, 1));
ActivityStatus.Next.NeedCheck.Add(true);
ActivityStatus.Next.NeedCheck.Add(true);
36、 ActivityStatus.Next.NeedCheck.Add(false);
ActivityStatus.Next.NeedCheck.Add(false);
ActivityStatus.Next.Next = ActivityStatus;
}
}
由于每种方块的变形方式都不一样,Z型有4种状态,I型有2中状态,而O型只有一种状态,现在需要描述方块形状状态,需要定义循环链表数据类型。
定义一个坐标点,描述位置和相对位置
/// 37、/ 定义一个方格坐标点
///
38、
///
39、每个方格]到这个位置的可行性
///
public List
40、 ///
41、 case 0: return new Box_S(ref grid); case 1: return new Box_Z(ref grid); case 2: return new Box_J(ref grid); case 3: return new Box_L(ref grid); case 4: return new Box_I(ref grid); case 5: return new Box_O(r
42、ef grid); case 6: return new Box_T(ref grid); default: return null; } } } 到此为止,方块定义好了,也可以随机产生了,怎么让展示在Grid中? 1.方块子类ShowAt函数标示展示到指定Grid; 2.ShowWating表示展示在等候区域。 当方块展示到容器Grid中时,怎么自动下降呢?这里用到DispatcherTimer。 dispatcherTim
43、er = new DispatcherTimer(DispatcherPriority.Normal);
dispatcherTimer.Tick += new EventHandler(Timer_Tick);
dispatcherTimer.Interval = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50);
///
44、 public void AtuoDown() { dispatcherTimer.Start(); } private void Timer_Tick(object sender, EventArgs e) { if (!MoveDown()) { dispatcherTimer.Stop(); OnBottom(this, null);
45、 }
}
当方块到达底部时,事件通知容器类执行消层函数:
在Box中:
///
46、 dispatcherTimer.Stop();
OnBottom(this, null);
}
}
在Container中:
ActivityBox.OnBottom += ActivityBox_OnBottom;
///
47、er, EventArgs e)
{
Result.GetInstance().CalculateScore(RemoveLine());
NewBoxReadyToDown();
}
RemoveLine消层函数
///
48、 new Exception("缺少活动区域,必须为容器指定grid值。"); int[] lineCount = new int[24]; for (int i = 0; i < 24; i++) lineCount[i] = 0; int RemoveLineCount = 0; //计算每一行方块总数 foreach (var r in grid.Children) { if (r is
49、Rectangle) { int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)); lineCount[x]++; } } for (int i = 23; i >= 0; i--) { if (lineCount[i] >= 12) { //移除一行小方格 for (int j = 0; j < grid.Children.Count; j++)// (var r in mygrid.Children) { if (grid.Children[j] is Recta






