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

news2024/11/19 1:46:37

设计一个 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.coloradmin.cn/o/1955386.html

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

相关文章

如何从网站获取表格数据

1.手动复制粘贴 最简单的方法是直接在网页上手动选择表格内容&#xff0c;然后复制粘贴到Excel或其他表格处理软件中。这种方法适用于表格较小且不经常更新的情况。 2.使用浏览器插件 有许多浏览器插件可以帮助从网页中提取表格数据&#xff0c;例如&#xff1a; -TableCapt…

liteos定时器回调时间过长造成死机问题解决思路

项目需求 原代码是稳定的&#xff0c;现我实现EMQ平台断开连接的时候&#xff0c;把HSL的模拟点位数据采集到网关&#xff0c;然后存入Flash&#xff0c;当EMQ平台连接的时候&#xff0c;把Flash里面的点位数据放在消息队列里面&#xff0c;不影响实时采集。 核心1&#xff1a…

【Linux】多线程4——线程同步/条件变量

1.Linux线程同步 1.1.同步概念与线程饥饿问题 先来理解同步的概念 什么是线程同步 在一般情况下&#xff0c;创建一个线程是不能提高程序的执行效率的&#xff0c;所以要创建多个线程。但是多个线程同时运行的时候可能调用线程函数&#xff0c;在多个线程同时对同一个内存地…

【文件fd】C++文件操作 | 详解系统调用接口文件操作 | 系统调用接口库函数

目录 1.回顾理解&引出问题 2.C文件操作 3.系统调用文件操作 3.0准备工作 3.1版本1☞open 3.2版本2☞文件权限 3.3版本3☞权限掩码 3.4版本3☞标记位传参 3.5版本4☞close 3.6版本5☞write 3.7flags选项 3.7.1 O_WRONLY | O_CREAT 3.7.2 O_WRONLY | O_CREAT …

Servlet详解(超详细)

Servlet详解 文章目录 Servlet详解一、基本概念二、Servlet的使用1、创建Servlet类2、配置Servleta. 使用web.xml配置b. 使用注解配置 3、部署Web应用4、处理HTTP请求和生成响应5、处理表单数据HTML表单Servlet 6、管理会话 三、servlet生命周期1、加载和实例化2、初始化3、 请…

Python爬虫入门02:Fiddler下载使用教程

文章目录 手机抓包全攻略&#xff1a;Fiddler 工具深度解析引言Fiddler 工具简介为什么选择 Fiddler&#xff1f; 安装与配置 Fiddler步骤一&#xff1a;下载与安装步骤二&#xff1a;配置浏览器代理步骤三&#xff1a;安装 HTTPS 证书 配置手机以使用 Fiddler步骤一&#xff1…

鸿蒙应用框架开发【OpenGL三棱椎】 NDK

OpenGL三棱椎 介绍 XComponent控件常用于相机预览流的显示和游戏画面的绘制,在HarmonyOS上&#xff0c;可以配合Native Window创建OpenGL开发环境&#xff0c;并最终将OpenGL绘制的图形显示到XComponent控件。本示例基于"Native C"模板&#xff0c;调用OpenGL(Open…

wpf中团队独立开发模块和左侧2个菜单的框架演示

此篇文章和上一篇文章wpf中开发独立模块功能和左侧1个菜单的框架演示-CSDN博客的结构是一样的&#xff0c;有1点不同的是&#xff0c;左侧有2层菜单&#xff0c;所以&#xff0c;就会更加的复杂。建议&#xff0c;先看明白上一篇的内容&#xff0c;再看这篇文章&#xff0c;否则…

CSS实现表格无限轮播

<div className{styles.tableTh}><div className{styles.thItem} style{{ width: 40% }}>报警名称</div><div className{styles.thItem} style{{ width: 35% }}>开始时间</div><div className{styles.thItem} style{{ width: 25% }}>状态&…

前端三大主流框架对比

在现代前端开发中&#xff0c;React、Vue和Angular是三大流行的框架/库。它们各自有独特的优缺点&#xff0c;适用于不同的开发需求和项目规模。下面是对这三者的详细比较&#xff1a; 一、 React 简介&#xff1a; 由Facebook开发和维护&#xff0c;是一个用于构建用户界面…

亚博科技和幻尔科技的十轴IMU在Ros2 Humble下驱动后数值无限趋于0的解决方案

在做机器人导航以及建模的时候&#xff0c;考虑到多传感器融合可能会带来更好的效果&#xff0c;于是决定使用幻尔科技的十轴IMU&#xff08;其实亚博科技与幻尔科技这块IMU的内部完全一致&#xff0c;驱动代码都完全一致&#xff09;驱动后使用以下命令输出传来的四元数等数据…

自写ApiTools工具,功能参考Postman和ApiPost

近日在使用ApiPost的时候&#xff0c;发现新版本8和7不兼容&#xff0c;也就是说8不支持离线操作&#xff0c;而7可以。 我想说&#xff0c;我就是因为不想登录使用才从Postman换到ApiPost的。 众所周知&#xff0c;postman时国外软件&#xff0c;登录经常性抽风&#xff0c;…

Mike SHE里如何正确设置分区降雨

前言&#xff1a; MIKE SHE分布式水文模型现阶段用于流域洪水的项目比较多&#xff0c;因属于大尺度模型&#xff0c;基本可以模拟水循环全过程&#xff0c;包含降雨—蒸发——产汇流—地表水—地下水等。同时还可以耦合MIKE11水动力水质模型。 今天给大家介绍下MIKESHE是如何…

从零到一使用 Ollama、Dify 和 Docker 构建 Llama 3.1 模型服务

本篇文章聊聊&#xff0c;如何使用 Ollama、Dify 和 Docker 来完成本地 Llama 3.1 模型服务的搭建。 如果你需要将 Ollama 官方不支持的模型运行起来&#xff0c;或者将新版本 llama.cpp 转换的模型运行起来&#xff0c;并且想更轻松的使用 Dify 构建 AI 应用&#xff0c;那么…

进程间的通信(IPC)--管道

1.进程间通信常用的方式 1 &#xff0c;管道通信&#xff1a;有名管道&#xff0c;无名管道 2 &#xff0c;信号 - 系统开销小 3 &#xff0c;消息队列 - 内核的链表 4 &#xff0c;信号量 - 计数器 5 &#xff0c;共享内存 6 &#xff0c;内存映射 7 &#xff0c;套接…

人称“灯爷”的灯光师到底要做些什么,看看他的岗位说明书

灯光师又称“灯爷”,是摄影制作部门负责灯光设备的技术人员,一般归摄影指导调配。被尊称“爷”,可见灯光师的地位不容小觑。那么这个岗位到底要做些什么呢&#xff1f; 岗位职责&#xff1a; 1、负责公司灯光设备的调制、维护和保养&#xff1b; 2、负责各包房灯光设备的调制、…

Mac环境报错 error: symbol(s) not found for architecture x86_64

Mac 环境Qt Creator报错 error: symbol(s) not found for architecture x86_64 错误信息 "symbol(s) not found for architecture x86_64" 通常是在编译或链接过程中出现的问题。这种错误提示通常涉及到符号未找到或者是因为编译器没有找到适当的库文件或函数定义。 …

基于springboot+vue+uniapp的养老院系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

初识git工具~~上传代码到gitee仓库的方法

目录 1.背景~~其安装 2.gitee介绍 2.1新建仓库 2.2进行相关配置 3.拉取仓库 4.服务器操作 4.1克隆操作 4.2查看本地仓库 4.3代码拖到本地仓库 4.4关于git三板斧介绍 4.4.1add操作 4.4.2commit操作 4.4.3push操作 5.一些其他说明 5.1.ignore说明 5.2git log命令 …

ACC:Automatic ECN Tuning for High-Speed Datacenter Networks 相关知识点介绍(二)

目录 PerfTest工具 Incast traffic Incast Traffic 的原因 Incast Traffic 的影响 解决方法 流量负载 简单解释 影响因素 影响 管理方法 LINKPACK 主要特点 LinkPack 的应用 运行结果 Quantum ESPRESSO 主要特点 TensorFlow 主要特点 主要组件 Incast与qp …