【碰碰球】弹珠游戏-微信小程序项目开发流程详解

还记得小时候玩过的弹珠撞击游戏不,这里把它的实现原理通俗易懂地讲一下,看看怎样实现一个碰碰球(弹珠)小游戏,除了个人玩法,也可以双人玩哦,与打乒乓球一样的,可练习临场反应。

创建项目

打开微信开发者工具,

小程序项目

选择创建小程序,项目名称自己填写,例如miniprogram-pairs-play

选择项目属性

如下图,依次选择即可
tu1

  • AppID 选自己的测试号
  • 不使用云开发
  • JavaScript - JS 基础模板

小游戏项目

如果要选创建小游戏项目来做,也是可以的,实现步骤大同小异,

可以将小程序的游戏源码改写到小游戏项目中,有兴趣可以看看笔者写得这篇文章来做

【贪吃蛇】微信小程序的游戏转到小游戏上实现方法详解

修改主页

创建一个项目,会看到里面自动创建好了一些文件,

找到位置pages/index/index,打开其中index.wxml

这是第一个页面布局文件,在里面加一个button按钮组件布局,

在对应的index.js逻辑文件中,实现一个点击方法,点击可进入游戏,

横屏显示

在对应的index.json配置文件中添加一个设置,如下,可实现横屏操作

"pageOrientation": "landscape"

游戏页面

进入的游戏页面,位置在pages/game/game

这里是没有的,需要自己创建一个游戏页面,

打开其中的game.wxml文件,添加内容如下,

<!--pages/game/game.wxml-->
<canvas class="canvas" id="zs1028_csdn" type="2d" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd"></canvas>

游戏页面只需要一个canvas画布组件就可以了,非常简单

游戏逻辑

理清了游戏逻辑思路,就可以实现了,

看看游戏页面,如下图,思考一下它是怎样实现的,是否简单呢,
在这里插入图片描述

初始化

首先,写好初始化代码,并绑定canvas组件的触摸点击方法,

// pages/game/game.js
import ZS1028_CSDN from '../../utils/zs1028_CSDN.js'const app = getApp()Page({/*** 生命周期函数--监听页面初次渲染完成*/async onReady() {const { width, height, node:canvas } = await ZS1028_CSDN.query('#zs1028_csdn')Object.assign(canvas, { width, height })// 创建一个小游戏的引擎框架对象let game = ZS1028_CSDN.createMiniGameEngine({canvas,bgColor: 'black', //背景色// isTest:true //性能测试用途,需要时取消这里注释})this.game = game// 初始化一些游戏数据对象const leftPlayerData = {}const rightPlayerData = {}const aBallData = {}// 定义需要存储的游戏数据const gameData = {leftPlayerData, //左侧的球拍rightPlayerData, //右侧的球拍aBallData, //弹珠的timeNum: 0, //计时scopeCount: 0, //记录分isGameEnd: false //游戏状态}// 定义游戏平面布局需要用到一些数据const r = canvas.height * 0.18  // 球拍半径const dR = r*0.25 // 弹珠半径const dH = canvas.height/2 //垂直居中位置const powR = Math.pow(r, 2) // 勾股定理中斜边长的平方this.gameData = gameData// 这里处理将上面定义的一些游戏数据对象添加到游戏引擎中game.addBgObject({data: leftPlayerData,reset(){...},redraw(data){...}})game.addBgObject({data: rightPlayerData,reset(){...},redraw(data){...}})game.addBgObject({data: aBallData,reset(){...},redraw(data){...}})game.addForeObject({data:{...},reset(){...},redraw(data){...}})// 最后,开始游戏,这个方法就是调用了game.start()this.restart()},onTouchStart(e) {//...触摸开始时处理},onTouchMove(e) {//...触摸移动时处理},onTouchEnd(e) {//...触摸结束时处理}

其中ZS1028_CSDN 是一个模块,是作者编写的游戏引擎(框架)的一些方法,总体代码不到200行,可以研究学习

写好了初始化逻辑,就可以运行看了,界面显示效果如预期的一致

游戏引擎

这里说明一下模块ZS1028_CSDN 游戏引擎game对象的用法:

  • addBgObject() 是将参与的游戏对象添加背景中的方法;
  • addForeObject() 是将参与的游戏对象添加到前景中的方法,可以把绘制的背景对象覆盖;
  • add..() 还有其它方法都在模块中,这里没用到就不多讲了,请自己探索!
  • run() 是运行游戏的;
  • stop() 是停止游戏的,在游戏结束时就调用它

球拍

接下来,绘制左边和右边的球拍两个,然后让用户可以拖动它上下移动

绘制球拍

前面使用了游戏引擎,这样绘制变得简单一些,

在添加游戏对象的方法addBgObject()中,

在传入的redraw()方法这里实现绘制,代码如下

game.addBgObject({data: leftPlayerData,reset(){//初始化数据Object.assign(this.data,{r,x:0, y:dH,relY:0,direY:0 })},redraw(data){const { context:ctx } = data//获取球拍距离垂直中心点的长度let relY = that.calcRelY(this.data)//绘制球拍的背景色ctx.fillStyle = 'red'ctx.beginPath()//绘制一个半球形状ctx.arc(this.data.x,this.data.y+relY,this.data.r,Math.PI*1.5,Math.PI/2)ctx.fill()}})
  • 方法reset()是重置数据的,里面写初始化它的数据即可,在开始或重置游戏时都会调用它;
  • 方法calcRelY()是计算球拍距离垂直中心点的长度的,实现很简单

绘制右边的球拍同上面绘制球拍的方法一样,复制这一段代码,然后改一改,实现右边绘制

拿起球拍

球拍绘制出来后,下一步,需要实现玩家对它的控制,

实现球拍的拾起操作,就从触摸开始的方法里开始写,

如下代码,遍历判断触摸位置是否碰到球拍所在位置

onTouchStart(e) {//此处省略了...for(let i=0; i<e.touches.length; i++){//一个触摸点,有三个重要属性 x, y, identifierlet touch = e.touches[i]//此处省略了...}
},

看上面的代码,touches是一个数组,表示它是支持多点触摸操作的,
利用这个特点,可以实现两个球拍同时移动操作,
也就是说,可以用自己的双手操作,或者你一边我一边来控制球拍进行游戏

移动球拍

实现拖动球拍操作,就在触摸移动的方法里写,

如下代码,判断触摸点的数据,修改球拍数据就行

onTouchMove(e) {const { leftPlayerData, rightPlayerData } = this.gameDatafor(let i=0; i<e.touches.length; i++){let touch = e.touches[i]//此处省略了...}
},

修改球拍的数据就是对象的relY属性,
在游戏引擎绘制方法中,它绘制的球拍看起来是会移动的

放下球拍

在触摸结束的方法里,要处理放下球拍,

如下代码,重置球拍数据,要考虑处理一个在触摸,另一个没在触摸时的场景

onTouchEnd(e) {const { leftPlayerData, rightPlayerData } = this.gameDataif (e.touches.length>0){for(let i=0; i<e.touches.length; i++){let touch = e.touches[i]//此处省略了...}}else{//重置球拍的数据this.resetTouchRelY(leftPlayerData)this.resetTouchRelY(rightPlayerData)}
},

弹珠(球)

还有一个弹珠,绘制应是球的形状,

一开始不要想那么复杂,先绘制看看

绘制弹珠

同样需要在添加的游戏对象中去实现绘制,

如下代码,和之前的添加对象方式一样,

game.addBgObject({data: aBallData,reset(){Object.assign(this.data,{x:canvas.width/2, //初始坐标位置y:dH,moveDirection: {speed:8, //移动速度angle:0.1 //方向角度},})},redraw(data){const { context:ctx } = data// 实现让弹珠动起来// 此处省略了...//绘制弹珠ctx.fillStyle = 'green'ctx.beginPath()ctx.arc(this.data.x,this.data.y,dR,0,Math.PI*2)ctx.fill()//保存改变,判断游戏是否结束//此处省略了...}
})

让弹珠动起来

在上面绘制方法里,开始的地方,

添加如下代码,即可让弹珠动起来,是不是很神奇

let { speed, angle } = this.data.moveDirection// 球拍按照角度angle方向移动位置
this.data.y += Math.sin(angle/180*Math.PI) * speed
this.data.x += Math.cos(angle/180*Math.PI) * speed

这里用到了初中数学知识:勾股定理;
上过初中的学生,可曾记得正弦sin(A),余弦cos(A)的公式呢;
其中A是边长弧度,angle是相交于水平线夹角的角度;
弧度和角度它们之间的关系是:A = angle / 180 * Math.PI

碰撞检测

现在弹珠可以动起来了,接下来,继续写代码,

代码如下,实现碰撞检测的思路大致是这样,改变的速度和角度即可

// 计算弹珠的四个顶点位置,用于实现碰撞检测
let left = this.data.x-dR
let right = this.data.x+dR
let top = this.data.y-dR
let bottom = this.data.y+dR
// 开始判断,先看看看移动方向到了哪个位置
// 判断是否碰撞上下边界
// ...此处省略了
// 再判是否断碰撞左边和右边的球拍
// ...此处省略了
// 再判是否断碰撞左边和右边界
// ...此处省略了// 这里是绘制弹珠,上面已经讲了...此处省略//最后,保存改变的速度和角度
Object.assign(this.data.moveDirection, { speed, angle })//到左边和右边边界就判断出界,到此游戏结束
if (left<=0 || right>=canvas.width) {game.stop()gameData.isGameEnd = true// 记录最高分app.setHistoryScopeCount(gameData.scopeCount)// 弹窗提示游戏结束ZS1028_CSDN.showModal('游戏结束, 记录'+gameData.scopeCount,'重新开始','退出游戏').then(res=>{if (res.confirm) that.restart()else wx.navigateBack()})
}

角度方向改变

实现碰撞检测的思路会复杂一些,需要研究搞清楚弹珠的运动轨迹,

可要研究仔细了,不然这代码会看不懂的,

弹珠的移动到碰撞后怎样改变方向,大致讲一下,代码如下

// 判断上下边界的
if (top<=0 || bottom>=canvas.height) {angle *= -1 //改变负号,弹珠在靠近水平线时会弹跳起来,是不是很神奇
} else if (r >= left) {//判断到左边,接近球拍半径就会执行到这里//...此处省略了
} else if (canvas.width > right && canvas.width-r <= right) {//判断到右边,接近球拍半径就会执行到这里//...此处省略了
}
//...此处省略了

显示记录

显示记录的方法

方法addForeObject()同上面的添加对象方式一样的,就绘制显示游戏的数据,

最后添加的会在最上层显示的,很简单,不重要不讲吧,

游戏运行

写到这里,按照上面的实现思路去做,边写完一部边运行,在实践中学习,

做好了,基本就可以运行游戏测试了,

回到开始讲得游戏初始化地方,调用游戏开始方法是this.restart(),代码如下

restart() {const { game } = this// 调用游戏引擎的run方法即可运行game.run()
}

要重新开始游戏,就调用restart()方法即可,

用上游戏引擎框架,运行过程就不用自己考虑实现了,就是这么很简单!

碰碰球的游戏运行效果的动图如下,
请添加图片描述

右边的球拍是可以拖动的,录制的电脑鼠标只能控制一个,
在真机上可同时控制两个的,这样玩效果会效果更好

完整代码可以看看碰碰球的小程序小游戏项目源码,已放在资源里了 请点前往查看(可能在手机上会找不到,改用电脑浏览器看看),感谢支持!❤
请添加图片描述

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

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

相关文章

前端面试:如何实现并发请求数量控制?

题目&#xff1a;实现一个并发请求函数concurrencyRequest(urls, maxNum) 要求如下&#xff1a; 要求最大并发数 maxNum;每当有一个请求返回&#xff0c;就留下一个空位&#xff0c;可以增加新的请求;所有请求完成后&#xff0c;结果按照 urls 里面的顺序依次打出&#xff1b;…

DE算法简介

文章目录 前言一、DE是什么&#xff1f;二、DE流程2.1 初始化种群2.2 变异&#xff08;差分操作&#xff09;2.3 交叉2.4 选择2.5 重复迭代 三、DE运行结果 前言 这两天看了DE算法&#xff0c;简单说下自己的认识 一、DE是什么&#xff1f; 百科定义&#xff1a;差分进化算…

Vue+ElementUI技巧分享:自定义表单项label的文字提示

文章目录 概要在表单项label后添加文字提示1. 使用 Slot 自定义 Label2. 添加问号图标与提示信息 slot的作用详解1. 基本用法2. 具名插槽 显示多行文字提示的方法1. 问题背景2. 实现多行内容显示3. 样式优化 结语 概要 在Vue和ElementUI的丰富组件库中&#xff0c;定制化表单是…

Linux进程间通信之匿名管道

文章目录 为什么要有进程间通信pipe函数共享管道原理管道特点管道的四种情况 管道的应用场景&#xff08;进程池&#xff09;ProcessPool.ccTask.hpp 为什么要有进程间通信 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享…

Vue3-自定义hook函数

Vue3-自定义hook函数 功能&#xff1a;可以将组合式API封装成一个函数&#xff0c;用于解决代码复用的问题。注意&#xff1a;需要在src文件夹下创建一个文件夹hooks&#xff0c;在里面放js文件&#xff0c;命名随意&#xff0c;主要是将setup函数中的代码放入js文件中。 // s…

Windows10下Maven3.9.5安装教程

文章目录 1.下载maven2.安装3.配置系统变量3.1.新建系统变量 MAVEN_HOME3.2.编辑系统变量Path 4.CMD命令测试是否安装成功5.配置maven本地仓库6.配置国内镜像仓库 1.下载maven 官网 https://maven.apache.org/download.cgi 点击下载。 2.安装 解压到指定目录 D:\installSoft…

计算机硬件的基本组成

一、冯诺依曼结构 存储程序&#xff1a; “存储程序”的概念是指将指令以二进制代码的形式事先输入计算机的主存储器&#xff0c;然后按其在存储器中的首地址执行程序的第一条指令&#xff0c;以后就按该程序的规定顺序执行其他指令&#xff0c;直至程序执行结束。 冯诺依曼计…

io多路复用:select、poll和epoll

1、为什么使用多路复用&#xff1a; 1.1单线程BIO监听socket 多路复用一般用于网络io当中&#xff0c;提到网络io我们肯定能想到socket。如果我们想要一个线程单纯的用向下文的方式监听很多个socket看他是否有事件发生&#xff0c;那这样是不可行。 但上一个socket1没有可读事…

Codewhisperer 使用评价

最近亚⻢逊推出了一款基于机器学习的 AI 编程助手 Amazon CodeWhisperer&#xff0c;可以实时提供代码建议。在编写代码时&#xff0c;它会自动根据现有的代码和注释给出建议。Amazon CodeWhisperer 与GitHub Copilot类似&#xff0c;主要的功能有: 代码补全注释和文档补全代码…

Banana Pi BPI-W3之RK3588安装Qt+opencv+采集摄像头画面.

场景&#xff1a;在Banana Pi BPI-W3 RK3588上做qt开发工作RK3588安装Qtopencv采集摄像头画面 2. 环境介绍 硬件环境&#xff1a; Banana Pi BPI-W3RK3588开发板、MIPI-CSI摄像头( ArmSoM官方配件 )软件版本&#xff1a; OS&#xff1a;ArmSoM-W3 Debian11 QT&#xff1a;QT5…

MySQL/Oracle用逗号分割的id怎么实现in (逗号分割的id字符串)。find_in_set(`id`, ‘1,2,3‘) 函数,

1.MySQL 1.1.正确写法 select * from student where find_in_set(s_id, 1,2,3); 1.2.错误示范 select * from student where find_in_set(s_id, 1,2 ,3); -- 注意&#xff0c;中间不能有空格。1、3 select * from student where find_in_set(s_id, 1,2, 3); -- 注意…

在Windows系统中查找GitBash安装位置

使用注册表可以轻松获取&#xff1a; reg query HKEY_LOCAL_MACHINE\SOFTWARE\GitForWindows /v InstallPath | findStr InstallPath此时输出一串字符&#xff0c; 通过字符串切割即可获取&#xff1a;

「Verilog学习笔记」使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 当EI10时、U1禁止编码&#xff0c;其输出端Y为000&#xff0c;GS1、EO1均为0。同时EO1使EI00&#xff0c;U0也禁止编码&#xff0c;其输出端及GS0、EO0均为0。由电路…

软件测试/人工智能丨深入人工智能软件测试:PyTorch引领新时代

在人工智能的浪潮中&#xff0c;软件测试的角色变得愈发关键。本文将介绍在人工智能软件测试中的一些关键技术&#xff0c;以及如何借助PyTorch深度学习框架来推动测试的创新与升级。 PyTorch&#xff1a;深度学习的引擎 PyTorch作为一种开源的深度学习框架&#xff0c;为软件…

LeetCode【36】有效的数独

题目&#xff1a; 思路&#xff1a; https://blog.51cto.com/u_15072778/3788083 代码&#xff1a; public boolean isValidSudoku(char[][] board) {// 二维数组第一个标识 0-9行&#xff0c;第二个表示 0-9数字&#xff0c;存的内容boolean 表示第0-9行&#xff0c;0-9这些…

CV计算机视觉每日开源代码Paper with code速览-2023.11.15

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构&#xff1a;CNN】PadChannel: Improving CNN Performance through Explicit Padding Encoding 论文地址&#xff1a;https:/…

【教3妹学编程-java基础6】详解父子类变量、代码块、构造函数执行顺序

-----------------第二天------------------------ 本文先论述父子类变量、代码块、构造函数执行顺序的结论&#xff0c; 然后通过举例论证&#xff0c;接着再扩展&#xff0c;彻底搞懂静态代码块、动态代码块、构造函数、父子类、类加载机制等知识体系。 温故而知新&#xff…

用户增长模型:3A3R策略模型

一、概述 A - A - A - R - R - R 增长模型&#xff0c;即3A3R策略模型&#xff0c;由海盗模型演变而来&#xff0c;是目前使用最多、适用范围最广的增长策略模型。原始的海盗模型由 Acquisition &#xff08;获客&#xff09;、 Activation &#xff08;活跃&#xff09;、 Re…

华夏ERP打包手册

Maven安装及环境配置 1.下载 浏览器搜索maven点击apache Maven 2.选择安装目录&#xff0c;注意不能有中文 3.环境变量配置 点击计算机右键属性>高级系统设置>环境变量 新建系统变量 MAVEN_HOME 变量值是安装目录 进入path点击新建点击编辑&#xff0c;写入% MAVEN_H…

深度学习OCR中文识别 - opencv python 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…