【见缝插针】射击类游戏-微信小程序项目开发流程详解

还记得小时候玩过的见缝插针游戏吗,比一比看谁插得针比较多,可有趣了,当然了,通过它可以训练自己的手速反应,以及射击水平,把握时机,得分越高就越有成就感,相信小朋友们会喜欢它的,游戏实现原理看似简单,实则包含了数学中几何知识,接下来讲一讲实现过程吧。

这篇文章主要是用微信小程序项目做的,需要用微信开发者工具打开,

打开微信开发者工具,选择创建小程序,项目名称自己填写,例如miniprogram-shoot-scope

如下图,依次选择即可
tu1

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

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

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

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

游戏页面

接下来,创建一个游戏页面,文件路径是/pages/game/game,

打开布局文件/pages/game/game.wxml

在里面放一个画布组件(Canvas元素)就可以了,内容如下

<!--pages/game/game.wxml-->
<view class="page"><canvas class="canvas" type="2d" id="zs1028_csdn" bindtouchend="onTouchEnd"/>
</view>

游戏逻辑

打开逻辑文件/pages/game/game.js

在里面写游戏逻辑代码,先把画布组件的触摸事件和初始化方法都写好,

游戏引擎

写好的代码如下,从onReady()开始执行,绑定onTouchEnd()触摸事件

//导入一个模块,这是个小游戏引擎,或者框架
import ZS1028_CSDN from '../../utils/zs1028_CSDN.js'const app = getApp()Pages({/*** 生命周期函数--监听页面初次渲染完成*/onReady() {//选择查询画布组件实例wx.createSelectorQuery().select('#zs1028_csdn').fields({ size: true, node: true }, res => {//查询结果从这里返回const { width, height, node: canvas } = res//将画布大小调整一下,保证宽高一致Object.assign(canvas, { width, height })// 创建一个游戏引擎,用这实现游戏会方便一些const engine = ZS1028_CSDN.createMiniGameEngine({canvas,// isTest: true, //测试的,去掉注释可以显示游戏动画帧率,数字越大越流畅})//这里处理初始化游戏数据...稍后讲const newShotData = {...}const shotsData = {...}const centerScopeData = {...}//将上面的定义游戏都缓存到this.gameData = {centerScopeData,shotsData,newShotData}//把游戏引擎缓存到this.engine = engine//再把初始化游戏数据添加到游戏引擎对象中...稍后讲engine.addBgObject({data: newShotData,...})engine.addBgObject({data: shotsData,...})engine.addForeObject({data: centerScopeData,...})//最后,调用此方法开始游戏this.restart()}).exec()},/*** 绑定画布的触摸结束事件*/onTouchEnd() {if (this.isGameEnd) return//将底部的针箭的速度属性从0改为10,就可以发射const { newShotData } = this.gameDataif (newShotData.speed > 0) returnnewShotData.speed = 10},
})

模块文件zs1028_CSDN.js由开发者实现,代码看起来可能复杂些,这里讲简单的实现思路,

接下来讲,怎么用这个模块来轻松实现游戏,

有JavaScript编程基础功底的学者可以研究这模块来学习,
文件代码不多,有150行

初始化数据

开始游戏前,需要向游戏引擎传入游戏的一些初始化数据,

在上面省略的初始化游戏数据代码位置开始着写,写好代码如下

//记录一个水平的中心点位置
const centerX = width / 2
//定义一个靶的中心数据,就是绘制大红点的
const centerScopeData = {x: centerX,y: centerX,r: centerX * 0.5,initTime: 0,
}
//定义一个针箭的数据
const shotsData = {x: centerX,y: centerX,r: centerX * 0.1,//针的尾部圆半径shots: [],//放置已钉上的列表speed: 1,//旋转速度angle: 0,//旋转角度offset: 0
}
//定义一个在底部的针箭数据
const newShotData = {y: -1,//上下的位置,在底部speed: 0,//射出的速度,为0就是待发的状态
}

将初始化好的一些游戏数据对象都放到this.gameData,后面有需要就取,
对照游戏界面看看,就知道只用这三个数据就可以了,

加入游戏对象

继续写下去,将初始化数据添加到游戏引擎对象中,

钉上靶中的针箭

这里添加所有钉上针箭的对象,代码如下

//创建一个新的针箭对象
let shot = this.addNewShot()
//算出它的开始位置
const startY = canvas.height - shotsData.r - shot.data.linerLength - centerScopeData.r - centerScopeData.y
//使用游戏引擎的添加背景对象方法,绘制中心的所有针箭
engine.addBgObject({data: shotsData, //传入对象数据//实现重置数据方法reset() {const { shots } = this.datashots.length = 0 //重置时候,将所有钉上的针箭都清除},//实现绘制方法redraw(data) {const { canvas, context: ctx, topBar } = datalet { x, y, r, shots, speed, angle } = this.data// 内边距上边距离let paddingTop = topBar?.bottom || 0
// 绘制所有钉上的针箭shots.forEach((item, index) => {//夹角角度let deg = item.data.angle + angle//圆边弧度let radian = deg / 2 / Math.PI// 线段(针)长let c = item.data.linerLength + centerScopeData.r//使用数学中的勾股定理公式,求得线段的两点坐标let y2 = Math.sin(radian) * c + y + paddingToplet x2 = Math.cos(radian) * c + x//调用对象的绘制方法,传入的是针箭的两端坐标点item.redraw(x, y + paddingTop, x2, y2)})//旋转位置更新let offset = speed / 10this.data.offset = offsetthis.data.angle = (angle + offset) % 360}
})

在初中数学课上才有讲勾股定理哦,可见学好数学对做游戏来说是多么重要

底下待发的针箭

这里添加在底部针箭的对象,代码如下

const that = this
//调用引擎的添加背景对象方法,绘制底部的针箭
engine.addBgObject({data: newShotData,reset() {this.data.y = startYthis.data.speed = 0 //重置时候,速度为0表示不动shot?.reset()},redraw(data) {const { canvas, topBar } = data//其中y就是移动位置,通过改变这个值可实现上下移动射击let { y, speed } = this.datalet x1 = canvas.width / 2let y1 = y + centerScopeData.y + centerScopeData.rlet y2 = y1 + shot.data.linerLength//调用对象的绘制方法shot.redraw(x1, y1, x1, y2)if (speed > 0) {//当y的值还是大于0时,说明它还没有钉到靶中心,继续移动if (y >= (topBar?.bottom || 0)) {this.data.y -= speedreturn}//执行到这里,说明它刚刚钉上靶中心,就设置它在靶中心的角度以及偏移位置shot.data.angle = 90 - shotsData.angle - shotsData.offset * 10//这里用遍历,逐个判断这个针箭尾部的圆是否与已钉上的针箭相碰for (let i = 0; i < shotsData.shots.length; i++) {let item = shotsData.shots[i]if (item.x <= 0 || item.y <= 0) continue//计算两一个圆心之间的距离,这里用到数学的勾股定理公式:直角三角形三边关系let c = Math.sqrt(Math.pow(x1 - item.data.x, 2) + Math.pow(y2 - item.data.y, 2))//如果两个圆相交(互相碰到),那么就游戏结束if (c <= item.data.r + shot.data.r) {//调用游戏引擎的停止方法engine.stop()//记录最高分app.setMaxScope(shotsData.shots.length)//弹出对话框提示游戏结束that.showModalForGameEnd()return}}//将新的针箭添加到shotsData.shots.push(shot)//重置一下this.data.y = startYthis.data.speed = 0//重新添加shot = that.addNewShot()}}
})

💡直角三角形三边关系:假设直角的两边长是a和b,那么斜边长 c²=a²+b²

靶心中心

这里添加靶心的对象,代码如下

engine.addForeObject({data: centerScopeData,reset() {Object.assign(this.data,{initTime: Date.now()})},redraw(data) {const { canvas, context: ctx, topBar } = datalet { x, y, r, initTime } = this.datalet paddingTop = topBar?.bottom || 0//绘制靶心ctx.strokeStyle = 'black'ctx.fillStyle = 'red'ctx.lineWidth = 1ctx.beginPath()ctx.arc(x, y + paddingTop, r, 0, Math.PI * 2)ctx.fill()ctx.stroke()//绘制得分ctx.fillStyle = 'white'ctx.textAlign = 'center'ctx.baseTextAlign = 'middle'ctx.font = ctx.font.replace(/^\d+/, 38)ctx.fillText(`得分${shotsData.shots.length}`, x, y + paddingTop)//绘制计时let timer = Math.trunc((Date.now()-initTime)/1000)ctx.font = ctx.font.replace(/^\d+/, 32)ctx.fillText(`${timer}`, x, y + paddingTop + 48)}
})

就连这个方法addNewShot()实现也很简单,代码如下

/**
*	添加新的针箭对象
*/
addNewShot(){const { gameData, engine } = this//调用引擎创建的一个对象方法    let shot = engine.createObject({//...return shot
}

在这里会发现,引擎添加的游戏对象,都有data,reset(),redraw()的属性和方法,都看懂了吧,
实现过程都写在游戏引擎模块文件里,怎样实现的呢,对此感兴趣的可以看看项目源码研究看看

开始游戏

调用方法restart(),整个游戏就能运行起来了,如下代码
代码如下

/**
*	重新开始游戏
*/
restart(){const { engine } = this//重置游戏对象engine.reset()//运行游戏engine.run()//重置游戏结束状态this.isGameEnd = false
}

游戏引擎会处理其它实现的细节,基本的绘制流程无需我们操心,这样用实现起来会方便一些,

游戏项目

写完整个项目,就可以运行测试了,

运行效果动图如下,点击屏幕任意位置就可以发射
请添加图片描述
想看项目源码 请点击这里,在资源一栏下有个名称为 见缝插针游戏源码,

请放心下载,感谢支持❤

如果是在手机上浏览此文章的,可能看不到资源一栏下的项目源码,在电脑上浏览器看就能看到了

tu2

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

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

相关文章

css实现div倾斜效果

效果如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head> <style> *{margin:0;padding: 0;} .box1{margin:30px 100px;width:100px;height:200px;background:blueviolet;} …

cmd打开idea

当我们用idea打开一个项目的时候&#xff0c;有时候这个项目目录是有的&#xff0c;但是用idea的open却找不到&#xff0c;有时候我要重新关闭窗口&#xff0c;再open好多次才有 于是我现在使用命令打开&#xff0c;先把idea安装路径的bin目录放在path里面 然后cd到项目路径&…

Unreal Engine 学习笔记 (3)—— 导入资源

1.导入FBX文件 打开系统文件管理器按下鼠标左键拖动fbx文件到UE编辑器中松开鼠标左键在弹出对话框FBX导入选项页面中&#xff0c;选择对应的骨骼 重定向骨骼 拖动UE4的walk_strafe_back.fbx文件到UE5编辑器中 在弹出的FBX导入选项对话框中选择UE4对应的骨骼 使用重定向资产…

什么是微服务自动化测试?

什么是微服务&#xff1f; 微服务 - 也称为微服务架构 - 是一种构建方式&#xff0c;它将应用程序构建为松散耦合服务的集合&#xff0c;具有完整的业务功能。微服务架构允许连续交付/部署大型复杂应用程序。本文将概述自动微服务测试工具和最佳实践。 它还使组织能够发展其技…

原生微信小程序学习之旅(一) -来简单的使用

文章目录 取消导航栏标头组件创建添加Component组件接收传入的数据 页面创建(Page)关于tabBartabBar自定义样式 轮播图轮播图指示点样式改变 微信小程序快速获取用户信息路由跳转获取url路径中的参数 bindtap(click)传参wx:if编写用户登陆关于默认工程目前的获取方法尝试一下服…

【Python】二维码和条形码的识别

我主要的问题就在于无法识别图片 注意事项&#xff1a; 1、从文件中加载图像的时候注意图片尽量用英文来命名&#xff0c;因为中文无法识别到图片 2、使用绝对地址的时候要用两个双斜杠&#xff0c;因为用一个会被识别为Unicode 转义&#xff0c;但是并没有后续的合法 Unico…

回归预测 | Matlab实现PCA-PLS主成分降维结合偏最小二乘回归预测

回归预测 | Matlab实现PCA-PLS主成分降维结合偏最小二乘回归预测 目录 回归预测 | Matlab实现PCA-PLS主成分降维结合偏最小二乘回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现PCA-PLS主成分降维结合偏小二乘回归预测&#xff08;完整源码和数据) 1.输…

机器学习——逻辑回归

目录 一、分类问题 监督学习的最主要类型 二分类 多分类 二、Sigmoid函数 三、逻辑回归求解 代价函数推导过程&#xff08;极大似然估计&#xff09;&#xff1a; 交叉熵损失函数 逻辑回归的代价函数 代价函数最小化——梯度下降&#xff1a; ​编辑 正则化 四、逻辑…

pyqt环境搭建

创建虚拟环境 # 用管理员身份运行 conda create --prefixE:\Python\envs\pyqt5stu python3.6 # 激活虚拟环境 conda activate E:\Python\envs\pyqt5stu # 退出虚拟环境 conda deactivate安装包 pip install PyQt5 -i https://pypi.douban.com/simple pip install PyQt5-tools…

关于maven读取settings.xml文件的优先级问题

今天在IDEA中配置maven的setting.xml文件路径指向的.m2路径下的setting_a.xml文件&#xff0c;同时&#xff0c;我的maven3.6.3也放在.m2中。 [1] .m2文件夹 [2] apache-maven-3.6.3文件夹 然后&#xff0c;在IDEA中打包发布时发现&#xff0c;无论如何都读取不到指定的settin…

Sectigo SSL

Sectigo&#xff08;前身为ComodoCA&#xff09;是全球在线安全解决方案提供商和全球最大的证书颁发机构。为了强调其在SSL产品之外的扩张&#xff0c;Comodo在2018年更名为Sectigo。新名称减少了市场混乱&#xff0c;标志着公司向创新的全方位网络安全解决方案提供商过渡。 S…

Python基础入门例程52-NP52 累加数与平均值(循环语句)

最近的博文&#xff1a; Python基础入门例程51-NP51 列表的最大与最小(循环语句)-CSDN博客 Python基础入门例程50-NP50 程序员节&#xff08;循环语句&#xff09;-CSDN博客 Python基础入门例程49-NP49 字符列表的长度-CSDN博客 目录 最近的博文&#xff1a; 描述 输入描…

FPGA运算

算数运算中&#xff0c;输入输出的负数全用补码来表示&#xff0c;例如用三位小数位来表示的定点小数a-1.625和b-1.375。那么原码分别为a6b‘101101, b6b101011, 补码分别是a6’b110011&#xff0c;b6‘b110101&#xff1b; 如果想在fpga中实现a*b&#xff0c;则需要将a和b用补…

MySQL:日志系统

目录 概述错误日志&#xff08;error log&#xff09;慢查询日志&#xff08;slow query log&#xff09;一般查询日志( general log )中继日志&#xff08;relay log&#xff09;Buffer Pool 缓存回滚日志&#xff08;undo log)概述undo log 作用undo log 的存储机制Undo log …

万能在线预约小程序系统源码 适合任何行业在线预约小程序+预约到店模式 带完整的搭建教程

大家好啊&#xff0c;源码小编又来给大家分享啦&#xff01;随着互联网的发展和普及&#xff0c;越来越多的服务行业开始使用在线预约系统以方便客户和服务管理。例如&#xff0c;美发店、健身房、餐厅等都可以通过在线预约系统提高服务效率&#xff0c;减少等待时间&#xff0…

计算机课设python项目matplotlib数据可视化分析代码以及数据文档+自动化selenium实现boss网站爬虫代码

这是一个数据分析可视化课程的结课作业设计&#xff0c;受人所托写的&#xff0c;现在分享出来&#xff0c;有需要的同学自取哈&#xff0c;以下是文件目录&#xff0c;包括数据分析和爬虫代码都有&#xff0c;下载下来当一个demo也还是不错的&#xff0c;这篇博客就是文档里的…

博客积分上一万一千了

博客积分上一万一千了 充满自信&#xff0c;继续前进。

《QT从基础到进阶·十八》QT中的各种鼠标事件QEvent

1、界面标题栏事件&#xff1a; NonClientAreaMouseButtonPress 标题栏点击事件 NonClientAreaMouseButtonRelease 标题栏释放事件 bool CustomPopDialog::event(QEvent* event) {switch (event->type()){case QEvent::MouseButtonRelease://Event of mouse releasing wind…

移动硬盘和u盘的区别哪个好 移动硬盘和u盘有啥区别

在数字时代的今天&#xff0c;数据存储已经成为我们生活中的重要一环。当我们需要移动、备份或传输大量数据时&#xff0c;常常会不知道是选择移动硬盘还是U盘。其实&#xff0c;对于许多人来说&#xff0c;移动硬盘和U盘之间的区别并不清晰。下面我们就来看移动硬盘和u盘的区别…

web3 React Dapp书写订单 买入/取消操作

好 上文web3 前端dapp从redux过滤出 (我创建与别人创建&#xff09;正在执行的订单 并展示在Table上中 我们过滤出了 我创建的 与 别人创建的 且 未完成 未取消的订单数据 这边 我们起一下 ganache 环境 ganache -d然后 我们项目 发布一下智能合约 truffle migrate --reset然…