1.选择关卡:

利用点击事件的返回值event获取点击的坐标,用坐标转换为节点坐标来获取需要的坐标,通过点击坐标的所属象限选择四个象限的来进入对应关卡

    onTouchStart(event){//获取鼠标点击的位置if(this.lock){return ;}this.lock = true;// cc.log(event.getLocation());//获取的是世界坐标//获取点击的位置(基于世界坐标)let location = event.getLocation();//坐标系转换,转到节点坐标系里面来//this.你需要的节点.convertToNodeSpaceAR(你需要转换的坐标)//this.你需要的节点.convertToWorldSpaceAR(你需要转换的坐标)---将节点内坐标转到世界坐标上location = this.clover.convertToNodeSpaceAR(location);let res = this.getPos(location);let pos = res.pos;cc.vv.currentLevel = res.degree;//设置对应关卡等级//让星星移动cc.tween(this.star).parallel(cc.tween().to(0.2,{position:pos}),cc.tween().by(0.2,{angle:72})).call(()=>{//当前面动作都执行完毕以后才会调用这个回调函数,写法是箭头函数this.lock = false;}).start();},getPos(location){let res = {};let dis = this.clover.width / 4;//将移动的坐标规定出来if(location.x > 0 && location.y < 0){//第四象限res.pos = cc.v2(dis,-dis);res.degree = 4;}//第三象限else if(location.x < 0 && location.y < 0){res.pos = cc.v2(-dis,-dis);res.degree = 3;}//第二象限else if(location.x < 0 && location.y > 0){res.pos = cc.v2(-dis,dis);res.degree = 1;}else{   res.pos = cc.v2(dis,dis);res.degree = 2;}return res;},

2.游戏准备:

这里可以用layout来排布切分的图片块,也可以设置基准点来逐个设置拼图位置

    createCell() {//用盒子的大小除以行数或列数得到每个方块的大小let cellSize = this.answerSkin.node.width / this.line;let gap = (this.cellPar.width - this.answerSkin.node.width) / (this.line + 1);//保证放置方块的位置从左上角开始let basePos = {x: -this.cellPar.width / 2 + gap + cellSize / 2,y: this.cellPar.height / 2 - gap - cellSize / 2,};for (let i = 0; i < this.row; i++) {//行this.cellList[i] = [];//添加二维数组for (let j = 0; j < this.line; j++) {//列let cell = cc.instantiate(this.cellPrefab);//实例化预制体//调用预制体上的函数将参数传进去cell.getComponent("Cell").init(this.skin, [i, j], cellSize);//将预制体的宽高重新规定cell.width = cellSize;cell.height = cellSize;//设置预制体的位置cell.x = basePos.x + i * (gap + cellSize);cell.y = basePos.y - j * (gap + cellSize);this.cellPar.addChild(cell);this.cellList[i][j] = cell.getComponent("Cell");//方便调用各自脚本if (i === this.row - 1 && j === this.line - 1) {cell.opacity = 0;this.blackIndex = [i, j];}}}},

3.拼图移动:

首先打乱拼图,需要交换图片和数据层:

    //打乱拼图chaos() {//定义方向let dir = [[0, -1], [0, 1], [-1, 0], [1, 0]];//下上左右//打乱次数let count = 0;while (count < 100) {//随机一个方向let ran = Math.random() * dir.length | 0;//让下标随机变换--实际上是下标的变换方块并没有动let index = [this.blackIndex[0] + dir[ran][0], this.blackIndex[1] + dir[ran][1]];if (this.cross(index)) {//交换方块的条件满足之后才会进行交换//交换方块(传入的是黑块的下标和要去交换的下标)this.exchangeCell(this.blackIndex, index);//将黑块的坐标变为移动后的坐标this.blackIndex = index;count++;}}},//判断是否越界cross(index) {//行数不能超过定义的行数,并且行数要大于0,列数不能超过定义的列数,并且列数也要大于0return index[0] < this.row && index[0] >= 0 && index[1] < this.line && index[1] >= 0;},exchangeCell(blackIndex, index) {//黑块当前的位置(通过黑块在cellList里面的下标去拿到对应位置)let pos = this.cellList[blackIndex[0]][blackIndex[1]].node.getPosition();//getPosition可以拿到节点在父坐标系的位置//将黑块设置到要index所在的地方this.cellList[blackIndex[0]][blackIndex[1]].node.setPosition(this.cellList[index[0]][index[1]].node.getPosition());//将index所在的位置设置成原来黑块所在的位置this.cellList[index[0]][index[1]].node.setPosition(pos);//交换完图片交换cellList下标let obj = this.cellList[blackIndex[0]][blackIndex[1]];this.cellList[blackIndex[0]][blackIndex[1]] = this.cellList[index[0]][index[1]];this.cellList[index[0]][index[1]] = obj;},blackCellGoHome() {//当黑块不在最后一行的时候while (this.blackIndex[0] < this.row - 1) {//让黑块一直向下走直到最后一行为止this.exchangeCell(this.blackIndex, [this.blackIndex[0] + 1, this.blackIndex[1]]);this.blackIndex = [this.blackIndex[0] + 1, this.blackIndex[1]];}while (this.blackIndex[1] < this.line - 1) {//一直往右边走this.exchangeCell(this.blackIndex, [this.blackIndex[0], this.blackIndex[1] + 1]);this.blackIndex = [this.blackIndex[0], this.blackIndex[1] + 1];}},//判断点击的方块是不是和我想要的判断的方块相邻isNeighbor(index1, index2) {return (Math.abs(index1[0] - index2[0]) + Math.abs(index1[1] - index2[1]) === 1);},//开启点击事件后的逻辑onCellClicked(cell) {//这里的参数是为了知道点击的是哪个方块let audio = this.node.getComponent(cc.AudioSource);audio.play();//不需要名字因为只会播放组件上面有的//拿到当前点击方块的下标let currentIndex = this.getIndexByCell(cell);if (this.isNeighbor(this.blackIndex, currentIndex)) {this.exchangeCell(this.blackIndex, currentIndex);this.blackIndex = currentIndex;this.addStep();if (this.isGameWon()) {cc.vv.isGameOver = true;this.cellList[this.blackIndex[0]][this.blackIndex[1]].node.opacity = 255;this.showWonAnima();this.unschedule(this.addTime);}}else {//表示位置不相邻if (currentIndex != this.blackIndex) {cell.node.color = cc.color(255, 255, 255);cc.Tween.stopAllByTarget(cell.node);cc.tween(cell.node).to(0, { color: cc.color(255, 100, 100) }).delay(0.2).to(0, { color: cc.color(255, 255, 255) }).start();}}// let bool = this.isNeighbor(this.blackIndex,currentIndex);// cc.log(bool);},

因为通过点击获取的坐标比较难判断所在的方块,所以直接把点击事件放在生成的预制体里面,通过点击对应的预制体进行方块的交换

    onTouchStart(){cc.find("Canvas/gameLayer").getComponent("Game").onCellClicked(this);},

getPosition()可以拿到节点在父坐标系的位置

setPosition()可以设置位置

需要设置两个数组,一个存图片用来图片的交换一个存下标用来记录交换节点的下标相当于ID

获取下标(通过方块获取)遍历数组cellList里面的元素是否和这个cell===(相等)

只有需要移动的cell周遭有黑块才能移动交换(数据层也要跟着换)

拼图BFS思路:(还原)

1.创建一个State类来存状态(目标还原数组,父状态,当前坐标,移动方向,记录走过的路,黑块下标)

//越界判断
function checkCross(index) {return index[0] >= 0 && index[0] < global.row && index[1] >= 0 && index[1] < global.line;
};//在语法层面,引用数据类型的深拷贝
function arrClone(arr) {return JSON.parse(JSON.stringify(arr));
};class State {//包含的属性constructor(target, par, codeID, dir, recordList, blackIndex) {//目标  --->最终还原的数组this.target = target;//父状态this.par = par;//当前状态的唯一识别码,当前位置this.codeID = codeID//父状态到目前状态行走的方位this.dir = dir;//记录表---->记录走过的路   key:valuethis.recordList = recordList;//黑块下标this.blackIndex = blackIndex;};//以当前状态诞生子状态,获取所有可行的下一步  方法getChildren() {let children = [];//4个方向遍历尝试let dirList = [[1, 0], [-1, 0], [0, 1], [0, -1]];for (let i = 0; i < dirList.length; i++) {//获取方向let dir = dirList[i];//获取到下一步let nextIndex = [this.blackIndex[0] + dir[0], this.blackIndex[1] + dir[1]];//判断是否越界if (checkCross(nextIndex)) {//克隆数据,需要深拷贝let clone = arrClone(this.codeID);let temp = clone[nextIndex[0]][nextIndex[1]];clone[nextIndex[0]][nextIndex[1]] = clone[this.blackIndex[0]][this.blackIndex[1]];clone[this.blackIndex[0]][this.blackIndex[1]] = temp;//查看改变后的数据是否重复  不存在就记录if (!this.recordList.hasOwnProperty(JSON.stringify(clone))) {this.recordList[JSON.stringify(clone)] = "";//诞生子状态let state = new State(this.target, this, clone, dir, this.recordList, nextIndex);children.push(state);}}}return children}}//设置一个接口,对应的模块,对外暴露内容
module.exports = State;
//在语法层面,引用数据类型的深拷贝 但是对于vec类型会自动转换为object类型
function arrClone(arr) {return JSON.parse(JSON.stringify(arr));
};

2.创建一个专门放BFS算法的文件,里面只有function定义的方法

通过递归每次调用生成子状态,子状态会拥有父状态,通过子状态达到终点的情况倒退父节点,把路径塞入path,最后绘制路径

这里两个文件都是需要module.exports = 内容

在game脚本里面导入

import 名字 from "路径"

//检查数组是否完全一致
function checkIsSame(arr1, arr2) {return JSON.stringify(arr1) === JSON.stringify(arr2);
}function search(start) {let path = [];//每一层的容器let stateList = [start];//终点let destination = null;f(stateList);//核心逻辑,递归到终点为止function f(list){//获取所有的子状态let allChildren = [];for(let i = 0;i < list.length;i++){let children = list[i].getChildren();children.forEach(e => {allChildren.push(e);});}//判断子节点中是否存在终点for(let j = 0;j < allChildren.length;j++){if(checkIsSame(allChildren[j].target,allChildren[j].codeID)){destination = allChildren[j];}}// cc.log(destination);//检查是否找到了终点if(destination){cc.log("找到啦");//找到则绘制路径drawPath();}else{f(allChildren);}}//绘制还原路径function drawPath(){let p = destination;while(p.par){path.unshift(p.dir);p = p.par;}}return path;
}
module.exports = search;

cocos 拼图思路相关推荐

  1. 记一次cocos逆向

    记一次cocos逆向 为什么要想着去做逆向 何为逆向技术 cocos逆向思路 准备工作 开始逆向 最后 为什么要想着去做逆向 有一次我在考虑怎么给游戏加密的时候,突发奇想,与其想着怎么加密,不妨看看那 ...

  2. unity图片变成马赛克如何取像素并改变颜色_爬取微信好友头像完成马赛克拼图!千张头像拼成海贼王!...

    马赛克拼图 何谓马赛克拼图(千图成像),简单来说就是将若干小图片平凑成为一张大图,如下图路飞一样,如果放大看你会发现里面都是一些海贼王里面的图片. Our Tragets 爬取所有微信好友的头像 将所 ...

  3. 解密盛大和陈天桥:显娱乐帝国雏形 缺迪斯尼精神

    尽管盛大在短短几年内便完成了娱乐帝国的雏形,但是盛大无法回避的是,它仍然缺少米老鼠和迪斯尼精神. 陈天桥,一个见证了游戏产业发展的传奇人物,他的人和让他成功的游戏<传奇>都是被大家津津乐道 ...

  4. 滴滴开源小桔棱镜:一款专注移动端操作行为的利器

    一.棱镜是什么? 小桔棱镜是一款专注于移动端操作行为的工具,涵盖APP操作回放.操作检测.以及数据可视化能力.本篇我们会从产品设计理念和技术实现思路上对棱镜进行整体介绍. 功能结构图 二.为什么要做棱 ...

  5. 微信小程序(游戏)----拼图游戏(设计思路)

    微信小程序(游戏)----拼图游戏(设计思路) 设计思路 1.将一张海报等分成 N*N 的矩阵 方法一:利用两个组件循环完成,view组件和image组件,view组件作为盒子规定大小--超出部分不显 ...

  6. 【Cocos Creator 实战】05 - 如何判断拼图完成(胜利)

    文章目录 概览 主要内容 项目资源 开搞 胜利规则 核心代码 总结 知识点 下一步 继续继续. 上一篇地址:[Cocos Creator 实战]04 - 如何给拼图加上吸附效果 概览 主要内容 来看看 ...

  7. unity实现动态拼图的思路总结

    主要总结动态拼图的其中2个关键点 1.如何实现一个边缘不是锯齿的遮罩 2.如何实现对动态内容的遮罩 针对第一点,unity原生提供的sprite mask是用模板缓冲测试来实现的遮罩,当遮罩图某个像素 ...

  8. 【Cocos Creator 实战】06 - 如何给拼图游戏添加计时器

    文章目录 概览 主要内容 项目资源 开搞 项目结构 字体 如何控制节点的显示&隐藏 如何设置节点的相对位置 & 自动大小 & 对齐策略 如何防止节点的点击穿透 如何倒计时 总结 ...

  9. 《Cocos Creator游戏实战》老虎机抽奖效果实现思路

    在线体验地址 Cocos Creator | SlotMachine Cocos Store 购买地址(如果没有显示,那就是还在审核): https://store.cocos.com/app/det ...

最新文章

  1. blocked java线程_Java线程状态:BLOCKED与WAITING的区别
  2. Spider_douyin
  3. C语言矩阵M*N节省空间的算法(附完整源码)
  4. WebLogic中文博客
  5. shell脚本安装python_shell脚本安装python、pip
  6. Python爬虫自学之第(④)篇——强大的正则表达式,re模块
  7. Unity动态对象优化
  8. dataframe里面数据截取的规律
  9. 2_Recurrent Neural Networks (RNNs)循环神经网络 —Simple RNNs
  10. mysql开发必知必会
  11. flutter尽然还能有这种操作!!!
  12. Android实现多条Toast快速显示(强制中止上一条Toast的显示)
  13. Mxnet框架学习笔记(二):Kaggle房价预测实战分析
  14. 蓝桥杯官网 试题 PREV-113 历届真题 估计人数【第十届】【决赛】【研究生组】【C++】【Java】【Python】三种解法
  15. 极光尔沃:太空3D打印机首次亮相 航天领域应用潜力巨大
  16. 硬盘损坏,怪我咯?3分钟拯救硬盘里的小姐姐!
  17. airdrop搜不到对方_如何将AirDrop图标添加到您的macOS Dock
  18. 【转】面向程序员的数据库访问性能优化法则
  19. 计算机网络是按覆盖地域划分吗,下列哪些计算机网络是按覆盖地域划分的()。...
  20. oracle 判断表存在建表,oracle创建表之前判断表是否存在,如果存在则删除已有表...

热门文章

  1. c++:利用socket基于TPC/IP实现通信 在线聊天
  2. SpringBoot 基于配置文件给bean赋值
  3. 什么叫h5项目_对移动端h5项目的一点总结
  4. linux飞信机器人,linux飞信机器人的安装fetion
  5. LCD1602液晶显示案例
  6. (第三章)UI---PS 基础 钢笔抠图与商业案例
  7. 数字化转型:核心架构、重要价值及实现路径
  8. 复旦计算机考研英语,我收集的近几年复旦计算机复试笔试题
  9. 18.3 字节码指令集与解析举例 - 算数指令
  10. 业余爱好者想入门编程,一定远离那些只会说No的家伙,尤其程序员