【叠高高】叠蛋糕游戏的微信小程序开发流程详解

news2024/9/21 18:31:16

记得小时候玩过的搭积木游戏吗,和叠高高游戏原理差不多的,与之类似的还有盖高楼游戏,就是看谁盖的(叠的)最高,这里讲一下比较基础的叠高高游戏小程序实现过程,对编程感兴趣的同学可以参考学习一下,代码不会很多,非常值得入手研究学习哦。

打开微信开发工具,选择小程序,创建一个项目,
新建小程序

例如项目名称为miniprogram-StackHigh,然后选择以下,再确定创建

  • AppID 使用自己的测试号
  • 不使用云服务
  • JavaScript - 基础模板

开始页面

要实现从开始页面跳转到游戏页面,

只需在文件/pages/index/index.js里的onLoad()方法中添加一段代码即可,代码如下

wx.navigateTo({
  url: '/pages/game/game',
})

游戏页面

在一个游戏页面文件/pages/game/game.wxml中写,只需要一个canvas画布组件即可,布局如下

<view class="page">
  <canvas type="2d" id="canv" class="canvas" bindtouchstart="onTouchStart" bindtouchend="onTouchEnd"></canvas>
</view>

游戏逻辑

理清一下游戏逻辑,大致是这样,

需要一个钩子放在上面左右移动,同时带着方块,
当用户点击屏幕时,方块就会脱钩向下掉落,有惯性,会稍微偏移一点,
最好可以落到下面的方块上面,这样看着可以计算高度,
目标很简单,就是盖楼,叠高高,看谁的最高,
增加关卡难度,盖得越高,移动钩子越快

在一个游戏逻辑文件/pages/game/game.js中开始写代码,

加载时

先写好,从页面加载完成时的onReady()方法中去写获取canvas组件,

然后绑定的触摸事件onTouchStartonTouchEnd,代码如下

Page({
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    wx.createSelectorQuery().select('#canv').fields({ size: true, node: true }, res => {
      //...
      //设置到画布的数据
      this.canvasData = {
        canvas: res.node,
        ctx: res.node.getContext('2d'),
      };
      //初始化画布
      this.initCanvas();
    }).exec()
  },
  /**
  * 触摸开始事件
  */
  onTouchStart(e) {
    //这里没关系,可不写任何代码
  },
  /**
  * 触摸结束事件
  */
  onTouchEnd() {
  	// 这里先判断 如果在动画进行中 或者 游戏已结束 就不继续处理
    if (this.isAnimining || this.isGameEnd) return;
    const { objBlock, objHook } = this.canvasData;
    // 判断 方块是否被钩子勾上
    if (!objBlock.isHook) return;
	// 将方块脱钩 修改它的属性:下落速度 和 没勾
    objBlock.offsetX = objHook.offsetX;
    objBlock.isHook = false;
    // 动画开始了 方块将下落
    this.isAnimining = true;
  },
  
})

初始化

获取组件后,会看到上面有调用了初始化方法initCanvas()

先加载图片资源,图片文件都放在项目里的static文件夹中, 实现的代码如下

const { canvas, ctx } = this.canvasData;
this.loadResources([{
  src: '/static/hook.png',
  width: canvas.width * 0.2
}, {
  src: '/static/block-black.png',
  width: canvas.width * 0.3
}, {
  src: '/static/block-blue.png',
  width: canvas.width * 0.3
}, {
  src: '/static/block-yellow.png',
  width: canvas.width * 0.3
}, {
  src: '/static/block-red.png',
  width: canvas.width * 0.3
}], images => {
  // 将图片数据设置到画布数据中
  this.canvasData.images = images;
  // 初始化图层方法
  this.initLayers();
  // 设置初始化计时
  this.currentTime = 0;
  // 初始化游戏未结束
  this.isGameEnd = false;
  // 执行重绘方法
  this.redraw();
});

会看到调用了加载图片资源的方法loadResources(resources, success)
其中传入的两个参数分别是说:

  • resources:这是一个数组,传入每个项都是引用图片文件的路径,和图片在游戏画布中的显示宽度;
  • success:这是一个回调函数,由于加载图片文件是异步操作的,待所有图片加载完就会调用这个函数,从中得到图片资源列表images,然后继续处理

上面的初始化方法中,继续处理中有调用了两个方法,一个是initLayers(),另一个是redraw(),分别是怎么实现的呢

图层

一个初始化图层的方法initLayers(),实现代码大致如下,

const { canvas, ctx, images } = this.canvasData;
//初始化所有基本的图层对象
const layers = [
   { type: 'bg' },
   Object.assign({ type: 'hook' }, images[0]),
   Object.assign({ type: 'block' }, images[1]),
   { type: 'info' }
 ].map(layer => Object.assign({ x: 0, y: 0 }, layer));
 const objBackground = layers[0];//这是背景图对象
 const objHook = layers[1];//这是钩子图对象
 const objBlock = layers[2];//这是方块图对象
 const objInfo = layers[3];//这是游戏显示信息对象
 //这里进一步初始化处理,不同类型的对象有不同的处理方式
 layers.forEach((layer, index) => {
   	//这里代码看着比较多,稍后讲...
 });
 // 将所有的图片 和 游戏对象 设置到画布数据中,将来有用
 Object.assign(this.canvasData, {
   layers, objBackground, objHook, objBlock, objInfo
 });

layers.forEach()遍历出不同类型的对象,有不同的处理方式,代码如下

//通过图层layer的属性type判断
switch (layer.type) {
  case 'bg'://背景图
    {
      //设置平台(托盘)数据 用于能接住从上面掉落下的方块
      layer.platform = {
        //省略...
      };
      //更新和绘制方法
      layer.update = () => {
        //省略...
        //绘制图片
        ctx.drawImage(layer.image, layer.x, layer.y);
      };
      break;
    }
  case 'hook'://钩子
    {
      //...
      //更新和绘制方法
      layer.update = () => {
        //...
        //绘制图片
        ctx.drawImage(layer.image, layer.x, layer.y);
      };
      break;
    }
  case 'block'://方块
    {
      //...
      layer.update = () => {
        //...
        //这里判断 如果没有被下面的平台(托盘)接住
        if (layer.isFallOut) {
        	//判断  方块是否落到画布外
          if (layer.y > canvas.height) {
          	// 设置动画结束,减去HP值
            this.isAnimining = false;
            objInfo.hp--;
            // 判断HP值 如果还有,继续游戏
            if (objInfo.hp > 0) {
              wx.showToast({
                title: '还有机会,再试试',
                icon: 'none'
              });
              //...
              // 重新绘制背景 恢复上次的
              redrawBg();
              // 重置方块数据
              resetBlock();
              return;
            }
            //HP值 不够则提示游戏结束
            this.gameEnd();
            return;
          }
          //...
          ctx.drawImage(layer.image, layer.x, layer.y);
          //...
          return;
        } else {
       // 绘制方块
          ctx.drawImage(layer.image, layer.x, layer.y);
        }

        //...
      };
      break;
    }
  case 'info':// 游戏信息
    {
      //...
      layer.update = () => {
        //...
        // 更新显示游戏信息
        ctx.fillText(`❤x${layer.hp}${layer.time}s  ${layer.scope}m`, layer.x, layer.y);
      };
    }
}

看上面的方法实现代码比较多,有省略了,有一些没有说,看着会不会觉得复杂呢,能看懂大概吧,
有没有看出来,每个游戏对象都有初始化属性,包括它的方法update()是用于将来更新绘制游戏对象的

重绘

另一个是重新绘制的方法redraw(),这个看着简单,

就是将所有的图层(游戏对象)都重绘一遍,实现代码大致如下,

if (this.isGameEnd) return;
const { canvas, ctx, objInfo, layers } = this.canvasData;
// 每一次绘制 都要先清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 遍历每个游戏对象 调用对象的更新和绘制方法
layers.forEach((layer) => layer.update());
// 这里记录时间
this.currentTime += TimeFPS;
let time = Math.floor(this.currentTime / 1000);
// 判断计时数是否变化 有变化就更新
if (time != objInfo.time) objInfo.time = time;
// 设置延迟多少ms就进行下一个重绘
this.timer = setTimeout(() => canvas.requestAnimationFrame(() => this.redraw()), TimeFPS)

TimeFPS 就是延迟多少毫秒的常量,这里它的值是TimeFPS = 60,是可以调节刷新速度的

游戏测试

讲到这里,上面的游戏基本就算完成了,还有剩下的细节没有说,那不重要,不要在意,

看到这里,能想到小时候玩过的叠高高游戏是怎样实现了吧,

这个叠高高游戏实现过程是否有给你启发呢,

看着像不像多个图层叠起来的运动效果呢,叠高高是不是在叠图层

如果还不够详细,可以看项目源代码,是完整的,项目源代码点击这里查看,在资源类别下可找到(如果在手机上浏览可能会找不到,请用电脑浏览器查看),感谢支持。

来看一下运行时是怎么样的,运行效果图如下
在这里插入图片描述

在这个游戏基础上,学会了可以实现与之原理类似的游戏,例如盖楼,抓娃娃机等等;
如果遇到什么问题,可以留言哦,请耐心等待作者回复 ~

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

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

相关文章

Linux Shell 实现一键部署Rust1.69

rust 前言 一门赋予每个人&#xff0c;构建可靠且高效软件能力的语言。 全世界已有数百家公司在生产环境中使用 Rust&#xff0c;以达到快速、跨平台、低资源占用的目的。很多著名且受欢迎的软件&#xff0c;例如 Firefox、 Dropbox 和 Cloudflare 都在使用 Rust。从初创公司…

网络安全工程师的入门学习路径,年薪30W不是梦!

最近看到网上有很多人在问诸如&#xff1a;“怎样成为网络信息安全工程师”等相关问题&#xff0c;这可能与近几年网络安全事件频发&#xff0c;国家对于互联网信息安全和互联网舆情的重视程度不断提升有关&#xff0c;网络信息安全工程师随之成为炙手可热的职业。 首先&#…

Web的基本漏洞--文件包含漏洞

目录 一、文件包含漏洞的介绍 1.文件包含漏洞的原理 2.常见的文件包含函数 3.文件包含漏洞的分类 本地文件包含漏洞 远程文件包含漏洞 3.文件包含漏洞的危害 4.文件包含漏洞的防范措施 5.文件包含漏洞的绕过手法 空字符绕过 超长字符绕过 一、文件包含漏洞的介绍 1…

5年经验之谈:月薪3000到30000,测试工程师的变“行”记

自我介绍下&#xff0c;我是一名转IT测试人&#xff0c;我的专业是化学&#xff0c;去化工厂实习才发现这专业的坑人之处&#xff0c;化学试剂害人不浅&#xff0c;有毒&#xff0c;易燃易爆&#xff0c;实验室经常用丙酮&#xff0c;甲醇&#xff0c;四氯化碳&#xff0c;接触…

你需要知道的 Selenium4 新特性

前言 最近又用到了Selneium&#xff0c;发现已经来到了 4.9 版本了。本篇文章来介绍下它较比 Selenium3 的一些新特性。 记录下&#xff0c;当是做笔记了。 最令人惊喜的是&#xff0c;Selenium4 会自动回收浏览器资源。 本文所使用的 Selenium 版本为 4.9.9 知识点&#x1f4…

开发一个收废品小程序步骤

随着环保意识的提升和可持续发展的迫切需求&#xff0c;废品回收成为了一个重要的议题。预约上门回收小程序的开发为用户提供了方便、快捷的废品回收服务&#xff0c;促进了废品资源的再利用和环保行动的推进。本文将介绍开发预约上门回收小程序的流程&#xff0c;以帮助开发人…

java12--本章作业

1. 第1题 public class Hello{public static void main(String[] args){Person[] persons new Person[3];persons[0] new Person("zsq", 18, "学生");persons[1] new Person("zzq", 19, "大学生");persons[2] new Person("zq…

【leetcode】1130. 叶值的最小代价生成树

1130. 叶值的最小代价生成树 1、问题描述2、解决方案2.1、动态规划2.1.1、问题分析2.1.2、代码实现 2.2、单调栈 1、问题描述 1130. 叶值的最小代价生成树 给你一个正整数数组 arr&#xff0c;考虑所有满足以下条件的二叉树&#xff1a; 每个节点都有 0 个或是 2 个子节点。数…

一文3000字实现基于Selenium+Python的web自动化测试框架

一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff1a;Firefo…

2.4 IDEA开发词频统计项目

一、词频统计准备工作 &#xff08;一&#xff09;启动集群的HDFS与Spark 启动HDFS服务 启动Spark集群 &#xff08;二&#xff09;在HDFS上准备单词文件 在master虚拟机上创建单词文件 - words.txt 将单词文件上传到HDFS指定目录/wordcount/input 二、本地模式运行Sp…

RCE漏洞演示,墨者靶场

#案列演示 打开墨者靶场&#xff0c;黑盒#命令注入执行分析 这个功能点有这么个功能&#xff0c;进行类似的像我们电脑上ping命令&#xff0c;这相当于就满足了命令&#xff0c;明显可能出现命令执行漏洞&#xff0c;可控变量和漏洞函数都存在。第一要去分析是什么操作系统&am…

批量 ping 网段的终极方法

我们分析和判定网络故障&#xff0c;如果有 10 设备&#xff0c;100 台设备&#xff0c;1000 台设备怎么办&#xff1f;一个个 ping 过去人都要疯掉了&#xff0c;这种情况在大型网络中我们有可能遇到&#xff0c;那怎么办呢&#xff1f;来听听海翎光电小编的一点看法吧&#x…

Spark写入Hive报错Mkdir failed on :com.alibaba.jfs.JindoRequestPath

1. 报错内容 23/05/31 14:32:13 INFO [Driver] FsStats: cmdmkdirs, srcoss://sync-to-bi.[马赛克].aliyuncs.com/tmp/hive, dstnull, size0, parameterFsPermission:rwx-wx-wx, time-in-ms32, version3.5.0 23/05/31 14:32:13 ERROR [Driver] ApplicationMaster: User class …

八大技术架构——升级之路

目录 一、单机架构 简介 工作原理 架构优缺点 相关软件 二、应用数据分离架构 简介 工作原理 架构优缺点 三、应用服务集群架构 简介 出现原因 工作原理 架构优缺点 相关软件 四、读写分离/主从分离架构 简介 工作原理 架构优缺点 相关软件 五、冷热分离架…

JMeter数据库性能测试指南:全面掌握基础操作

1.网络请求时间 2.数据库查询的时间 数据库性能指标 TPS:每秒事务数&#xff08;一秒钟服务器处理的事务数&#xff0c;事务指&#xff0c;请求出去到响应回来的整个过程的时间&#xff09; QPS:每秒查询量&#xff08;就是数据库每秒执行的SQL数量&#xff0c;包含insert/…

239:设置extent:bbox,限制瓦片图的加载范围,不加载空白瓦片

第239个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中加载geoserver发布的数据,这里主要介绍extent,设置bbox附加载layer上,目的是bbox在可视范围内才加载瓦片,否则不加载,好处是不用加载空白的瓦片数据。 直接复制下面的 vue+openlayers源代码,操作…

Odoo 16的docker部署以及vscode环境配置

之前一直使用Odoo源码配置开发环境&#xff0c;安装的步骤比较多&#xff0c;费时。趁着升级到16版本的机会&#xff0c;尝试使用docker快速配置Odoo的VSCode开发环境。 1 系统环境 &#xff08;1&#xff09;操作系统&#xff1a;ubuntu 20.04 Alternative downloads | Ubu…

Eclipse 教程 完结中

Eclipse 快捷键 关于快捷键 Eclipse 的很多操作都提供了快捷键功能&#xff0c;我们可以通过键盘就能很好的控制 Eclipse 各个功能&#xff1a; 使用快捷键关联菜单或菜单项使用快捷键关联对话窗口或视图或编辑器使用快捷键关联工具条上的功能按钮 Eclipse 快捷键列表可通过…

可节省60% MCU开发成本的NV080D-S8,单片机语音芯片在恒温碗上的应用

社会在不断进步&#xff0c;科技在不断发展&#xff0c;如今的恒温碗不仅带有温度显示功能&#xff0c;更附带有语音播报&#xff0c;能更好地知晓当前饭菜&#xff0c;变凉或过烫的情况&#xff0c;有效避免伤害宝宝脆弱的肠胃&#xff1b; 广州九芯电子推出了一款&#xff0c…

dynamic-datasource动态数据源学习

学习链接 spring整合mybatis的核心思路 & 数据源动态切换 & 多数据源事务控制 - 自己的链接&#xff08;本篇文章的上篇&#xff09; Mybatisplus生成代码配置 & p6spy打印sql & mybatis日志打印 & mybatisplus用法 dynamic-datasource-spring-boot-sta…