如何用鸿蒙开发1024专注小游戏?

10,956次阅读
没有评论

共计 6579 个字符,预计需要花费 17 分钟才能阅读完成。

一、前言

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

如何用鸿蒙开发 1024 专注小游戏?

如何用鸿蒙开发 1024 专注小游戏?

三、创建工程

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

如何用鸿蒙开发 1024 专注小游戏?

如何用鸿蒙开发 1024 专注小游戏?

如何用鸿蒙开发 1024 专注小游戏?

四、主界面开发

在展示源代码之前,先介绍一下使用到了 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 devices, SelectResultListener listener) {initView(context, devices, listener);
    }
    private void initView(Context context, List 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 deviceInfoList;
    // 当前上下文
    private Context context;


    // 带参构造方法
    public DevicesListAdapter(List 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 主界面功能讲解:

主界面主要功能就是用表格布局生成 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 下添加

"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

原文地址: 如何用鸿蒙开发 1024 专注小游戏?

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-09-23发表,共计6579字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)