这里的表格是横行数列,也就是x是行,y是列,不要当x/y轴看。
1 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
|
|
|
-1 |
|
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
[0,2] |
0 |
|
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
[2,0] |
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
|
|
|
-1 |
|
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
[0,2] |
0 |
|
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
[2,0] |
|
|
2 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
[-1,-1] |
[-1,0] |
|
|
-1 |
[-1,-1] |
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
[-1,-1] |
[-1,0] |
|
|
-1 |
[-1,-1] |
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
3 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
|
|
-1 |
|
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
0 |
|
[0,0] |
[0,1] |
|
1 |
|
|
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
|
|
|
-1 |
|
[-1,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
[1,0] |
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
|
|
|
4 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
|
|
-1 |
|
|
|
|
0 |
|
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
1 |
|
[1,0] |
[1,1] |
|
1 |
[1,-1] |
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
[-1,-1] |
[-1,0] |
|
|
-1 |
|
|
[-1,1] |
|
0 |
|
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
1 |
|
[1,0] |
|
|
1 |
|
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
5 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
|
|
-1 |
[-1,-1] |
|
|
|
0 |
|
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
1 |
[1,-1] |
[1,0] |
|
|
1 |
|
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
[-1,1] |
|
-1 |
|
|
|
|
0 |
|
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
[0,1] |
|
1 |
|
[1,0] |
|
|
1 |
|
|
[1,1] |
|
2 |
|
|
|
|
2 |
|
|
|
|
6 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
[-1,-1] |
[-1,0] |
|
|
-1 |
|
[-1,0] |
|
|
0 |
|
[0,0] |
[0,1] |
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
[1,-1] |
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
[-1,-1] |
[-1,0] |
|
|
-1 |
|
[-1,0] |
|
|
0 |
|
[0,0] |
[0,1] |
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
[1,-1] |
|
|
|
2 |
|
|
|
|
2 |
|
|
|
|
7 |
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
[-1,1] |
|
-1 |
[-1,-1] |
|
|
|
0 |
[0,-1] |
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
|
|
|
|
-1 |
0 |
1 |
2 |
|
-1 |
0 |
1 |
2 |
-1 |
|
[-1,0] |
[-1,1] |
|
-1 |
[-1,-1] |
|
|
|
0 |
[0,-1] |
[0,0] |
|
|
0 |
[0,-1] |
[0,0] |
|
|
1 |
|
|
|
|
1 |
|
[1,0] |
|
|
2 |
|
|
|
|
2 |
|
|
|
|
然后根据这个xslx制作成数据然后
import { v2 } from "cc";
export const GridConfig = {
//素材限制 行
row: 12,
//列
column: 9,
//方块宽高
blockWidth: 60,
blockHeight: 60,
//I型
shape1: [
[v2(0, -1), v2(0, 0), v2(0, 1), v2(0, 2)],
[v2(-1, 0), v2(0, 0), v2(1, 0), v2(2, 0)],
[v2(0, -1), v2(0, 0), v2(0, 1), v2(0, 2)],
[v2(-1, 0), v2(0, 0), v2(1, 0), v2(2, 0)]
],
//O型
shape2: [
[v2(-1, -1), v2(-1, 0), v2(0, -1), v2(0, 0)],
[v2(-1, -1), v2(-1, 0), v2(0, -1), v2(0, 0)],
[v2(-1, -1), v2(-1, 0), v2(0, -1), v2(0, 0)],
[v2(-1, -1), v2(-1, 0), v2(0, -1), v2(0, 0)]
],
//T型
shape3: [
[v2(-1, 0), v2(0, -1), v2(0, 0), v2(0, 1)],
[v2(-1, 0), v2(0, 0), v2(0, 1), v2(1, 0)],
[v2(0, -1), v2(0, 0), v2(0, 1), v2(1, 0)],
[v2(-1, 0), v2(0, -1), v2(0, 0), v2(1, 0)]
],
//L型
shape4: [
[v2(-1, 0), v2(0, 0), v2(1, 0), v2(1, 1)],
[v2(0, -1), v2(0, 0), v2(0, 1), v2(1, -1)],
[v2(-1, -1), v2(-1, 0), v2(0, 0), v2(1, 0)],
[v2(-1, 1), v2(0, -1), v2(0, 0), v2(0, 1)]
],
//倒L型
shape5: [
[v2(-1, 0), v2(0, 0), v2(1, -1), v2(1, 0)],
[v2(-1, -1), v2(0, -1), v2(0, 0), v2(0, 1)],
[v2(-1, 0), v2(-1, 1), v2(0, 0), v2(1, 0)],
[v2(0, -1), v2(0, 0), v2(0, 1), v2(1, 1)]
],
//Z型
shape6: [
[v2(-1, -1), v2(-1, 0), v2(0, 0), v2(0, 1)],
[v2(-1, 0), v2(0, -1), v2(0, 0), v2(1, -1)],
[v2(-1, -1), v2(-1, 0), v2(0, 0), v2(0, 1)],
[v2(-1, 0), v2(0, -1), v2(0, 0), v2(1, -1)]
],
//倒Z型
shape7: [
[v2(-1, 0), v2(-1, 1), v2(0, -1), v2(0, 0)],
[v2(-1, -1), v2(0, -1), v2(0, 0), v2(1, 0)],
[v2(-1, 0), v2(-1, 1), v2(0, -1), v2(0, 0)],
[v2(-1, -1), v2(0, -1), v2(0, 0), v2(1, 0)]
],
}
然后是初始化这些东西
//两个二维数组 一个记录node
@property
gridNode: Node[][] = [];
//一个记录网点数据
@property
gridData: number[][] = [];
//540*720 一个作为放置的容器
@property(Node)
gridMap: Node = null;
//一个存放图片资源的数组,7张
@property([SpriteFrame])
blockSpriteFrame: SpriteFrame[] = [];
//数据模型 id指向生成的类型 starPos指向[0,0]的位置 angleIndex指向是这个类型的第几个,就是旋转后的形状
shapeData: any = {
id: 0,
starPos: v2(0, 0),
angleIndex: 0
}
//方块的预制体,加上Sprite、UITransform组件
@property({ type: Prefab, displayName: "方块预制体" })
blockPrefab: Prefab = null;
//开关 是否开始游戏
isStart: boolean = false;
初始化的一些操做
//初始化容器中的节点
this.initGridNodes();
//绑定上网点数据,给个0
this.initGridData();
//随机生成一个形状
this.createRadomShape();
this.isStart = true;
//初始化节点 铺满整个容器 不定时的计算位移并渲染形状
initGridNodes() {
//防止重新被渲染
// if (this.gridNode.length) return;
const mapWidth = this.gridMap.getComponent(UITransform).contentSize.width;
const mapHeight = this.gridMap.getComponent(UITransform).contentSize.height;
for (let row = 0; row < GridConfig.row; row++) {
//二维数组 第一位不初始化就使用会报错的
this.gridNode[row] = [];
for (let column = 0; column < GridConfig.column; column++) {
const blockNode: Node = instantiate(this.blockPrefab);
//从容器节点的左上角开始计算
const x: number = -mapWidth / 2 + GridConfig.blockWidth / 2 + GridConfig.blockWidth * column;
const y: number = mapHeight / 2 - GridConfig.blockHeight / 2 - GridConfig.blockHeight * row;
blockNode.setPosition(v3(x, y, 0));
blockNode.setParent(this.gridMap);
this.gridNode[row][column] = blockNode;
}
}
}
//绑定数据
initGridData() {
//ES6新特性,用于快速填充数组默认值0
this.gridData = new Array(GridConfig.row).fill(0).map(() => new Array(GridConfig.column).fill(0));
}
//随机创建形状
createRadomShape() {
this.shapeData.id = math.randomRangeInt(1, 8);
this.shapeData.angleIndex = math.randomRangeInt(0, 4);
const randomColum = math.randomRangeInt(3, 7);
//中心点位置 在这里x指向行,y指向列
// console.log(this.shapeData);//2-3
//特殊判断 [1,0] [1,2] [3,2] [4,1] [5,3]
if ((this.shapeData.id === 1 && this.shapeData.angleIndex == 0) ||
(this.shapeData.id === 1 && this.shapeData.angleIndex == 2) ||
(this.shapeData.id === 3 && this.shapeData.angleIndex == 2) ||
(this.shapeData.id === 4 && this.shapeData.angleIndex == 1) ||
(this.shapeData.id === 5 && this.shapeData.angleIndex == 3)) {
//初始生成形状[0,0]的位置
this.shapeData.starPos = v2(0, randomColum);
} else {
//初始生成形状[0,0]的位置
this.shapeData.starPos = v2(1, randomColum);
}
//检查有没有超出边界
if (this.checkShape()) {
//渲染形状
this.renderShape();
} else {
console.log("==========结束游戏了======");
this.isStart = false;
// this.restartGame();
// this.start();
}
}
//检查边界
checkShape(): boolean {
const shapeConfig = GridConfig[`shape${this.shapeData.id}`][this.shapeData.angleIndex];
for (let i = 0; i < shapeConfig.length; i++) {
const row = this.shapeData.starPos.x + shapeConfig[i].x;
const column = this.shapeData.starPos.y + shapeConfig[i].y;
if (row < 0 || row >= GridConfig.row) {
return false;
}
if (column < 0 || column >= GridConfig.column) {
return false;
}
if (this.gridData[row][column] !== 0) {
return false;
}
}
return true;
}
//确定生成的形状
renderShape() {
//生成哪一个形状
const shapeConfig = GridConfig[`shape${this.shapeData.id}`][this.shapeData.angleIndex]
//遍历
shapeConfig.forEach(async (blockPos: any) => {
const row = this.shapeData.starPos.x + blockPos.x;
const column = this.shapeData.starPos.y + blockPos.y;
this.gridData[row][column] = this.shapeData.id;
//挂上图片
this.gridNode[row][column].getComponent(Sprite).spriteFrame = this.blockSpriteFrame[this.shapeData.id - 1];
});
}
下落的逻辑,可以用计时器,也可在update中
autoDropTime: number = 0;
autoDropTimeDela: number = 1;
//插值运行
update(deltaTime: number) {
if (this.isStart) {
this.autoDropTime += deltaTime;
if (this.autoDropTime >= this.autoDropTimeDela) {
this.autoDropShape();
this.autoDropTime = 0;
}
}
}
autoDropShape() {
//啥也没有就返回
if (this.shapeData.id == 0) return;
//清空上一个形状
this.clearShape();
//位移向下
this.shapeData.starPos.x += 1;
//没有挨边的或者可以自由下落的
if (this.checkShape()) {
//重新渲染形状
this.renderShape();
} else {
//有挨边的或者不能再次下落的,返回上一个坐标
this.shapeData.starPos.x -= 1;
//重新渲染形状
this.renderShape();
//检查是否能够消除
this.checkRows();
//完事后创建下一个形状
this.createRadomShape();
}
}
clearShape就是清空图片,数据置0
clearShape() {
const shapeConfig = GridConfig[`shape${this.shapeData.id}`][this.shapeData.angleIndex];
//遍历
shapeConfig.forEach(async (blockPos: any) => {
const row = this.shapeData.starPos.x + blockPos.x;
const column = this.shapeData.starPos.y + blockPos.y;
this.gridData[row][column] = [0][0];
this.gridNode[row][column].getComponent(Sprite).spriteFrame = null;
});
}
由下向上过滤一遍容器,有满足的替换成它上面一个的位置,重新渲染
//由下向上检查是否有满格
checkRows() {
let lastRow: number = GridConfig.row - 1;
let needRender: boolean = false;
while (lastRow >= 0) {
let isFull: boolean = true;
for (let column = 0; column < GridConfig.column; column++) {
//从左到右有空的
if (this.gridData[lastRow][column] === 0) {
isFull = false;
break;
}
}
if (isFull) {
needRender = true;
for (let i = lastRow; i > 0; i--) {
for (let j = 0; j < GridConfig.column; j++) {
this.gridData[i][j] = this.gridData[i - 1][j];
}
}
} else {
lastRow--;
}
}
if (needRender) {
this.renderGrid();
// this.renderShape();
}
}
图片也改了它
renderGrid() {
for (let row = 0; row < GridConfig.row; row++) {
for (let column = 0; column < GridConfig.column; column++) {
this.gridNode[row][column].getComponent(Sprite).spriteFrame = this.blockSpriteFrame[this.gridData[row][column] - 1];
}
}
}
旋转按钮
onBtnChange() {
this.clearShape();
//0~3 3最大下面0 剩下的++或--
this.shapeData.angleIndex = this.shapeData.angleIndex === 3 ? 0 : this.shapeData.angleIndex + 1;
if (this.checkShape()) {
this.renderShape();
} else {
this.shapeData.angleIndex = this.shapeData.angleIndex === 0 ? 3 : this.shapeData.angleIndex - 1;
this.renderShape();
}
}
其它三个按钮,传位置v2(0, -1) v2(0, 1) 向下吗v2(2, 0)/v2(3, 0)
changeShapePos(pos: Vec2) {
this.clearShape();
this.shapeData.starPos.x += pos.x;
this.shapeData.starPos.y += pos.y;
if (this.checkShape()) {
this.renderShape();
} else {
this.shapeData.starPos.x -= pos.x;
this.shapeData.starPos.y -= pos.y;
this.renderShape();
}
}
重新开始 我这里直接调用的start方法,有点不妥
onBtnRestartGame() {
//清空容器下的所用节点
for (let i = this.gridMap.children.length - 1; i > 0; i--) {
const element = this.gridMap.children[i];
element.destroy();
}
this.start();
}
暂定 恢复 就不说了 就是改this.isStart 游戏截图,这样写也有个很大的问题,如果用骨骼或者龙骨动画制作,动画切换会有问题,循环中加setTimeout或者Promise有点问题。
demo抽时间上传一下,在家休息的日子也快要过去了