俄罗斯方块,作为手机、游戏机上最经久不衰的游戏之一,陪伴我们走过少年时代。现在我们使用appinventor来自己开发一款自己的俄罗斯方块。


aia文件可以从这里获取


组件设计界面:

tetrix15.png


组件设计界面很简单(很简陋):

屏幕 窗口大小设为固定,水平对齐设为居中

6个按钮:开始游戏、左移、右移、逆时针转、顺时针转、下落

1个画布:宽度设为240,高度设为480

1个计时器,1个对话框




设计思路:


我们将画布分为20行、10列的格子,俄罗斯方块就是在这200个格子内移动、旋转。

给每个格子编号(从0开始),如图:

tetrix164.png


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

tetrix218.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。


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

tetrix921.png



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


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


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

tetrix1027.png



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

tetrix1148.png


画出小方块:


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


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


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


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

tetrix1271.png



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


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


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


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


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


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


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


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


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


举例来说,对于L型。

tetrix1566.png


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


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


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


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

tetrix1684.png


这时,他占据的四个位置相对于31的位移变成了:-1,0,1,-11


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

tetrix1739.png


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


再次旋转90度

tetrix1803.png



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


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


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

tetrix1880.png


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


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

tetrix1945.png



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


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


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


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

tetrix2068.png


tetrix2197.png



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


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

tetrix2199.png



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


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



每次点开始,都在画布上方画出不同种类不同造型的组合了。


这样,左移、右移、顺转、逆转就简单了:


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


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


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


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

tetrix2353.png

tetrix2355.png



tetrix2417.png



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


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


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

tetrix2448.png



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


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

tetrix2528.png



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

tetrix2568.png



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


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


修改移动和旋转事件:

tetrix2685.png


tetrix2687.png

tetrix2689.pngtetrix2691.png



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

tetrix2716.png


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

tetrix2792.png



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


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


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

tetrix2854.png


添加后还要显示出来:


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


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

tetrix2936.png



修改计时器事件:


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

tetrix2967.png


修改”重绘画布”过程:

tetrix2982.png


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


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

tetrix3036.png


tetrix3039.png




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


这是因为我们把初始的组合中心设为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.png


tetrix3465.png

tetrix3468.png

tetrix3471.png



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

tetrix3526.png



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

tetrix3560.png


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

tetrix3583.png


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

tetrix3599.png



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


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


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


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

tetrix3738.png


tetrix3741.png


tetrix3743.png


tetrix3746.png


tetrix3749.png



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


标签: 画布, 游戏

添加新评论