Silverlight:手把手教你写俄罗斯方块(二)
protected Point[] point; protected Color c;
point用来存储小方块坐标,c存储方块颜色。然后定义3个属性:
/// <summary> /// 方块颜色 /// </summary> public Color color { get { return c; } } /// <summary> /// 中心点横坐标 /// </summary> public int posX { get; set; } /// <summary> /// 中心点纵坐标 /// </summary> public int posY { get; set; }
中心点横坐标和中心点纵坐标是指这个方块在画板中的坐标,而point存储的是在方块内部定义的坐标,以“L”方块为例,我们这样设置:
point[0].X = -1; point[0].Y = 0; point[1].X = -1; point[1].Y = -1; point[2].X = 0; point[2].Y = 0; point[3].X = 1; point[3].Y = 0;
您不妨在纸上画个坐标系,然后画出这4个点的位置,看是否够成了“L”这个形状。中心点横坐标和中心点纵坐标可以看成是原点(0,0)在画板中的坐标,这样一旦确定了posX和posY,我们就可以通过posX + this.point[index].X和 posY - this.point[index].Y来获取其他点在画板中的坐标了。于是我们再写一个索引器用来取得小方块的坐标:
/// <summary> /// 小方块的坐标 /// </summary> /// <param name="index">俄罗斯方块内部小方块索引</param> /// <returns></returns> public Point this[int index] { get { return new Point(posX + this.point[index].X, posY - this.point[index].Y); } }
构造函数,当方块出现在画板之前,我们要先确定它在画板中的位置,所以需要对这posX和posY属性赋值。
/// <summary> /// 俄罗斯方块中心点在画板上的坐标 /// </summary> /// <param name="x">横坐标</param> /// <param name="y">纵坐标</param> public Block(int x, int y) { point = new Point[4]; this.posX = x; this.posY = y; }
方块还需要变形,我们还是以“L”方块为例,我们规定它的变形是在同样的坐标系中沿着原点(0,0)做顺时针旋转,这样一来它的每个小方块的坐标会发生什么变化呢?您可以用笔在纸上画一下,看看是不是旧坐标的Y轴变成了新坐标的X轴,旧坐标的X轴变成了新坐标的负Y轴,变形方法如下:
public virtual void Change() { for (int z = 0; z < 4; z++) { double oldX = point[z].X; double oldY = point[z].Y; point[z].X = oldY; point[z].Y = -oldX; } }
这里使用的是虚方法,因为我们并不想所有的方块都以这种方式变形,一些特殊的方块我们希望能够重载,比如“正方形”方块并不需要旋转。但是还有一点需要注意,方块在某些情况是不能变形的,比如变形后超出了边界,或者变形后的新坐标上已经存在方块(即被其它方块挡住),所以在变形前我们需要先要取得方块变形后的坐标,然后判断方块能否变形。代码如下:
public virtual Point[] GetChangedPoint() { Point[] newPoint = new Point[4]; for (int z = 0; z < 4; z++) { double oldX = point[z].X; double oldY = point[z].Y; double newX = oldY; double newY = -oldX; newPoint[z] = new Point(posX + newX, posY - newY); } return newPoint; }
同样采用虚方法。最后还需要2个方法用来控制方块在画板上的显示和消失:
public void Show(Rect[,] board) { for (int i = 0; i < 4; i++) { int x = (int)this[i].X; int y = (int)this[i].Y; board[x, y].Color = this.color; } } public void Hidden(Rect[,] board) { for (int i = 0; i < 4; i++) { int x = (int)this[i].X; int y = (int)this[i].Y; board[x, y].Color = null; } }
这里的参数board就是我们用Rect填充的画板,通过索引器遍历每个小方块,取得它们在画板上的坐标,然后给相应的Rect绘制方块的颜色,前面说过,当我们赋值为null的时候,相应的Rect就隐藏了,方块也就消失了,我们就是通过方块的消失和显示,来实现方块的移动和变形效果。
俄罗斯方块的基类到此就构建完毕了,下一节中,我将介绍构建具体形状的俄罗斯方块,敬请关注。