cocos creator 3.8 俄罗斯方块Demo 10

ops/2024/11/30 5:23:57/

这里的表格是横行数列,也就是x是行,y是列,不要当x/y轴看。

1-1012-1012
-1-1[-1,0]
0[0,-1][0,0][0,1][0,2]0[0,0]
11[1,0]
22[2,0]
-1012-1012
-1-1[-1,0]
0[0,-1][0,0][0,1][0,2]0[0,0]
11[1,0]
22[2,0]
2-1012-1012
-1[-1,-1][-1,0]-1[-1,-1][-1,0]
0[0,-1][0,0]0[0,-1][0,0]
11
22
-1012-1012
-1[-1,-1][-1,0]-1[-1,-1][-1,0]
0[0,-1][0,0]0[0,-1][0,0]
11
22
3-1012-1012
-1[-1,0]-1[-1,0]
0[0,-1][0,0][0,1]0[0,0][0,1]
11[1,0]
22
-1012-1012
-1-1[-1,0]
0[0,-1][0,0][0,1]0[0,-1][0,0]
1[1,0]1[1,0]
22
4-1012-1012
-1[-1,0]-1
0[0,0]0[0,-1][0,0][0,1]
1[1,0][1,1]1[1,-1]
22
-1012-1012
-1[-1,-1][-1,0]-1[-1,1]
0[0,0]0[0,-1][0,0][0,1]
1[1,0]1
22
5-1012-1012
-1[-1,0]-1[-1,-1]
0[0,0]0[0,-1][0,0][0,1]
1[1,-1][1,0]1
22
-1012-1012
-1[-1,0][-1,1]-1
0[0,0]0[0,-1][0,0][0,1]
1[1,0]1[1,1]
22
6-1012-1012
-1[-1,-1][-1,0]-1[-1,0]
0[0,0][0,1]0[0,-1][0,0]
11[1,-1]
22
-1012-1012
-1[-1,-1][-1,0]-1[-1,0]
0[0,0][0,1]0[0,-1][0,0]
11[1,-1]
22
7-1012-1012
-1[-1,0][-1,1]-1[-1,-1]
0[0,-1][0,0]0[0,-1][0,0]
11[1,0]
22
-1012-1012
-1[-1,0][-1,1]-1[-1,-1]
0[0,-1][0,0]0[0,-1][0,0]
11[1,0]
22

然后根据这个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@propertygridNode: Node[][] = [];//一个记录网点数据@propertygridData: 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新特性,用于快速填充数组默认值0this.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抽时间上传一下,在家休息的日子也快要过去了 


http://www.ppmy.cn/ops/137837.html

相关文章

银联大数据面试题及参考答案

说说 Hadoop 的基本组件 Hadoop 主要由以下几个基本组件构成: HDFS(Hadoop Distributed File System):它是一个分布式文件系统,能将文件切分成多个数据块,并存储在不同的节点上。具有高容错性,可在低成本的硬件上搭建,适合存储海量数据 。例如,互联网公司存储用户的行…

Linux环境变量(添加环境变量、修改系统环境变量、内建命令和非内建命令)

Linux环境变量&#xff08;添加环境变量、修改系统环境变量、内建命令和非内建命令&#xff09; 1. 环境变量的介绍 环境变量&#xff08;environment variables&#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数。环境变量是在操作系统中一个具有特定名字…

28.UE5实现对话系统

目录 1.对话结构的设计&#xff08;重点&#xff09; 2.NPC对话接口的实现 2.1创建类型为pawn的蓝图 2.2创建对话接口 3.对话组件的创建 4.对话的UI设计 4.1UI_对话内容 4.2UI_对话选项 4.3UI_对话选项框 5.对话组件的逻辑实现 通过组件蓝图&#xff0c;也就是下图中的…

node.js.抓取代理ip(提供参考)

我们示范来使用node.js结合axios库&#xff08;用于发起HTTP请求&#xff09;来抓取某代理IP网站上的代理IP列表的示例代码&#xff08;示例仅供参考&#xff0c;实际中不同网站结构不同需相应调整解析逻辑&#xff09;&#xff0c;这里只是简单示意抓取过程&#xff0c;真实使…

扫雷-完整源码(C语言实现)

云边有个稻草人-CSDN博客 在学完C语言函数之后&#xff0c;我们就有能力去实现简易版扫雷游戏了&#xff08;成就感满满&#xff09;&#xff0c;下面是扫雷游戏的源码&#xff0c;快试一试效果如何吧&#xff01; 在test.c里面进行扫雷游戏的测试&#xff0c;game.h和game.c…

Redis开发03:常见的Redis命令

1.输入以下命令&#xff0c;启动redis。 sudo service redis-server start 如果你是直接安装在WSL的&#xff0c;搜索栏搜索Ubuntu或者点击左下角Windows图表找到U那一栏&#xff0c;直接打开Ubentu&#xff0c;输入账密后&#xff0c;输入“sudo service redis-server start”…

【MySQL】MySQL中的函数之JSON_ARRAY_APPEND

在 MySQL 8.0 及更高版本中&#xff0c;JSON_ARRAY_APPEND() 函数用于在 JSON 数组的指定位置追加一个或多个值。这个函数非常有用&#xff0c;特别是在你需要在 JSON 数组的末尾或特定位置添加新的元素时。 基本语法 JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ..…

Java高级教程:数据结构、集合框架、ArrayList与LinkedList深度解析

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Java &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 标题 Java高级教程&#xff1a;数据结构、集合框架、ArrayList与LinkedList深度解析 摘要 Java作为一种…