文档开发者中心
我的

#HarmonyOS挑战赛第三期#1024一起玩专注游戏

一, 前言

       1024一起专注游戏是在屏幕上画上N x N个方格(如4x4共16个),格子内任意填写上从1开始顺序生成的数字(如1~16共16个数字)。游戏时,要求玩家用手指按从小到大(如1~16)的顺序依次指出其位置,按完所有数字后,显示所用的时间(秒)。所用时间越短,注意力水平越高。能够培养注意力集中、分配、控制能力;拓展视幅;加快视频;提高视觉的稳定性、辨别人、定向搜索能力。此游戏为最简单,最有效也是最科学的注意力训练方法。寻找目标数字时,注意力是需要极度集中的,把这短暂的高强度的集中精力过程反复练习,大脑的集中注意力功能就会不断的加固,提高。注意水平越来越高。

       同时,1024一起专注游戏使用了鸿蒙分布式协同技术,在训练小孩子专注力和耐力时,大人也可以一起陪伴训练,只要两台鸿蒙系统手机或一台手机一台平板,大人,小孩就可以同时一起在玩一个游戏,比如大人在其中一台手机上按了一部份小数字,然后点击分布式协同图标,拉起另一台手机的1024一起专注游戏,小孩可以接着按大人没有按完的数字,最终显示出所用的时间。

二, 实现效果

       开发工具环境下视频:https://www.bilibili.com/video/BV1B34y1m7M5?spm_id_from=333.999.0.0

       手机+手机环境下视频:https://www.bilibili.com/video/BV1kh411b7QM?spm_id_from=333.999.0.0

       手机+平板环境下视频:https://www.bilibili.com/video/BV1ov411M7sq?spm_id_from=333.999.0.0

1634612726842.gif  1024_game.jpg

三, 创建工程

     在这当作你已经安装好最新版本DevEco-Studio开发工具, 点击File -> New -> New Project... 弹出Create HarmonyOS Project窗口, 这里我选择空白Java模板创建, 上一个视频播放实例是用JS写的界面,这个游戏界面就用Java来写,还是JS写界面快,调试也快些.

image.png

image.png  image.png

四, 主界面开发

     在展示源代码之前,先介绍一下使用到了JAVA哪些组件:DirectionalLayout, TableLayout, DependentLayout, Button, Image, Text, ListContainer, CommonDialog,通过查看Java UI参考文档,就可以做出你喜欢的应用了。 

     先介绍公共类Java代码,有了这些公共类,以后做类似功能的应用,可以直接复制公共类文件可以使用:

LogUtil 日志打印类:

收起
自动换行
深色代码主题
复制

public class LogUtil { private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, "1024Game"); private static final String LOG_FORMAT = "%{public}s: %{public}s"; private LogUtil() { } public static void debug(String className, String msg) { HiLog.debug(LABEL_LOG, LOG_FORMAT, className, msg); } public static void info(String className, String msg) { HiLog.info(LABEL_LOG, LOG_FORMAT, className, msg); } public static void info(Class<?> classType, final String format, Object... args) { String buffMsg = String.format(Locale.ROOT, format, args); HiLog.info(LABEL_LOG, LOG_FORMAT, classType == null ? "null" : classType.getSimpleName(), buffMsg); } public static void error(String tag, String msg) { HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg); }}

SelectDeviceDialog设备选择对话框:

收起
自动换行
深色代码主题
复制

public class SelectDeviceDialog { private static final int DIALOG_WIDTH = 840; private static final int DIALOG_HEIGHT = 900; private CommonDialog commonDialog; public SelectDeviceDialog(Context context, List<DeviceInfo> devices, SelectResultListener listener) { initView(context, devices, listener); } private void initView(Context context, List<DeviceInfo> devices, SelectResultListener listener) { // 创建一个公共对话框 commonDialog = new CommonDialog(context); // 设置对齐方式居中 commonDialog.setAlignment(LayoutAlignment.CENTER); // 设置对话框尺寸 commonDialog.setSize(DIALOG_WIDTH, DIALOG_HEIGHT); // 设置对话框自动关闭 commonDialog.setAutoClosable(true); // 加载XML布局文件 Component dialogLayout = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_select_device, null, false); // 设置对话框内容 commonDialog.setContentCustomComponent(dialogLayout); // 查找到列表容器 if (dialogLayout.findComponentById(ResourceTable.Id_list_devices) instanceof ListContainer) { // 获取列表容器对象 ListContainer devicesListContainer = (ListContainer) dialogLayout.findComponentById(ResourceTable.Id_list_devices); // 设备列表适配器 DevicesListAdapter devicesListAdapter = new DevicesListAdapter(devices, context); // 设置设备列表容器项提供者 devicesListContainer.setItemProvider(devicesListAdapter); // 设置设备列表项单击事件 devicesListContainer.setItemClickedListener((listContainer, component, position, id) -> { // 回调选择的设备信息 listener.callBack(devices.get(position)); // 关闭对话框 commonDialog.hide(); }); } dialogLayout.findComponentById(ResourceTable.Id_cancel).setClickedListener(component -> { // 关闭对话框 commonDialog.hide(); }); } // 显示对话框 public void show() { commonDialog.show(); } /** * 内部接口, 选择设备后回调事件 */ public interface SelectResultListener { void callBack(DeviceInfo deviceInfo); }}

DevicesListAdapter设备列表适配器:

收起
自动换行
深色代码主题
复制

public class DevicesListAdapter extends BaseItemProvider { // 开始下标从0开始 private static final int SUBSTRING_START = 0; // 结束下标为4 private static final int SUBSTRING_END = 4; // 设备信息列表 private List<DeviceInfo> deviceInfoList; // 当前上下文 private Context context; // 带参构造方法 public DevicesListAdapter(List<DeviceInfo> deviceInfoList, Context context) { this.deviceInfoList = deviceInfoList; this.context = context; } @Override public int getCount() { return deviceInfoList == null ? 0 : deviceInfoList.size(); } @Override public Object getItem(int i) { return Optional.of(deviceInfoList.get(i)); } @Override public long getItemId(int i) { return i; } @Override public Component getComponent(int i, Component component, ComponentContainer componentContainer) { // 定义设备视图内部类 ViewHolder viewHolder = null; // 定义组件 Component mComponent = component; // 组件为空时 if (mComponent == null) { // 查找设备列表项布局XML mComponent = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_device_list, null, false); // 初始化设备视图类 viewHolder = new ViewHolder(); // 判断组件布局里是否包含设备名称文本组件 if (mComponent.findComponentById(ResourceTable.Id_device_name) instanceof Text) { // 获取设备列表项布局XML的设备名称文件组件,并赋值给内部类设备视图设备名称属性缓存 viewHolder.devicesName = (Text) mComponent.findComponentById(ResourceTable.Id_device_name); } // 判断组件布局里是否包含设备Id文本组件 if (mComponent.findComponentById(ResourceTable.Id_device_id) instanceof Text) { // 获取设备列表项布局XML的设备Id文件组件,并赋值给内部类设备视图设备Id属性缓存 viewHolder.devicesId = (Text) mComponent.findComponentById(ResourceTable.Id_device_id); } mComponent.setTag(viewHolder); } else { // 如果组件不为空, 并且标签包含内部类设备视图 if (mComponent.getTag() instanceof ViewHolder) { // 从组件标签获取出设备视图 viewHolder = (ViewHolder) mComponent.getTag(); } } // 设备视图不为空时 if (viewHolder != null) { // 设置设备名称内容 viewHolder.devicesName.setText(deviceInfoList.get(i).getDeviceName()); String deviceId = deviceInfoList.get(i).getDeviceId(); deviceId = deviceId.substring(SUBSTRING_START, SUBSTRING_END) + "******" + deviceId.substring(deviceId.length() - SUBSTRING_END); // 设置设备名称Id viewHolder.devicesId.setText(deviceId); } return mComponent; } /** * 内部类, 设备视图 */ private static class ViewHolder { // 设备名称 private Text devicesName; // 设备Id private Text devicesId; }}

MainAbilitySlice主界面功能讲解 :

       主界面主要功能就是用表格布局生成3x3, 4x4, 5x5, 6x6, 7x7, 8x8, 9x9 七个按钮,点击后跳转游戏界面,初始化相应的数字按钮,用到了Slice之间跳转传参数, 源码都有详细注释,有兴趣小伙伴可以到gitee查看源码。

PlayAbilitySlice游戏界面功能讲解:

       游戏界面主要功能也是用表格布局生成相应主界面传过来的参数按钮,数字显示顺序随机, 分布式协同拉起GameServiceAbility游戏服务,并且在点击每个数字按钮时,通过订阅Event,把当前点到哪个数字,相关变量都接收到,然后更新相应的数据, 源码都有详细注释,有兴趣小伙伴可以到gitee查看源码。

GameServiceAbility游戏服务讲解:

       游戏服务主要功能是如果请求是Ability的,接收到参数后,再流转到其它界面传参;如果是其它请求,接收到参数后,通过公共事件发布出去,让订阅了此事件的Ability更新数据,源码都有详细注释,有兴趣小伙伴可以到gitee查看源码。

讲解到此了,不要忘记了config.json文件的权限配置哦,在module下添加 

收起
自动换行
深色代码主题
复制

"reqPermissions": [ { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" }, { "name": "ohos.permission.DISTRIBUTED_DATASYNC" }, { "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" }, { "name": "ohos.permission.READ_USER_STORAGE" }, { "name": "ohos.permission.WRITE_USER_STORAGE" }, { "name": "ohos.permission.GET_BUNDLE_INFO" } ]

同时,在游戏界面入口也是要提供动态授权:

收起
自动换行
深色代码主题
复制

private static void grantPermission(Context context) { LogUtil.info(TAG, "grantPermission"); if (context.verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) { if (context.canRequestPermission(DISTRIBUTED_DATASYNC)) { context.requestPermissionsFromUser(new String[] {DISTRIBUTED_DATASYNC}, PERMISSION_CODE); } }}

五, 总结

     有兴趣的小伙伴可以下载源码查看, 项目代码基本都有注释了,游戏规则很简单,就是在界面按顺序点击数字,时间越短,说明注意力越集中。 源码同步到gitee码云。

源码在这: https://gitee.com/army16/qin-hong-jun-board

点赞
7
收藏
2
回复
6
分享
举报
浏览1047 发布于2021-10-19 04:09未知归属地
全部评论
最多点赞
最新发布
最早发布
大佬 互关一波呀  
1
1楼回复于2021-10-19 06:54 未知归属地
  • 狼哥
    好的 已经关注,互相学习 
    2021-10-19 07:20 未知归属地
赞,前段时间还和孩子玩了纸质版的,还得手动秒表计时,这下好了!
1
3楼回复于2021-10-22 02:40 未知归属地
  • 狼哥
    如果你现在家里有两台鸿蒙手机或一台鸿蒙手机,一台鸿蒙平板,可以先同步源代码来运行,就可以和小孩一起玩了,如果你还没有投票这个活动,麻烦帮我投票一下, 谢谢 【人气投票】挑战赛第三期:福利加“码”,挑战HarmonyOS分布式趣味应用  https://developer.huawei.com/consumer/cn/forum/topic/0202701929746120043?fid=0101587866109860105 (出处: 论坛首页)
    2021-10-22 03:06 未知归属地
挺有意思的,有点想试试
1
2楼回复于2021-10-19 12:32 未知归属地
  • 狼哥
    想试就开始把项目搭建越来,游戏规则很简单,就是点击相应的按钮,生成NxN数字按钮,然后从1开始点到最后一个数字,技术知识,可以Codelabs的实例,或者直接看我的源码。
    2021-10-20 03:13 未知归属地
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

了解社区公约,与您携手共创和谐专业的开发者社区。