微信小游戏之三消(二)主要游戏控制方法

设计一个 game class。负责了游戏的核心控制逻辑,包括游戏状态管理、方块和道具的生成与效果处理,以及游戏的重新开始和复活流程。通过这些方法,脚本实现了游戏的基本玩法和用户交互。

主要游戏控制方法

  • gameStart():开始游戏,恢复所有方块状态,初始化分数管理器,设置地图。

  • mapSet(num):初始化地图,生成随机的方块布局。

  • checkNeedFall():检查是否需要下落的防抖方法。

  • onFall():方块下落的逻辑。

  • gameOver():游戏结束的逻辑,添加复活页面。

  • askRevive():处理复活请求,显示复活页面。

  • onReviveButton():复活按钮的点击事件。

  • showReviveSuccess():显示复活成功的页面。

  • onReviveCertainBtn():处理确定复活的按钮点击事件。

  • restart():重新开始游戏。

道具相关方法

  • onUserTouched(iid, jid, itemType, color, warning, pos):存储用户点击的方块信息,用于生成道具。

  • generatePropItem(type):根据类型生成道具。

  • checkGenerateProp(chain):检查并生成连锁道具效果。

  • onItem(type, color, pos):处理道具效果,如分数翻倍、炸弹消除等。

预制体实例化方法

  • generatePool():生成对象池,用于方块的实例化和回收。

  • instantiateBlock(self, data, parent, itemType, pos):实例化单个方块,初始化方块组件。

  • recoveryAllBlocks():回收所有方块节点,用于游戏重新开始或结束。

gameStart 方法是游戏开始时调用的核心逻辑,用于初始化游戏环境并启动游戏循环。以下是 gameStart 方法的逻辑分析:


/*** gameStart 方法用于启动游戏,初始化游戏环境和状态。*/
gameStart() {// 回收所有方块,准备重新开始游戏this.recoveryAllBlocks().then(() => {// 初始化分数管理器this._score.init(this);// 初始化游戏地图,设置方块布局this.mapSet(this.rowNum).then((result) => {// 游戏状态改变,更新游戏状态为开始状态(状态1)this._status = 1;});});
},

详细步骤:

  • 回收方块 (recoveryAllBlocks): 将之前游戏中使用的所有方块回收到对象池,以便重新利用,减少实例化开销。

  • 初始化分数 (_score.init): 初始化或重置分数管理器,为新游戏开始做准备。

  • 设置地图 (mapSet): 创建一个新的地图,随机生成方块,并设置它们在地图上的位置。这个方法还负责设置特殊方块类型,如道具方块。

  • 异步等待: 由于 mapSet 是异步的,使用 then 来确保在地图准备好之后再继续。

  • 状态更新: 设置 _status 为 1,这通常会在游戏循环和用户界面中用来检查游戏是否已经开始。

mapSet 方法的目的是为游戏创建一个初始状态的地图,其中包括随机分布的方块和道具,为游戏开始做好准备。通过使用 PromisesetTimeout,它能够处理异步的动画延迟,确保方块以动画形式逐一出现在游戏地图上。

// mapSet 方法用于初始化游戏地图,设置方块的布局和类型
mapSet(num) {// 初始化地图为一个 num x num 的二维数组this.map = new Array();// 保存当前对象的引用let self = this;// 生成随机数来确定特殊方块的位置let a = Math.floor(Math.random() * num);let b = Math.floor(Math.random() * num);let c = Math.floor(1 + Math.random() * (num - 1)) - 1;// 确保 c 不等于 a,以便有区分的道具位置if (a == c) c++;let d = Math.floor(Math.random() * num);// 返回一个 Promise 对象,以便在地图设置完毕后执行异步操作return new Promise((resolve, reject) => {// 遍历地图的每一行for (let i = 0; i < num; i++) {// 初始化当前行的数组this.map[i] = new Array();// 遍历地图的每一列for (let j = 0; j < num; j++) {// 根据随机坐标确定方块的类型(0为普通方块,1和2为不同类型的道具方块)let itemType = (i == a && j == b) ? 1 : (i == c && j == d) ? 2 : 0;// 调用 instantiateBlock 方法来创建方块实例self.map[i][j] = self.instantiateBlock(self, {x: j, // 列位置y: i, // 行位置width: self.blockWidth, // 根据地图宽度计算的方块宽度startTime: (i + j + 1) * self._controller.config.json.startAnimationTime / num * 2 // 计算动画开始时间}, self.blocksContainer, itemType);}}// 初始化检查管理器,准备进行方块检查this.checkMgr.init(this);// 设置一个延迟,以便于所有方块动画完成后再执行检查setTimeout(() => {// 解析 Promise,表示地图设置完成resolve('200 OK');// 执行检查函数,检查方块布局和消除情况self.checkMgr.check(self);}, self._controller.config.json.startAnimationTime * num / 2);});
}

详细步骤:

  1. 初始化地图数组:创建一个二维数组 this.map 来存储游戏地图的布局。

  2. 定义局部变量:保存对当前类的引用,以便在匿名函数中使用。

  3. 随机生成位置:生成随机坐标点,用于确定特殊方块的初始位置。

  4. 返回 Promise:使 mapSet 方法支持异步操作,以便在地图初始化完成后执行其他任务。

  5. 遍历地图位置:通过两层嵌套循环遍历地图的每一行和每一列。

  6. 确定方块类型:根据随机生成的坐标点,为每个方块分配类型(普通或道具)。

  7. 实例化方块:为每个位置创建方块实例,设置其属性,并添加到游戏地图中。

  8. 初始化检查管理器:在所有方块生成后,准备进行方块的消除检查。

  9. 设置延迟执行:使用 setTimeout 延迟执行检查函数,确保方块动画完成后再进行检查。

  10. 解析 Promise:在延迟时间结束后,解析 Promise 并执行方块检查,完成地图的初始化。

checkNeedFall 方法实现了一个防抖机制,确保方块下落的逻辑不会过于频繁地被触发,从而提高游戏性能并优化用户体验

// checkNeedFall 方法用于检查是否需要执行方块的下落动作
checkNeedFall() {// 如果 checkNeedFallTimer 已经存在,说明之前的检查尚未完成,需要清除定时器if (this.checkNeedFallTimer) {clearTimeout(this.checkNeedFallTimer);}// 设置一个新的定时器,以实现防抖功能// 防抖逻辑:在一定时间间隔(例如300毫秒)内,即使多次触发也不会连续执行下落逻辑this.checkNeedFallTimer = setTimeout(() => {// 检查游戏状态是否允许方块下落(状态为5时允许)if (this._status == 5) {// 如果状态允许,将游戏状态更新为下落状态(状态4)this._status = 4;// 调用 onFall 方法执行方块下落的逻辑this.onFall();}// 设置定时器的时间间隔为 300 毫秒,以实现防抖效果}, 300 / 1// (cc.game.getFrameRate() / 60) // 这里被注释掉的代码可能是为了适应不同的帧率);
}

详细步骤:

  1. 清除已有定时器:如果 checkNeedFallTimer 已经设置,使用 clearTimeout 清除它,避免之前的延迟操作影响当前逻辑。

  2. 定义局部变量:this 关键字引用当前对象,用于访问类的属性和方法。

  3. 设置新定时器:使用 setTimeout 创建一个新的定时器,延迟执行下落检查逻辑。

  4. 防抖逻辑:定时器的延迟时间设置为 300 毫秒,这意味着在这段时间内,无论触发多少次 checkNeedFall 方法,onFall 方法都只会执行一次。

  5. 检查游戏状态:在定时器的回调函数中,检查 _status 是否等于 5,即是否处于可以下落的状态。

  6. 更新状态为下落:如果条件满足,将 _status 更新为 4,表示方块即将开始下落。

  7. 执行下落逻辑:调用 onFall 方法,执行方块下落的逻辑。

  8. 定时器时间间隔:定时器的时间间隔可以根据游戏的帧率进行调整,以确保不同设备上都能正常工作。

onFall 方法实现了方块下落的逻辑,包括处理空格、生成新方块、执行下落动画,以及在适当的时候更新游戏状态


// onFall 方法用于处理方块下落的逻辑
onFall() {// 检查是否可以生成道具,并在完成后继续执行下落逻辑this.checkGenerateProp(this._score.chain).then(() => {let self = this; // 保存当前对象的引用let canFall = 0; // 用于记录连续空格的数量// 从每一列的最下面开始往上判断,是否有空格for (let j = this.rowNum - 1; j >= 0; j--) {canFall = 0; // 重置连续空格计数器// 从底部开始向上遍历每一列的方块for (let i = this.rowNum - 1; i >= 0; i--) {// 如果当前位置的方块状态为已消失(状态2),则进行下落处理if (this.map[i][j].getComponent('cell')._status == 2) {// 将消失的方块回收到对象池中this.blockPool.put(this.map[i][j]);// 更新地图数组,标记当前位置为空this.map[i][j] = null;canFall++; // 增加连续空格计数} else {// 如果上方有连续空格,则让当前方块下落if (canFall != 0) {// 交换当前方块与上方空格的方块this.map[i + canFall][j] = this.map[i][j];this.map[i][j] = null;// 让上方的方块下落this.map[i + canFall][j].getComponent('cell').playFallAction(canFall, {x: j,y: i + canFall,});}}}// 如果当前列有连续空格,生成新方块并让它们下落for (var k = 0; k < canFall; k++) {// 在地图数组中放置新方块的位置this.map[k][j] = this.instantiateBlock(this, {x: j,y: k,width: this.blockWidth,startTime: null}, this.blocksContainer, '', {x: j,y: -canFall + k});// 让新生成的方块执行下落动作this.map[k][j].getComponent('cell').playFallAction(canFall, null);}}// 在所有下落动作完成后,设置一个延迟,再次检查游戏状态setTimeout(() => {// 初始化检查管理器,准备进行方块检查this.checkMgr.init(this);// 执行检查函数,检查方块布局和消除情况this.checkMgr.check(this);// 更新游戏状态为可玩this._status = 1;}, 250); // 设置延迟时间,以便于动画效果完成后再执行检查});
}

详细步骤:

  1. 检查生成道具:调用 checkGenerateProp 方法检查是否可以生成道具,并等待其完成后继续。

  2. 保存引用:保存当前对象的引用,以便在匿名函数中使用。

  3. 初始化空格计数器:canFall 用于记录连续的空格数量。

  4. 遍历列:从地图的最底部开始,向上遍历每一列。

  5. 重置空格计数器:在遍历每一列时重置 canFall

  6. 遍历行:在每一列内部,从底部向上遍历每一行。

  7. 方块下落处理:

    • 如果当前方块已经消失(状态为2),则将其回收并标记地图数组中相应位置为空。

    • 如果上方有空格,让当前方块下落。

  8. 生成新方块:如果有连续空格,生成新方块并让它们下落。

  9. 执行下落动作:调用 playFallAction 方法让方块执行下落动画。

  10. 设置延迟:在所有下落动作完成后,使用 setTimeout 设置延迟。

  11. 再次检查状态:延迟结束后,初始化检查管理器并执行检查函数,更新游戏状态。

更多详细代码逻辑请看:微信小游戏之三消(二)主要游戏控制方法代码逻辑分享 (qq.com)icon-default.png?t=N7T8https://mp.weixin.qq.com/s?__biz=MzI0NTE3ODY5Mg==&mid=2247483770&idx=1&sn=721d6cb02baf8d2345870e924598e094&chksm=e953c951de24404768866f4c01a3e97f4cda185fe4f4a1cba84c8b98fc76303de832f66c3ebb&token=1281952290&lang=zh_CN#rd

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

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

相关文章

Java学习Day16:基础篇6

1.静态和非静态 2.调用静态和非静态的过程 注&#xff1a;在Java中&#xff0c;同类中&#xff0c;确实可以使用类的对象来调用静态方法&#xff0c;尽管这不是推荐的做法。静态方法属于类本身&#xff0c;而不是类的任何特定实例。因此&#xff0c;理论上讲&#xff0c;你应该…

【iOS】—— KVO与KVC

KVO与KVC 1. KVOKVO底层实现分析如何验证上面的说法&#xff1a;NSKVONotifyin_Person内部结构didChangeValueForKey:内部会调用observer的observeValueForKeyPath:ofObject:change:context:方法 回答问题&#xff1a; 2. KVC简介&#xff1a;key和keyPath的区别key&#xff1a…

探索 Electron:如何进行网址收藏并无缝收录网页图片内容?

Electron是一个开源的桌面应用程序开发框架&#xff0c;它允许开发者使用Web技术&#xff08;如 HTML、CSS 和 JavaScript&#xff09;构建跨平台的桌面应用程序&#xff0c;它的出现极大地简化了桌面应用程序的开发流程&#xff0c;让更多的开发者能够利用已有的 Web 开发技能…

EtherNet/IP转CAN协议转化网关(功能与配置)

怎么样把EtherNet/IP和CAN两个协议连接起来?有很多朋友想要了解这个问题&#xff0c;那么作者在这里统一说明一下。其实有一个不错的设备产品可以很轻易地解决这个问题&#xff0c;名为JM-EIP-ECAT网关。接下来作者就从该设备的功能及配置详细说明一下。 一&#xff0c;设备主…

聊聊基于Alink库的主成分分析(PCA)

概述 主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是一种常用的数据降维和特征提取技术&#xff0c;用于将高维数据转换为低维的特征空间。其目标是通过线性变换将原始特征转化为一组新的互相无关的变量&#xff0c;这些新变量称为主成分&…

TinyMCE一些问题

1.element 在el-dialog中使用tinymce导致富文本弹窗在el-dialog后面的问题 原因是富文本的弹窗层级太低了 在APP.vue中添加样式即可解决 /* 富文本菜单 */ .tox-tinymce-aux {z-index: 9999 !important; }2.element 在el-dialog中点击富文本的功能栏报错 由于 aria-hidden 属…

Midjourney、Sora和硅谷机密-《分析模式》漫谈15

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的Preface&#xff08;前言&#xff09;有这么一句&#xff1a; Kent Beck, Ward Cunningham, and Jim Coplein encouraged me to get involved with the commu…

虚假的互联网信息?不妨从IT的角度理解【景观社会】

博主前言&#xff1a;“我思故我在”&#xff0c;笛卡尔的这一哲学命题&#xff0c;大抵上次还比较熟络的时光还是高中亦或复习考研政治的岁月里。这是一个光怪陆离的社会——或者说网络社会&#xff0c;形形色色的消息充斥在脑海之时&#xff0c;你是否还能认识真正的自己&…

YOLOV8-源码解读-SPP-SPPF

先给出YOLOV8中一键三连卷积模块 def autopad(k, pNone, d1): # kernel, padding, dilation"""Pad to same shape outputs."""if d > 1:k d * (k - 1) 1 if isinstance(k, int) else [d * (x - 1) 1 for x in k] # actual kernel-sizeif…

分布式事务解决方案(一) 2PC、3PC、TCC、Sega

目录 1.绪论 2.2PC 2.1 基本原理 2.1.1 组成 2.1.2 步骤 1.prepare阶段 2.commit阶段 2.2 2PC 存在的问题 2.2.1 阻塞问题 2.2.2 单点故障问题 1. 事务协调器宕机 2.部分数据不一致问题 2.资源管理器宕机 3. 事务协调器和资源管理管理器同时宕机 2.2 实现 2.2.1…

怎么将几个pdf合成为一个pdf?pdf合成为一个的常用方法

在现代的职场和学术环境中&#xff0c;如何将多个独立的PDF文档合并成一个统一的文件已经成为提高工作效率、优化文档管理和促进信息共享的重要手段。PDF格式以其卓越的跨平台兼容性、强大的数据保护能力以及清晰易读的版面设计&#xff0c;在全球范围内得到了广泛的应用和认可…

2-45 基于matlab的递归最小二乘法(RLS)对声音信号去噪

基于matlab的递归最小二乘法&#xff08;RLS&#xff09;对声音信号去噪,并对消噪前后的信号进行FFT分析&#xff0c;对比消噪前后的效果。可替换自己的声音信号进行分析。程序已调通&#xff0c;可直接运行。 2-45 递归最小二乘法&#xff08;RLS&#xff09; FFT分析 - 小红书…

系统移植(七)u-boot移植 ④ trusted版本

文章目录 一、U-boot源码适配&#xff08;一&#xff09;执行make stm32mp15_trusted_defconfig命令进行配置&#xff0c;生成.config文件&#xff08;二&#xff09;执行make menuconfig命令&#xff0c;对u-boot源码进行重新配置1. 对u-boot源码进行配置&#xff0c;移除pmic…

【C++进阶学习】第十弹——哈希的原理与实现——链地址法的原理与讲解

开放地址法&#xff1a;【C进阶学习】第九弹——哈希的原理与实现——开放寻址法的讲解-CSDN博客 前言&#xff1a; 哈希的整体思想就是建立映射关系&#xff0c;前面的开放地址法的讲解中&#xff0c;也对哈希的原理做了详细的讲解&#xff0c;今天就来讲解一下实现哈希的另一…

Java NIO (一)

因工作需要我接触到了netty框架&#xff0c;这让我想起之前为夺高薪而在CSDN购买的Netty课程。如今看来&#xff0c;这套课程买的很值。这套课程中关于NIO的讲解&#xff0c;让我对Tomcat产生了浓厚的兴趣&#xff0c;于是我阅读了Tomcat中关于服务端和客户端之间连接部分的源码…

如何快速获取全网精准客流?揭秘不为人知的5大运营策略!

有同行所在的地方&#xff0c;就一定拥有咱们需要的客户。客户看的是结果&#xff0c;搜索的是问题&#xff0c;寻找的是答案。 如果没有付费流量&#xff0c;单纯靠搞免费流量&#xff0c;很多大厂的运营也会变得一文不值。一个牛逼的运营&#xff0c;不仅是会做付费流量&…

leetcode10 -- 正则表达式匹配

题目描述&#xff1a; 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s的&#xff0c;而不是部分字符串。 示例 1&#xff1…

PDF转Word后不能修改怎么办?是什么原因呢?

平时在生活中&#xff0c;很多朋友都会有将PDF转换成Word文档的需求&#xff0c;因为一般情况下PDF文件是不能直接编辑修改的&#xff0c;所以只能通过这种方式来解决问题。但是近期&#xff0c;有部分用户在后台反馈说PDF转Word后不能修改怎么办呢&#xff1f;其实这个问题也是…

第1-3章Excel数据分析基础

文章目录 第1章&#xff1a;使用统计函数做数据分析1-1常用统计函数应用1-2条件统计函数1-3多条件统计函数1-4条件统计函数中的通配符1-5将条件统计函数中的条件数组化1-6单条件文本合并-新增函数1-7多条件与模仿通配符的文本合并 第2章&#xff1a;数据分析之合并计算2-1合并计…