【飞翔的鸟】飞行游戏

您所在的位置:网站首页 小鸟项目 【飞翔的鸟】飞行游戏

【飞翔的鸟】飞行游戏

2023-12-28 03:19| 来源: 网络整理| 查看: 265

小时候玩过的飞行游戏,叫什么名字来着,通过点击操作控制煽动翅膀来持续飞行,躲避障碍物,有多远就飞多远吧,现在想起来,其中的实现原理非常简单,感兴趣的话来一起看看,这里给大家讲一讲飞翔的小鸟游戏的开发过程。

文章目录 创建项目页面布局初始页面游戏页面设置横屏 游戏逻辑加载模块初始化画布初始化游戏数据绘制游戏状态绘制小鸟绘制障碍物开始游戏触摸事件 游戏测试

创建项目

这里用HBuilderX开发工具来创建一个uniapp项目,

例如项目名填写uniapp_FlapperBird,依次选择如下图 在这里插入图片描述

选择新建uni-app项目使用默认模板Vue版本选择 3 页面布局

新建好项目,会看到自动创建了一个初始页面文件,

初始页面

文件位置在pages/index/index.vue,打开看看,

在页面布局中,对应的template标签里添加一个按钮组件,按钮名叫进入游戏,

然后在script标签里,添加一个按钮点击方法,实现打开游戏页面,

打开页面的代码很简单,自己能写出来吧,这里就不展开讲,

游戏页面

需要自己创建一个游戏页面,

页面文件在pages/game/game.vue,打开接着写,

在页面布局中,对应的template标签里添加,内容如下

就这么简单,只放一个canvas组件即可,组件的一些属性不用说能看懂吧

写好后,要做出运行的游戏页面效果,就像如下图这样 在这里插入图片描述

这是在游戏开始时,其它的物品还没有出现

设置横屏

竖屏这样玩是不是视野变窄了点,可以设置横屏的,

把项目根目录下的文件pages.json打开,

添加一个属性pageOrientation设置,代码如下

{ //... "globalStyle": { //... "pageOrientation": "landscape" }, }

不知道这样设置有没有效果,H5版好像不行吧,手机浏览器上是跟随系统横屏的

游戏逻辑

接下来,在script标签里,写游戏逻辑,

加载模块

开始写初始化代码,先加载游戏模块,添加代码如下

// pages/game/game.js import ZS1028_CSDN from '../../utils/zs1028_CSDN.js' const app = getApp() Page({ //... /** * 生命周期函数--监听页面初次渲染完成 */ async onReady() { //...这里处理初始化 }, /** * 生命周期函数--监听页面卸载 */ onUnload() { this.game?.destroy() }, /** * 以下是通过canvas的触摸事件来调用 */ onTouchStart(e) {...}, })

导入的一个模块 ZS1028_CSDN ,是一个游戏引擎框架模块,用上它让游戏实现变得简单; 话说这个游戏模块,是通过一层又一层的绘制来实现的,代码总才182行,这么少,这一看很快就读完; 继续往下看,就能大概知道怎样绘制游戏了

初始化画布

游戏大致的思路呢,是要先把画布初始化,然后绘制出来游戏画面,

就在onReady()方法里写,画布初始化的逻辑,代码如下

const { width, height } = await ZS1028_CSDN.query('#zs1028_csdn') const canvas = { width, height, getContext() { return uni.createCanvasContext('zs1028_csdn') }, //... } const game = ZS1028_CSDN.createMiniGameEngine({ canvas, // isTest: true //游戏测试用途 }) this.game = game 初始化游戏数据

继续写下去,初始化游戏数据,代码如下,

//游戏状态数据 const gameState = { bottom: 50, //绘制游戏状态的底边间距 timeCount: 0, //计时 scope: 0, //计分 } //小鸟的数据 const birdData = { width: 60, //定义小鸟宽度 imgIndex: 0, //图片索引(至少要2张图片,才能绘制动画效果) climb: 0 //点击后,小鸟飞行上升的高度 } Object.assign(birdData, { height: birdData.width / 1.4 //按照图片尺寸计算出小鸟的高度 }) //障碍物的数据 const barrierData = { width: birdData.width * 1.1, 宽度 list: [] //存放的障碍物列表 } Object.assign(barrierData, { minWidth: barrierData.width * 0.86, //计算最小的宽度,用于绘制 distance: barrierData.width * 3 //计算上一个障碍物与下一个的间距 }) 绘制游戏状态

接下来,调用游戏对象的绘制过程,

这是绘制游戏标题,显示游戏状态,代码如下

const that = this //绘制游戏标题层,在屏幕上面显示游戏状态 game.initTopBar({ data: gameState, //把定义的游戏状态数据传入其中 //重置事件 reset() { Object.assign(this.data, { timeCount: 0, //计时重置 scope: 0, //计分重置 maxScope: app.getMaxScope() //最高分 }) }, //重绘事件 redraw(data) { const { canvas, context: ctx } = data const { timeCount, scope, maxScope, bottom } = this.data //...这里处理更新计时timeCount //以下是绘制标题 ctx.textAlign = 'center' ctx.font = `18px sans-serif` ctx.strokeStyle = '#ffffff' let text = `⏰x${timeCount}s 🪙x${scope} 🏆x${maxScope}` ctx.strokeText(text, canvas.width * 0.5, 30) ctx.fillText(text, canvas.width * 0.5, 30) } }) 绘制小鸟

接下来,绘制一只飞翔的鸟,在其上层的中间位置绘制,代码如下

//添加游戏前景层,绘制一只鸟 game.addForeObject({ data: birdData, reset() { //...这里重置小鸟的数据,放屏幕中间位置 }, redraw(data) { const { canvas, context: ctx } = data //调用绘制小鸟的方法 this.drawBird(ctx) }, methods: { drawBird(ctx) { let { x, y, width, height, imgIndex, climb } = this.data if (climb > 0) { //... y -= 2 //小鸟在上升 } else { y += 2 //小鸟在滑翔 } // 判断图片索引,决定让使用那个图片显示小鸟 switch (imgIndex) { //... default: ctx.drawImage('./../../static/tu_03.png', x, y, width, height) } // 调用碰撞检测方法,如果碰到了障碍物,游戏就会结束 if (this.crashDetection(y)) { game.stop() that.isGameEnd = true app.setMaxScope(gameState.scope) //...这里执行弹出游戏结束提示即可 } // 记录时间变化 let nowTime = Date.now() // 判断时间差,如果大于300毫秒就替换小鸟图片 if (!this.preTime || (nowTime - this.preTime) > 300) { //...改变小鸟的图片,实现煽动翅膀动画效果 this.data.imgIndex = (imgIndex + 1) % 2 } //...最后,记得更新一下小鸟变化后的数据 }, crashDetection(y) { //...这里实现碰撞检测 for (let i = 0; i data: barrierData, //传入障碍物的数据 reset() { this.data.list.length = 0 //重置就清空列表 this.addBarrier() //这里执行添加一个障碍物方法 }, redraw(data) { const { canvas, context: ctx } = data const { list, width, distance } = this.data list.forEach((item, index) => { //障碍物上下对称出现 //先绘制上面的障碍物 if (item.y > 0) this.drawBarrier(ctx, item.x, item.y) //再计算间距,绘制出下面的障碍物 if (item.y + item.distance 0) { if (list[0].x + width //每隔一段距离,就出现一个 this.addBarrier() } } }, methods: { drawBarrier(ctx, x, y, isDown = false) { //...这里实现绘制障碍物即可,isDown是绘制下面的,否则绘制上面 }, addBarrier() { //...这里实现添加新的障碍物数据 this.data.list.push({...}) //数据属性y和distance是随机变化的 } } }) 开始游戏

初始化都写好了,最后要保存好数据,代码如下

//将初始化数据存放好 this.gameData = { gameState, barrierData, birdData } //调用此方法开始游戏 this.restart()

那游戏开始了吗,看方法restart()代码是怎么样的

const { game } = this this.isGameEnd = false game.reset()

这里发现,没有调用game.run()方法,因此,游戏还没有运行起来

触摸事件

接下来,处理画布canvas触摸事件,让游戏与玩家交互,

开始触摸时,改一下小鸟的数据即可,

就通过触摸开始事件来处理,代码如下

onTouchStart(e) { if (this.isGameEnd) return const { birdData } = this.gameData birdData.climb = 20 //改变这个属性值,小鸟就会上升的 const { game } = this //如果游戏没有运行,这里执行一下就开始游戏了 if (!game.isRun()) game.run() }, 游戏测试

写到这里,基本上就可以运行测试玩玩了,

看看飞翔的小鸟游戏运行效果吧,运行动图如下请添加图片描述

游戏里有用了小鸟图片,图片是可以自己替换的, 替换直升机图片飞行吧,反正游戏体验效果都是一致的; 还没有背景音呢,想要就自己找个音乐文件加上吧

想要项目源码在点这里查看下载,或者直接点这里搜索:飞翔的鸟,在本博客站内请放心下载,感谢支持!

可能手机上看不到,请改用电脑浏览器查看; 如果搜索不到,只能在资源一栏慢慢找了(太多了不好找 )

请添加图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3