鸿蒙分布式1024一起玩专注游戏

鸿蒙分布式1024一起玩专注游戏

作者:狼哥Army 2021-10-20 16:13:05

开发

前端

分布式 1024一起专注游戏是在屏幕上画上N x N个方格(如4×4共16个),格子内任意填写上从1开始顺序生成的数字(如1 ~ 16共16个数字)。

[[430078]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.IDC.NET

一, 前言

1024一起专注游戏是在屏幕上画上N x N个方格(如4×4共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

三, 创建工程

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

四, 主界面开发

在展示源代码之前,先介绍一下使用到了JAVA哪些组件:

DirectionalLayout, TableLayout, DependentLayout, Button, Image, Text, ListContainer, CommonDialog,通过查看Java UI参考文档,就可以做出你喜欢的应用了。

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

LogUtil 日志打印类:

  1. public class LogUtil { 
  2.     private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, "1024Game"); 
  3.     private static final String LOG_FORMAT = "%{public}s: %{public}s"
  4.  
  5.     private LogUtil() { 
  6.  
  7.     } 
  8.     public static void debug(String className, String msg) { 
  9.         HiLog.debug(LABEL_LOG, LOG_FORMAT, className, msg); 
  10.     } 
  11.     public static void info(String className, String msg) { 
  12.         HiLog.info(LABEL_LOG, LOG_FORMAT, className, msg); 
  13.     } 
  14.     public static void info(Class<?> classType, final String format, Object... args) { 
  15.         String buffMsg = String.format(Locale.ROOT, format, args); 
  16.         HiLog.info(LABEL_LOG, LOG_FORMAT, classType == null ? "null" : classType.getSimpleName(), buffMsg); 
  17.     } 
  18.     public static void error(String tag, String msg) { 
  19.         HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg); 
  20.     } 

SelectDeviceDialog设备选择对话框:

  1. public class SelectDeviceDialog { 
  2.     private static final int DIALOG_WIDTH = 840; 
  3.     private static final int DIALOG_HEIGHT = 900; 
  4.     private CommonDialog commonDialog; 
  5.  
  6.     public SelectDeviceDialog(Context context, List<DeviceInfo> devices, SelectResultListener listener) { 
  7.         initView(context, devices, listener); 
  8.     } 
  9.     private void initView(Context context, List<DeviceInfo> devices, SelectResultListener listener) { 
  10.         // 创建一个公共对话框 
  11.         commonDialog = new CommonDialog(context); 
  12.         // 设置对齐方式居中 
  13.         commonDialog.setAlignment(LayoutAlignment.CENTER); 
  14.         // 设置对话框尺寸 
  15.         commonDialog.setSize(DIALOG_WIDTH, DIALOG_HEIGHT); 
  16.         // 设置对话框自动关闭 
  17.         commonDialog.setAutoClosable(true); 
  18.         // 加载XML布局文件 
  19.         Component dialogLayout = 
  20.                 LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_select_device, nullfalse); 
  21.         // 设置对话框内容 
  22.         commonDialog.setContentCustomComponent(dialogLayout); 
  23.         // 查找到列表容器 
  24.         if (dialogLayout.findComponentById(ResourceTable.Id_list_devices) instanceof ListContainer) { 
  25.             // 获取列表容器对象 
  26.             ListContainer devicesListContainer = 
  27.                     (ListContainer) dialogLayout.findComponentById(ResourceTable.Id_list_devices); 
  28.             // 设备列表适配器 
  29.             DevicesListAdapter devicesListAdapter = new DevicesListAdapter(devices, context); 
  30.             // 设置设备列表容器项提供者 
  31.             devicesListContainer.setItemProvider(devicesListAdapter); 
  32.             // 设置设备列表项单击事件 
  33.             devicesListContainer.setItemClickedListener((listContainer, component, position, id) -> { 
  34.                 // 回调选择的设备信息 
  35.                 listener.callBack(devices.get(position)); 
  36.                 // 关闭对话框 
  37.                 commonDialog.hide(); 
  38.             }); 
  39.         } 
  40.         dialogLayout.findComponentById(ResourceTable.Id_cancel).setClickedListener(component -> { 
  41.             // 关闭对话框 
  42.             commonDialog.hide(); 
  43.         }); 
  44.     } 
  45.     // 显示对话框 
  46.     public void show() { 
  47.         commonDialog.show(); 
  48.     } 
  49.     /** 
  50.      * 内部接口, 选择设备后回调事件 
  51.      */ 
  52.     public interface SelectResultListener { 
  53.         void callBack(DeviceInfo deviceInfo); 
  54.     } 

DevicesListAdapter设备列表适配器:

  1. public class DevicesListAdapter extends BaseItemProvider { 
  2.     // 开始下标从0开始 
  3.     private static final int SUBSTRING_START = 0; 
  4.     // 结束下标为4 
  5.     private static final int SUBSTRING_END = 4; 
  6.     // 设备信息列表 
  7.     private List<DeviceInfo> deviceInfoList; 
  8.     // 当前上下文 
  9.     private Context context; 
  10.  
  11.     // 带参构造方法 
  12.     public DevicesListAdapter(List<DeviceInfo> deviceInfoList, Context context) { 
  13.         this.deviceInfoList = deviceInfoList; 
  14.         this.context = context; 
  15.     } 
  16.     @Override 
  17.     public int getCount() { 
  18.         return deviceInfoList == null ? 0 : deviceInfoList.size(); 
  19.     } 
  20.     @Override 
  21.     public Object getItem(int i) { 
  22.         return Optional.of(deviceInfoList.get(i)); 
  23.     } 
  24.     @Override 
  25.     public long getItemId(int i) { 
  26.         return i; 
  27.     } 
  28.     @Override 
  29.     public Component getComponent(int i, Component component, ComponentContainer componentContainer) { 
  30.         // 定义设备视图内部类 
  31.         ViewHolder viewHolder = null
  32.         // 定义组件 
  33.         Component mComponent = component; 
  34.         // 组件为空时 
  35.         if (mComponent == null) { 
  36.             // 查找设备列表项布局XML 
  37.             mComponent = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_device_list, nullfalse); 
  38.             // 初始化设备视图类 
  39.             viewHolder = new ViewHolder(); 
  40.             // 判断组件布局里是否包含设备名称文本组件 
  41.             if (mComponent.findComponentById(ResourceTable.Id_device_name) instanceof Text) { 
  42.                 // 获取设备列表项布局XML的设备名称文件组件,并赋值给内部类设备视图设备名称属性缓存 
  43.                 viewHolder.devicesName = (Text) mComponent.findComponentById(ResourceTable.Id_device_name); 
  44.             } 
  45.             // 判断组件布局里是否包含设备Id文本组件 
  46.             if (mComponent.findComponentById(ResourceTable.Id_device_id) instanceof Text) { 
  47.                 // 获取设备列表项布局XML的设备Id文件组件,并赋值给内部类设备视图设备Id属性缓存 
  48.                 viewHolder.devicesId = (Text) mComponent.findComponentById(ResourceTable.Id_device_id); 
  49.             } 
  50.             mComponent.setTag(viewHolder); 
  51.         } else { 
  52.             // 如果组件不为空, 并且标签包含内部类设备视图 
  53.             if (mComponent.getTag() instanceof ViewHolder) { 
  54.                 // 从组件标签获取出设备视图 
  55.                 viewHolder = (ViewHolder) mComponent.getTag(); 
  56.             } 
  57.         } 
  58.         // 设备视图不为空时 
  59.         if (viewHolder != null) { 
  60.             // 设置设备名称内容 
  61.             viewHolder.devicesName.setText(deviceInfoList.get(i).getDeviceName()); 
  62.             String deviceId = deviceInfoList.get(i).getDeviceId(); 
  63.             deviceId = deviceId.substring(SUBSTRING_START, SUBSTRING_END) + "******" 
  64.                     + deviceId.substring(deviceId.length() - SUBSTRING_END); 
  65.             // 设置设备名称Id 
  66.             viewHolder.devicesId.setText(deviceId); 
  67.         } 
  68.         return mComponent; 
  69.     } 
  70.     /** 
  71.      * 内部类, 设备视图 
  72.      */ 
  73.     private static class ViewHolder { 
  74.         // 设备名称 
  75.         private Text devicesName; 
  76.         // 设备Id 
  77.         private Text devicesId; 
  78.     } 

MainAbilitySlice主界面功能讲解 :

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

PlayAbilitySlice游戏界面功能讲解:

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

GameServiceAbility游戏服务讲解:

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

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

  1. "reqPermissions": [ 
  2.       { 
  3.         "name""ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" 
  4.       }, 
  5.       { 
  6.         "name""ohos.permission.DISTRIBUTED_DATASYNC" 
  7.       }, 
  8.       { 
  9.         "name""ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" 
  10.       }, 
  11.       { 
  12.         "name""ohos.permission.READ_USER_STORAGE" 
  13.       }, 
  14.       { 
  15.         "name""ohos.permission.WRITE_USER_STORAGE" 
  16.       }, 
  17.       { 
  18.         "name""ohos.permission.GET_BUNDLE_INFO" 
  19.       } 
  20.     ] 

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

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

五, 总结

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

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.IDC.NET

 

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/277364.html<

(0)
运维的头像运维
上一篇2025-05-11 02:21
下一篇 2025-05-11 02:22

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注