cocos creator 3.8 俄罗斯方块Demo 10

news2024/11/29 6:19:12

这里的表格是横行数列,也就是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
    @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抽时间上传一下,在家休息的日子也快要过去了 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2249559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java安全—原生反序列化重写方法链条分析触发类

前言 在Java安全中反序列化是一个非常重要点&#xff0c;有原生态的反序列化&#xff0c;还有一些特定漏洞情况下的。今天主要讲一下原生态的反序列化&#xff0c;这部分内容对于没Java基础的来说可能有点难&#xff0c;包括我。 序列化与反序列化 序列化&#xff1a;将内存…

【Java 学习】面向程序的三大特性:封装、继承、多态

引言 1. 封装1.1 什么是封装呢&#xff1f;1.2 访问限定符1.3 使用封装 2. 继承2.1 为什么要有继承&#xff1f;2.2 继承的概念2.3 继承的语法2.4 访问父类成员2.4.1 子类中访问父类成员的变量2.4.2 访问父类的成员方法 2.5 super关键字2.6 子类的构造方法 3. 多态3.1 多态的概…

LeetCode—74. 搜索二维矩阵(中等)

仅供个人学习使用 题目描述&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true…

uniapp关闭sourceMap的生成,提高编译、生产打包速度

警告信息&#xff1a;[警告⚠] packageF\components\mpvue-echarts\echarts.min.js 文件体积超过 500KB&#xff0c;已跳过压缩以及 ES6 转 ES5 的处理&#xff0c;手机端使用过大的js库影响性能。 遇到问题&#xff1a;由于微信小程序引入了mpvue-echarts\echarts.min.js&…

房屋出租出售预约系统支持微信小程序+H5+APP

核心功能有&#xff1a;新盘销售、房屋租赁、地图找房、小区找房&#xff0c;地铁找房等方式。 地图找房&#xff1a;通过地图标注查看附近房源&#xff0c;方便用户根据地理位置查找合适的房产。二手房资讯&#xff1a;提供租房及二手房市场的相关资讯&#xff0c;帮助用户了…

Axure农业农村数据可视化大屏模板分享

在当今信息技术飞速发展的时代&#xff0c;数据可视化已成为各行各业提升管理效率、优化决策过程的重要手段。Axure作为一款强大的原型设计工具&#xff0c;凭借其高度的自定义能力和丰富的交互设计功能&#xff0c;在农业农村数据可视化领域展现出强大的潜力。本文将详细介绍A…

【分享】PPT打开密码的设置与移除方法

设置和取消PPT的打开密码&#xff0c;是保障和移除文件访问权限的重要操作。以下将分别讲解如何为PPT设置密码&#xff0c;以及如何取消打开密码。 一、如何设置PPT打开密码 方法1&#xff1a; 1、在PowerPoint中打开目标文件&#xff0c;然后点击左上角的“文件”选项。在弹…

网络基础 - 地址篇

一、IP 地址 IP 协议有两个版本&#xff0c;IPv4 和 IPv6IP 地址(IPv4 地址)是一个 4 字节&#xff0c;32 位的正整数&#xff0c;通常使用 “点分十进制” 的字符串进行表示&#xff0c;例如 192.168.0.1&#xff0c;用点分割的每一个数字表示一个字节&#xff0c;范围是 0 ~…

在 Ubuntu 上部署 MediaWiki 开源维基平台

MediaWiki 是一个功能强大的开源维基软件&#xff0c;全球众多组织使用它来创建协作文档网站。本文将指导你如何在 Ubuntu 服务器上安装 MediaWiki&#xff0c;使用 Nginx 作为 Web 服务器&#xff0c;PostgreSQL 作为数据库管理系统。 简介 MediaWiki 是一个灵活且强大的维基…

Spring Boot整合EasyExcel

文章目录 EasyExcel简介Spring Boot整合EasyExcel一、单sheet写操作二、多sheet写数据三、读操作 EasyExcel简介 1、EasyExcel 是一个基于 Java 的简单、省内存的读写 Excel 的开源项目。在尽可能节约内存的情况下支持读写百 M 的 Excel&#xff08;没有一次性将数据读取到内存…

Java 基础面试题

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

deepin 安装 chrome 浏览器

deepin 安装 chrome 浏览器 最近好多小伙伴儿和我说 deepin 无法安装最新的谷歌浏览器 其实是因为最新的 谷歌浏览器 其中的一个依赖需要提前安装 提前安装依赖然后再安装谷歌浏览器就可以了 安装 fonts-liberationsudo apt -y install fonts-liberation安装 chrome 浏览器sudo…

数据结构2:顺序表

目录 1.线性表 2.顺序表 2.1概念及结构 2.2接口实现 1.线性表 线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串 线性表在逻辑上是线性结构&#xff0c;也就说…

Java 反射(Reflection)

Java 反射&#xff08;Reflection&#xff09; Java 反射&#xff08;Reflection&#xff09;是一个强大的特性&#xff0c;它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力&#xff0c;这在很多框架和库中被广泛使用&#…

利用Python爬虫阿里巴巴中国站获得跨境属性的详细指南

在全球化贸易的背景下&#xff0c;跨境电商成为了连接全球买家和卖家的重要桥梁。阿里巴巴中国站作为全球知名的B2B电子商务平台&#xff0c;提供了海量的商品信息&#xff0c;其中跨境属性信息对于跨境电商尤为重要。本文将详细介绍如何使用Python编写爬虫&#xff0c;从阿里巴…

【JavaEE】Spring Web MVC

目录 一、Spring Web MVC简介1.1 MVC简介1.2 Spring MVC1.3 RequestMapping注解1.3.1 使用1.3.2 RequestMapping的请求设置1.3.2.1 方法11.3.2.2 方法2 二、Postman介绍2.1 创建请求2.2 界面如下&#xff1a;2.3 传参介绍 一、Spring Web MVC简介 官方文档介绍&#xff1a; Sp…

实现 Browser 客户端下载 XML 文件功能

后端 使用 io.BytesIO 方法 创建一个字节缓冲区在不需要磁盘文件的情况下进行文件操作打包为 zip 压缩包&#xff08;上图代码&#xff09;in_memory_zip.seek(0) 数据写入ZIP后文件指针会停留在缓冲区的末尾将文件指针重置回开头make_response() 方法用于创建HTTP响应的函数.g…

【SPIE出版|四大高校联合举办】先进算法与图像处理技术国际学术会议(IC-AAIP 2025)

&#x1f4da;IC-AAIP 2025【ISSN:0277786X】 2025年先进算法与图像处理技术国际学术会议 ⏰时间&#xff1a;2025年8月9日至10日 &#x1f440;地点&#xff1a;中国沈阳 &#x1f4dd;出版商&#xff1a;SPIE 组委负责人刘老师&#xff1a;13660240104 2025年先…

设备内存指纹修改

一、前端通过获取Navigator.deviceMemory来查询系统内存。 二、Navigator.deviceMemory 1、navigator_device_memory.idl接口定义&#xff1a; // https://github.com/w3c/device-memory#the-web-exposed-apiinterface mixin NavigatorDeviceMemory {[HighEntropyDirect,Meas…

市面上好用的AIPPT-API接口

文多多 AiPPT | 一键搞定PPT 文多多 AiPPT | 一键搞定PPT文多多AiPPT&#xff0c;一键搞定PPT。AI根据主题、文档、网址智能生成PPT文档&#xff0c;同时支持在线编辑、美化、排版、导出、一键动效、自动生成演讲稿等功能&#xff0c;告别工作烦恼&#xff01;https://docmee.…