俄罗斯方块数据模型

关于方块和棋盘

方块类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1.
口口 
 口口

 口口
口口
2.




3.


口口

 口
 口
口口
4.
口口
口口
5.
 口
口口口


开始尝试使用一个4*4的二维数组分别标识行列,1表示方块。

1
2
3
4
5
6
7
8
9
[
[0,0,0,0],
[0,0,0,0],
[0,1,1,0],
[0,1,1,0],
]
表示
口口
口口

游戏棋盘同理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
]

后发现当数据需要合并时操作起来非常复杂,而且不好确定子方块的偏移。

尝试第二种方案。使用坐标表示方块,并且将[0,0]坐标设置为方块的旋转锚点,这种方式的数据很好合并到棋盘数据中(主要是好计算,好获取子方块偏移)。

1
2
3
4
5
6
7
8
9
[
[-1,1],
[0,1],
[0,0],
[1,0]
]
表示
口口
口口

这样方块移动前做判定也方便多了,
比如当前方块

1
2
3
4
5
6
[
[-1,1],
[0,1],
[0,0],
[1,0]
]

要下落。当前方块位置为[0,5]。计算过程为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function downable() {
let stageData = this.Stage.stageData;
let can = true;
this.data.forEach(d => {
//子方块偏移
let deltX = d[0];
let deltY = d[1];
let l = this.xy.y - deltY + 1; //+1 判断下一行
let c = this.xy.x + deltX + 1; //+1 墙壁
//不可
if (stageData[l] && (stageData[l][c])) {
cc.log(this.xy.y + deltY + '行' + this.xy.x + deltX + '列为1 不可下落');
can = false;
}
})
return can;
}

左右移动同理
当下落判定为否且执行了下落,则下落失败,当前方块生命周期结束,数据合并至棋盘

合并

1
2
3
4
5
6
7
8
9
let xy = tetris.xy;
let data = tetris.data;
data.forEach(d=>{
let deltX = d[0];
let deltY = d[1];
let x = xy.x+1+deltX;
let y = xy.y - deltY;
this.stageData[y]&&(this.stageData[y][x] = 1);
})

关于转换

1
2
cosθ*x-sinθ*y = x'
sinθ*x+cosθ*y = y'

关于消除

合并 更新棋盘时根据棋盘数据绘制棋盘,切将上一次合并的方块移除场景。
判定行满 消除 整体下移

源码(CocosCreator)
https://gitee.com/yutou527/tetris