【合成数字】合成类游戏-uniapp项目开发流程详解

2023-12-17 20:38:12

以前玩过2048游戏,从中发现规律,想到跟合成类游戏相似,知道为什么很相似吗,在这里,做一个数字合成游戏玩玩吧,感兴趣的话可以看看,这里给大家讲一讲数字合成游戏的开发过程。

创建项目

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

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

  • 选择新建uni-app项目
  • 使用默认模板
  • Vue版本选择 3

页面布局

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

初始页面

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

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

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

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

游戏页面

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

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

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

<!--pages/game/game.wxml-->
<view class="page">
    <canvas type="2d" id="zs1028_csdn" class="canvas" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd" disable-scroll="{{true}}"/>
</view>

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

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

看着是不是很像2048游戏呢,没错,与其不同的是从数字1开始计算,
实现思路,就是把两个相同的数字合成,如1+1=2,计算规则n+n=2n

游戏逻辑

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

加载模块

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

// pages/game/game.js
import ZS1028_CSDN from '../../utils/zs1028_CSDN.js'
import Gesture from '../../utils/gesture.js'

const app = getApp()

Page({
     //...
    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    async onReady() {
       //...这里处理初始化
    },
    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {
        if(this.timer) clearTimeout(this.timer)
        this.game?.destroy()
    },
    /**
    * 以下是通过canvas的触摸事件来调用
    */
    onTouchStart(e) {...},

    onTouchMove(e) {...},

    onTouchEnd(e) {...},
})

导入的两个模块,想必看过之前笔者发布过文章的读者会有点映像,
Gesture ,是一个处理触摸手势模块,有参考文章 关于手机中的触摸手势操作实现过程详解
ZS1028_CSDN ,是一个游戏引擎框架模块,让游戏实现变得简单;

初始化画布

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

也就是绘制网格,然后绘制一些数字在上面,

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

const { node: canvas, width, height } = await ZS1028_CSDN.query('#zs1028_csdn')
Object.assign(canvas, { width, height })
const game = ZS1028_CSDN.createMiniGameEngine({
      canvas,
     // isTest: true //游戏测试用途
})
this.game = game

初始化游戏数据

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

//游戏状态数据
const gameState = {
    bottom: 38 //游戏标题底部位置
}
//游戏网格数据
const gridsData = {
    grids: [], //游戏网格列表
    cols: 5, //网格列数
    isNew: false, //是否出现新的数字 
}

绘制游戏状态

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

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

const that = this
//初始化游戏标题层
game.initTopBar({
    data: gameState,
    reset() {
    	//重置数据的
        Object.assign(this.data,{
            scope: 0,
            best: app.getMaxScope(),
            timerNum: 300,
        })
    },
    redraw(data) {
        const { canvas, context: ctx, topBar } = data
        let { scope, best, timerNum } = this.data
        //这里绘制游戏标题区域...
    }
})

绘制网格

接下来,绘制出来网格,代码如下

//添加游戏背景层,绘制网格
game.addBgObject({
    data: gridsData,
    reset() {
        const { grids } = this.data
        //...这里重置游戏网格数据
		//添加随机数字到网格
        for(let i=0;i<5;i++){
            this.addRandomGridValue()
        }
    },
    redraw(data) {
        const { canvas, context: ctx, topBar } = data
        let { cols, grids, gridSize, isNew } = this.data
        if (!this.cacheBgImg) {
            //...在这里画背景图片,也就是绘制网格,第一次就要画出来,导出图片,然后就直接用图片绘制来代替
            return
        }
        //...判断一个状态,如果要新的随机位置数字
        if (isNew) {
            this.addRandomGridValue()
            //添加好,就重置一下状态
            this.data.isNew = false
        }
        //这里先绘制背景图片(网格)
        ctx.drawImage(this.cacheBgImg, 0, 0, canvas.width, canvas.height)
        let r = gridSize / 2
        //...这里绘制网格中的数字
        grids.forEach(g => {
            if (g.value < 1) return
            //...绘制数字value
            ctx.fillText(g.value, g.x + g.relX + r, g.y + g.relY + r * 1.1)
            //...这之后就是绘制移动数字动画的,代码虽少,但不好理解
        })
    },
    methods: {
        addRandomGridValue() {
            //...自定义方法,实现添加随机位置的数
        }
    }
})

开始游戏

最后,准备就绪,开始游戏,代码如下

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

重新开始

写重新开始的逻辑很简单,

在开始游戏调用方法restart()里有实现,代码如下

game.reset()
//...其它的初始化逻辑
game.run()

可见,重新开始游戏,只需调用游戏对象game的两个方法就可以了

触摸事件

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

用到了处理手势的模块,这实现会变得简单,

开始触摸时,记录下按下的点数据,

就是触摸开始点touch1 和移动到最后的点touch2两个,代码如下

onTouchStart(e) {
 if (this.isGameEnd || this.startAnimating) return
    this.touch1 = e.touches[0]
},

onTouchMove(e) {
    if (!this.touch1) return
    this.touch2 = e.touches[0]
},

触摸移动结束时,调用手势模块的方法,就能得出滑动的方向,

这样就知道往哪个方向移动,来处理网格里的一些数字移动,

实现移动的逻辑,加上动画,这会变得复杂一些,

仔细构思一下,就写了出来,代码如下

onTouchEnd(e) {
    if (this.touch1 && this.touch2) {
    	//通过调用模块的方法获取
        let g = Gesture.touchesToG(this.touch1, this.touch2)
        let list = this.scanGrids(g)
        let gs = []
        let isReverse //是否反向排列
        //判断是哪个手势
        switch (g) {
            case Gesture.G.left:
            case Gesture.G.right:
                isReverse = true
                break
            case Gesture.G.up:
            case Gesture.G.down:
                isReverse = false
                break
            default:
                throw new Error('this is error')
        }
        //遍历一遍,将可移动的数字记录到gs列表中
        list.forEach(arr => gs.push(...this.calcMoveGrids(arr, isReverse)))
        //这里列表若不为空,就有移动的数字在里面
        if (gs.length > 0) {
            this.startAnimating = true
            //开始下一个的移动数字动画 
            this.nextAnimation(list,gs,isReverse,1)
        } else {
        	//没有可移动的,可能有存在两个相邻的相同数字,需要调用合并数字的方法
            let scope = this.compositeNumber(list, isReverse)
            //当scope大于0,也就是有得分,表示合并成功,就执行移动数字动画
            if (scope > 0) {
                this.startAnimating = true
                //开始下一个的移动数字动画
                this.nextAnimation(list,gs,isReverse)
            }
        }
    }
    //最后,别忘了重置触摸点数据
    this.touch1 = undefined
    this.touch2 = undefined
},

别法算法想那么复杂,只要思路是对的,能实现出来的就没问题

游戏测试

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

看看合成数字的游戏效果吧,运行动图如下
请添加图片描述

想要改成2048游戏一样是可以的,只需要在新建的随机位置数字代码里修改12即可;

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

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

请添加图片描述

文章来源:https://blog.csdn.net/zs1028/article/details/134867885
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。