一、明确玩法
演示视频:https://www.bilibili.com/video/BV1ig41127T3。
开源地址:https://gitee.com/cheng-wan-orz/olgh。
- 通过点击选择对应的目标
- 点击目标后界面中消失,移动到栏中
- 当目标连续凑够三个(左或右),进行消除
- 第一层消除后显示出第二层
- 当储存栏满了后失败
二、简易逻辑搭建
因为这个内容是半个下午实现的(拖到现在才发而已),仅仅搭建了框架,若有大的问题也请大家谅解,该内容仅做学习使用。
(1)确定层数、栏目数以及种类
在这里我选择使用两层、4种类型,总个数36个,界面选择6*6的方格,下面存储的格数选择为6个(PS:本来打算3层8种60个,后来嫌麻烦)。
(2)建立类型标志
这里选择使用单维36数组,代表总数36个,其中1-4代表四种类型,此时将数组进行打乱。
此时经过打乱后得到一个随机的数组排序,即实现完全随机的游戏体验。
(3)建立层次
在得到打乱后的数组后需要进行分层,此时使用随机数。
得到第一层是[0,10]+10,即得到一个10-20的数作为第一层的个数。
(4)位置排序
在确定第一层和第二层数目以及整体类型数组后,需要考虑怎么样进行随机位置的摆放,单纯的按数排序是我们不希望看到的,这里引入坐标的概念,因为我使用的是6*6的单元格,这里创建一个36成员的数组。
此时进行第一次打乱,同样使用打乱函数。
打乱后即可得到一个乱序的位置排序,此时将第一层的内容进行放入即可。
(5)建立棋盘
在位置和类型确定后建立棋盘。
将上方确定的内容进行导入,此时fisrt_set和Second_set代表两层棋盘的摆放情况。
(6)点击判定
点击判定这里简化为坐标实现(具体实现看下午技术部分),通过6*6单元格的分析,当点击后得到一个XY轴,此时首先判断该层数的XY轴处有没有放置图片,如果有则读取当前点的类型(1-4),并将其消除进入消除判定。
(7)消除判定
当点击到类型后,该图片进入栏目中,此时需要对栏目进行判定,是否出现连续三个的情况,引入一维数组。
当点击判定后,首先判断当前第一位是否存在,没有的话点击的内容成为第一位,有的话成为第二位。
在前两位都存在的情况下,判断前三位是否一致,一致的话消除,不一致的话成为第三位。
当前三位的存在的情况下,判断第二第三和点击的是否一致,不一致判断第一第二和点击的项目是否一致,都不一致则成为第四位,一致则消除。
当栏目数为5的情况下,且点击项目左右都不一致,则游戏失败(判断程序如下)。
(8)第一层完成
每次操作后都判断一次棋盘数组是否都为0,如果都为0的话代表当前层数被清空,进入下一层。
三、OpenHarmony程序编写
我们主要使用到了Canvas画布组件:https://docs.openharmony.cn/pages/v3.2Beta/zh-cn/application-dev/reference/arkui-ts/ts-components-canvas-canvas.md/。
Canvas
说明: 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
提供画布组件,用于自定义绘制图形。
(1)主要函数
drawImage
drawImage(image: ImageBitmap | PixelMap, dx: number, dy: number): void
drawImage(image: ImageBitmap | PixelMap, dx: number, dy: number, dWidth: number, dHeight: number): void
drawImage(image: ImageBitmap | PixelMap, sx: number, sy: number, sWidth: number, sHeight: number, dx: number, dy: number, dWidth: number, dHeight: number):void
进行图像绘制。
- 参数
参数 | 类型 | 必填 | 默认值 | 描述 |
image | ImageBitmap或PixelMap | 是 | null | 图片资源,请参考ImageBitmap或PixelMap。 |
sx | number | 否 | 0 | 裁切源图像时距离源图像左上角的x坐标值。 |
sy | number | 否 | 0 | 裁切源图像时距离源图像左上角的y坐标值。 |
sWidth | number | 否 | 0 | 裁切源图像时需要裁切的宽度。 |
sHeight | number | 否 | 0 | 裁切源图像时需要裁切的高度。 |
dx | number | 是 | 0 | 绘制区域左上角在x轴的位置。 |
dy | number | 是 | 0 | 绘制区域左上角在y 轴的位置。 |
dWidth | number | 否 | 0 | 绘制区域的宽度。 当绘制区域的宽度和裁剪图像的宽度不一致时,将图像宽度拉伸或压缩为绘制区域的宽度。 |
dHeight | number | 否 | 0 | 绘制区域的高度。 当绘制区域的高度和裁剪图像的高度不一致时,将图像高度拉伸或压缩为绘制区域的高度。 |
clearRect
clearRect(x: number, y: number, w: number, h: number): void
删除指定区域内的绘制内容。
- 参数
参数 | 类型 | 必填 | 默认值 | 描述 |
x | number | 是 | 0 | 指定矩形上的左上角x坐标。 |
y | number | 是 | 0 | 指定矩形上的左上角y坐标。 |
width | number | 是 | 0 | 指定矩形的宽度。 |
height | number | 是 | 0 | 指定矩形的高度。 |
fillRect
fillRect(x: number, y: number, w: number, h: number): void
填充一个矩形。
- 参数
参数 | 类型 | 必填 | 默认值 | 说明 |
x | number | 是 | 0 | 指定矩形左上角点的x坐标。 |
y | number | 是 | 0 | 指定矩形左上角点的y坐标。 |
width | number | 是 | 0 | 指定矩形的宽度。 |
height | number | 是 | 0 | 指定矩形的高度。 |
(2)游戏开局渲染
导入背景图片:
(3)设置单元格
我的模拟器参数为:
所以设置单元格大小为100*100,图片大小为80x80,同时需要确定下方的栏的坐标位置(可自行摸索)。
(4)开局两层摆放
由第二部分内容确定逻辑,即可实现游戏初始的渲染部分。
(5)点击判定
该部分是引入onTouch函数,得到对应的XY轴坐标,再进行分析得到6*6单元格的坐标进行判定。
事件
名称 | 是否冒泡 | 功能描述 |
onTouch(callback: (event?: TouchEvent) => void) | 是 | 触摸动作触发该方法调用,event参数见TouchEvent介绍。 |
得到坐标后需要判断是否为单元格区域,如果超出该区域则不进行响应。
(6)第二层绘制
当通过第一层时,因为在第一层和第二层之间有一个灰色图层。需要进行一次全局刷新,此时通过提前记录的第一次生成的数据,进行一次更新即可。
(7)游戏成功
如果正确游戏且通过的话,会提示游戏成功(因为有较大的随机性,不一定一定成功哦,下一期会教大家怎么使用背景音乐!)