使用画布,设计俄罗斯方块。

ENGLISH VERSION HERE

组件设计界面:

2023-05-24T01:25:55.png

组件设计界面很简单(很简陋):
6个按钮:开始游戏、左移、右移、逆时针转、顺时针转、下落
1个画布:宽度设为240,高度设为480
1个计时器,1个对话框

设计思路:

我们将画布分为20行、10列的格子,俄罗斯方块就是在这200个格子内移动、旋转。
给每个格子编号(从0开始),如图:
2023-05-24T01:26:08.png

图中的白色部分就是我们的画布,外面包围的灰色一圈,就代表画布的边框,俄罗斯方块不能移动到这些边框上。

2023-05-24T01:26:26.png

所有的棋盘游戏,都是背后的数据支撑。

我们初始化一个棋盘数据变量,记录每个小格子上的颜色。

棋盘数据初始化时是这样的:

9,9,9,9,9,9,9,9,9,9,9,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,0,0,0,0,0,0,0,0,0,0,9,

9,9,9,9,9,9,9,9,9,9,9,9

这些数字应该是在一行上的,这里分为22行12列,是为了便于观察。

在画布的边框格子,我们都填上9。中间画布的位置都填上0。

以后如果这个位置被某个组合占据,就把这个位置标记为组合的编号。

2023-05-24T01:26:40.png

给出每个方块的位置,我们可以求出他所在的行或者列。注意,这个行和列是从0开始的。

比如0号位置,就是0行0列。13号位置就是1行1列。250号位置就是20行10列。

相对于可见的画布来说,正好符合我们的习惯。

2023-05-24T01:26:51.png

初始化一个颜色列表变量,分别代表7种不同的组合的颜色,

2023-05-24T01:26:59.png

画出小方块:

每个俄罗斯方块的不同组合都是由4个小方块拼成。若需要画出组合,先需要画出小的方块。

每个小方块都有不同的编号,只要给定一个编号,我们就可以在这个位置画出小方块。

我们在设计界面把画布设为240宽480高,这样每个格子就是24宽24高。

首先根据方块的位置编号,求出他所在的行和列。把线段的长度和宽度都设为22,这样每两个格子之间有个空隙。

2023-05-24T01:27:09.png

好了,现在我们就可以连接手机伴侣,测试下我们的画方块过程了。

是不是正好画在画布的左上角?把13改成250,是不是正好画在右下角?

如果不是,说明你的画方块过程有错误,请仔细改正。

现在我们已经可以在任意位置画出小方块了,如何才能画出一个组合(4个方块)呢?

我们只要知道组合所占据的4个方块的编号就可以了。

俄罗斯方块共有7种不同的类型:分别是L型,J型,Z型,S型,T型,田字型,一字型。我们把他们称为7种组合。

每个组合可以旋转,每旋转90度是一个造型,共有4个造型(有的造型有重复)。这样,旋转组合就是切换不同的造型了

每个造型我们给他指定一个基点。这样,移动组合就是移动他的基点。

下面进入重点:造型的偏移表

举例来说,对于L型。

2023-05-24T01:27:56.png

如果我们把它放在19,31,43,44号位置上。

我们指定31是他的基点(也可以指定其他位置作为基点),这样四个位置减去基点31的差就是:-12,0,12,13。

我们把这个称为该造型的偏移表。

我们把它逆时针旋转90度,变为:

2023-05-24T01:28:17.png

这时,他占据的四个位置相对于31的位移变成了:-1,0,1,-11
2023-05-24T01:28:47.png
我们把它再次逆时针旋转90度,变为

2023-05-24T01:29:15.png

这时,他占据的四个位置相对于31的位移变成了:-13,-12,0,12 (四个格子的顺序是可以打乱的)。

再次旋转90度

2023-05-24T01:30:11.png

位移变成了-1,0,1,11

注意,这个偏移表只跟这个组合的种类和造型(旋转)有关,跟她的位置(基点)无关。

比如第一种造型我们把他向左平移2格到:

2023-05-24T01:30:20.png

这时,基点移动到29,他的四个格子的偏移表还是:-12,0,12,13。

使用这个方法,我们记下7种组合每个造型的偏移表:

2023-05-24T01:30:30.png

同一种组合的不同偏移表之间用\n 连接。

注意这里用的是"csv转列表"块,而不是"csv行转列表"块。

对于田字形和一字型,可能部分造型有重复。为了跟其他组合都是4种造型相匹配,我们就把他写4次。

现在就可以画出某种组合的某种造型了:

2023-05-24T01:30:39.png

tetrix2197

确定了组合编号和组合造型,我们就确定了组合的偏移表。

偏移表中的每个偏移数值分别加上组合中心,就知道了组合所占据的位置编号了,这样就可以画出这个组合。

tetrix2199

生成新组合,我们都把它显示在画布上部中间位置(17号)。

即组合中心设为17,随机生成编号和造型

每次点开始,都在画布上方画出不同种类不同造型的组合了。
2023-05-24T01:36:24.png
这样,左移、右移、顺转、逆转就简单了:

左移就是把组合中心向左移动一个,就是组合中心数值减1,

右移就是把组合中心向右移动一个,就是组合中心数值加1,

下移就是把组合中心向下移动一个,就是组合中心数值加12。

(记得先点开始,随机产生一个组合)

tetrix2353

tetrix2355

tetrix2417

逆时针转就是把造型加1,顺时针转就是把造型减1。

注意,组合造型只能在1-4之间切换。每次造型改变后必须更新偏移表。

有没有发现组合可能会移动或者旋转出了画布?如何避免呢?

tetrix2448

比如图中L型组合要往左移动,但是要前往的格子内保存的是9(非0值),这样就不能移动。

要前往的位置占据的格子只要有1个的值为非0,就不能移动(或者旋转)。

tetrix2528

之所以位置+1,是因为格子位置编号是从0开始,而列表取值索引是从1开始。

tetrix2568

为了要检测移动和旋转两种操作,需要传入两个参数。记住如果造型变了,就要更新新位置偏移表。

每次移动或者旋转前,先检测要去往或者旋转后占用的地方是不是可以到达的(都为空格)。只有可以到达才移动或者旋转。

修改移动和旋转事件:

tetrix2685

tetrix2687

tetrix2689

tetrix2691

怎么让组合自动下落呢?就必须请出计时器了。

tetrix2716

每次游戏开始,都让计时器开始计时。

tetrix2792

每次计时,判断可否向下移动(组合中心+12就是下移)。如果碰到底边或者其他组合,就重新在画布上部生成新组合。

如果你测试这个代码,就会发现触底的组合并没有留在那里,而是消失了。

因为我们没有把触底的组合保存到“棋盘数据”变量:

tetrix2854

添加后还要显示出来:

循环取出棋盘数据中的每个数(颜色,也是这格方块曾经被某个组合占据)。

如果这个数不是9(边框),也不是0(空白格),就在这个位置画方块。

tetrix2936

修改计时器事件:

生成新组合之前,保存数据到棋盘数据。

tetrix2967

修改”重绘画布”过程:

tetrix2982

现在我们的组合可以左右移动、顺转逆转、定时下落了。

那什么时候游戏结束呢?就在新生成的组合无法安放时:

tetrix3036

tetrix3039

有没有发现在生成新组合时经常莫名其妙就提示游戏结束了?

这是因为我们把初始的组合中心设为17,非常靠近上边缘,而有的组合造型就出了边界了。

为了解决这个问题,我们把棋盘数据的第一行,也就是上边缘数据由9,9,9,9,9,9,9,9,9,9,9,9共12个9,

改为9,0,0,0,0,0,0,0,0,0,0,9 也就是上边缘开放。因为我们没有上移的操作,不会影响程序其他部分运行。

下面是本游戏的另一个重点:

如何消除一行方块?

当棋盘数据某一行的所有位置都是非0值,这一行的方块就可以移除。

比如图示的倒数第二行,也就是画布的倒数第一行,分别是9,1,1,6,6,4,4,7,7,7,7,9,

这12个数没有0值,说明这一行可以消除,我们就把这一行从“棋盘数据”变量中删除。

重复检查第20行,第19行...到第1行,并统计一共删除的行数。最后在画布第一行插入12个数:

9,0,0,0,0,0,0,0,0,0,0,9,删除了几行,插入几行。

tetrix3462

tetrix3465

tetrix3468

tetrix3471

根据消除的行数计算得分:1行10分,2行30分,3行60分,4行100分。不可能同时消除5行及以上的。

tetrix3526

修改计时器计时事件,在生成新方块之前检测消除方块并计算得分:

tetrix3560

修改开始游戏事件,游戏开始时重新计分:

tetrix3583

最后一个,快速下落事件:

tetrix3599

重复检查可否下移一格(组合中心+12),若可以,再次下移一格,直到无法下移为止。

我们在回头看下“消除方块”这个过程:

实际上每次消除时不可能有20行都能消除,可以消除的行只可能在当前组合占据的行中产生。

我们只要找到当前组合占据的行,依次判断这几行可否消除就可以了。

tetrix3738

tetrix3741

tetrix3743

tetrix3746

tetrix3749
2023-05-24T01:36:24.png

2023-05-24T01:36:17.png

2023-05-24T01:36:09.png

2023-05-24T01:36:03.png

为什么在13位置插入呢?因为13位置就是棋盘数据第二行的第一个数字。

标签: 画布, 游戏

添加新评论