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

news2024/11/22 16:18:43

以前玩过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即可;

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

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

请添加图片描述

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

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

相关文章

四. 基于环视Camera的BEV感知算法-BEVDet

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…

【Java】智慧工地系统:让建筑行业管理更简单

概述 智慧工地管理平台面向房建、能源、交通各类工地的管理者&#xff0c;通过AI视频、物联感知技术对工地场景中的施工机械、建筑材料、施工规范、施工环境监管、完善施工现场项目管控。实现项目管控、特种设备管理、绿色施工、工地巡检等业务功能&#xff0c;沉淀工地监管数…

6.鸿蒙app_hap_DevEco如何真机调试模式_app安装在手机中

真机调试 手机》设置》关于手机》HarmonyOS版本》软件版本&#xff0c;连续单击10次启动开发者模式 然后&#xff1a;设置》系统和更新》开发人员选项》打开USB调试功能。 电脑USB连接手机&#xff0c;手机USB连接类型&#xff0c;传文件&#xff08;不要选择仅充电&#xf…

CAD 审图意见的导出

看图的时候喜欢在图上直接标注意见&#xff0c;但是如果还要再把意见一行一行的导出到word里面就很麻烦&#xff0c;在网上看了一个审图软件&#xff0c;报价要980&#xff0c;而且那个审图意见做的太复杂了。 我的需求就是把图上标的单行文字和多行文字直接导出来就行&#x…

MybatisPlus进阶,UUID VS SnowFlake(雪花算法)

目录 一、什么是MybatisPlus 为什么要学MybatisPlus&#xff1f; 特性&#xff1a; 二、快速入门 2.1快速初始化一个空的spring boot 项目 2.2配置依赖 2.3配置(连接数据库) 2.4在spring boot启动类中添加MapperScan注解&#xff0c;扫描Mapper文件夹&#xff1a; 2.5…

自动驾驶学习笔记(二十)——Planning算法

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 参考线平滑 双层状态机 EM Planner …

Sherlock:社交媒体账号搜索工具 | 开源日报 No.111

sherlock-project/sherlock Stars: 45.1k License: MIT 这个项目是一个社交媒体账号搜索工具&#xff0c;名为 Sherlock。它可以通过用户名在不同的社交网络上追踪用户的账号。 支持单个或多个用户搜索提供 Docker 容器化部署方式开放源代码并欢迎贡献者参与开发包含详细测试…

LeetCode(62)删除排序链表中的重复元素 II【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 删除排序链表中的重复元素 II 1.题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1…

2020年第九届数学建模国际赛小美赛D题石头剪刀游戏与合作解题全过程文档及程序

2020年第九届数学建模国际赛小美赛 D题 石头剪刀游戏与合作 原题再现&#xff1a; 小时候你可能至少玩过几次石头剪刀游戏。在这个游戏中&#xff0c;你几乎有三个选择&#xff0c;每一个都有一个项目要打败&#xff0c;一个项目输给。石头打败剪刀&#xff0c;剪刀剪纸和布覆…

二分查找算法的概念、原理、效率以及使用C语言循环和数组的简单实现

二分查找的概念 二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;它是一种效率较高的查找方法。但是&#xff0c;折半查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字有序排列。 实现原理 首先&#xff0c;假设表中元素是按升序…

FinalShell的下载、安装及基本使用

一&#xff1a;引言 FinalShell 是一体化的的服务器,网络管理软件,不仅是 ssh 客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 主要特性&#xff1a; 1.多平台支持 Windows,macOS,Linux 2.多标签,批量服务器管理. 3.支持登录 ssh 和 Windows 远程桌面. 4.漂亮的…

elementUi表单验证 上一下两项都有必填校验,添加v-if后失效

需在el-form-item 在不一样的key区分就在页面会生效

12、ble_mesh_vendor_model 服务端,自定义模型

1、初始化流程&#xff0c;存储初始化&#xff0c;nvs擦除&#xff0c; board_init();初始化LED。 2、bluetooth_init();ble协议栈初始化 3、ble_mesh_get_dev_uuid(dev_uuid);//获取设备uuid加载到mac&#xff0c;后两位dev uuid 4、ble_mesh_init();//ble mesh协议栈初始化。…

springboot229基于Spring Boot的企业员工薪酬关系系统的设计

springboot229基于Spring Boot的企业员工薪酬关系系统的设计 源码获取&#xff1a; https://docs.qq.com/doc/DUXdsVlhIdVlsemdX

2023年度佳作:AIGC、AGI、GhatGPT、人工智能大语言模型的崛起与挑战

目录 前言 01 《ChatGPT 驱动软件开发》 内容简介 02 《ChatGPT原理与实战》 内容简介 03 《神经网络与深度学习》 04 《AIGC重塑教育》 内容简介 05 《通用人工智能》 目  录 前言 2023年是人工智能大语言模型大爆发的一年&#xff0c;一些概念和英文缩写也在这一…

【MyBatis-Plus】常用的插件介绍(乐观锁、逻辑删除、分页)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于MyBatis-Plus的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.为什么要使用MyBatis-Plus中的插…

day01-报表技术POI

前言 报表[forms for reporting to the higher organizations]&#xff0c;就是向上级报告情况的表格。简单的说&#xff1a;报表就是用表格、图表等格式来动态显示数据&#xff0c;可以用公式表示为&#xff1a;“报表 多样的格式 动态的数据”。 1、开发环境搭建 功能说…

SQLMAP的使用(rails 为例)

1.启动一个项目&#xff0c;例如rails学习的项目&#xff0c;修改config/database.yml&#xff0c; 假设来一个接口&#xfeff; class YourModel::YourController < ApplicationController def test_sqlisql "select * from your_table_name where id " par…

鸿蒙开发组件之Web

一、加载一个url myWebController: WebviewController new webview.WebviewControllerbuild() {Column() {Web({src: https://www.baidu.com,controller: this.myWebController})}.width(100%).height(100%)} 二、注意点 2.1 不能用Previewer预览 Web这个组件不能使用预览…

配置Nginx解决跨域问题

Nginx 中将前端请求中的所有以 “/apiUrl” 开头的路径代理到 http://192.12.200.101:9813 例如&#xff1a; /apiUrl/login > http://192.12.200.101:9813/login 配置nginx环境 进入Nginx 的配置文件编辑界面: sudo nano /etc/nginx/conf.d/default.conf开始编辑 defaul…