开源鸿蒙Cocos游戏大赛报名!25万奖金!¥250000

@iwae 救命

鸿蒙和cocos,目前是在不同的线程里,要互相调用的话,需要进行线程通信。目前是没有进行封装,实现的方式还是比较原始些,复杂些,后续我们会考虑优化封装。

首先鸿蒙的ts接口是跑在ARK上的,我们先定义为UI线程或者主线程,cocos是运行在worker上的,我们定义为cocos线程。

ark 调用 cocos的接口:

首先是从UI线程发消息通知COCOS线程:
works/cocos_worker.ts是在cocos线程里。
workPort.postMessage 这个地方就是代表着发送消息到cocos线程
例如在CocosVideoPlayer.ts里的

      this.workPort?.postMessage("onVideoEvent", {
          videoTag: this.videoInfo.viewTag as number,
          videoEvent: EventType.PLAYING as EventType
        } as param);
      })

cocos线程需要监听,是在cocos_worker.ts里监听,类似:

    case "onVideoEvent":
      nativeVideo.onVideoEvent(JSON.stringify(msg.param));
      break;

到了这个过程,其实就已经完成了从鸿蒙UI线程到COCOS线程,同一个线程的js引擎是一样的,全局的变量也是一样的,这个时候就可以有很多方案可以选择了。

比如:可以在游戏里,定义一个全局的变量,例如window.oh.test, 然后在cocos_worker.ts里进行调用。

目前这里的大部分实现的方式是引擎内部的,实际上是很麻烦的,走的流程是:
cocos_worker.ts ->c++ -> 游戏里

这里是通过NAPI来实现的,下面也大概说下流程:
c++里面注册一个函数给cocos_worker里进行调用

// 导出一个接口给cocos_worker.ts调用
exports["onVideoEvent"] = Napi::Function::New(env, napiOnVideoEvent);

调用cocos引擎的jsb.onVideoEvent,这里相当于是在C++里转到cocos的ts里:

    se::Value onVideoEventVal;
    ok = ohVal.toObject()->getProperty("onVideoEvent", &onVideoEventVal);
    if (!ok || !onVideoEventVal.isObject() || !onVideoEventVal.toObject()->isFunction()) {
        CC_LOG_ERROR("onVideoEvent not found");
        return;
    }
    // Convert args to se::ValueArray
    se::ValueArray seArgs;
    seArgs.reserve(1);
    seArgs.emplace_back(se::Value(info[0].As<Napi::String>().Utf8Value()));
    ok = onVideoEventVal.toObject()->call(seArgs, ohVal.toObject());
    if (!ok) {
        CC_LOG_ERROR("Call oh.onEventEvent failed!");
    }

引擎的ts处理:

window.oh.onVideoEvent = (args) => {

        const data = JSON.parse(args);

        videoPlayers.forEach((player) => {

            if (player.index === data.videoTag) {

                player.dispatchEvent(data.videoEvent, data.args);

            }

        });

    };

cocos 调用 ark 的接口其实也是一样的,就是cocos线程上,postMessage给UI线程(ARK线程),这个地方是有封装接口的,所以在游戏里,可以直接使用window.oh.postMessage
例如videoplayer的实现:

        pause () {
            window.oh.postMessage('pauseVideo', this._videoIndex);
        }
        setVisible (visible) {
            window.oh.postMessage('setVideoVisible', { tag: this._videoIndex, visible });
        }
        resume () {
            window.oh.postMessage('resumeVideo', this._videoIndex);
        }

ui线程的接收消息的地方是在index.ets里面:

        case "startVideo": {
          let index = this.videoIndexMap.get(msg.param as number) as number;
          if(this.videoArray[index].duration){
            this.videoArray[index].controller.start();
          }else{
            this.videoArray[index].isPreparedStart = true;
          }
          break;
        }
        case "pauseVideo": {
          let index = this.videoIndexMap.get(msg.param as number) as number;
          this.videoArray[index].controller.pause();
          break;
        }
        case "stopVideo": {
          let index = this.videoIndexMap.get(msg.param as number) as number;
          this.videoArray[index].controller.stop();
          break;
        }

到了这里,其实就可以使用ark的接口了。

还有一种方式,可以调用ts的接口,就是在sys-ability-polyfill.ts里,定义全局接口,然后在游戏里直接调用。但是部分接口应该是有问题的,因为有些接口不一定是线程安全的,就相当于在一个线程里,调用另一个线程的环境。

在后面发布的2.4.14和3.8.5里,可以使用类似jsb.reflection.callStaticMethod的方法,可以在cocos里直接调用ark引擎的方法。可以参考实现

3赞

好像有点理解了,因为之前在观察鸿蒙的原生层是否有实现类似安卓原生层的“Cocos2dxJavascriptJavaBridge.evalString”这种去调用cocos层里的ts函数的接口,这里鸿蒙调cocos好像要在NapiHelper.cpp写接口,并且c++层也要有对应的实现才行

嗯,后续的版本会有类似的接口

本次OH报名队伍超过410只,后续大家可以继续讨论和优化,期待决赛相见!

image
应该没有超时,发了邮件,没有回复是怎么回事??
@iwae

咨询下鸿蒙报名方 可以扫码入群image

有点奇怪:

手机系统版本号: OpenHarmony 4.1.7.605
目前我收到的华为手机无论怎么怎么切换 USB 连电脑,并没任何提示,我看开发者模式是默认有的

于是使用这个 IDE 准备模拟器调试下,没想到并没任何报错, 但是就是没运行起来,大家没有遇到过这种情况的吗?官方交流群好少人说话:

不支持模拟器,设备打开usb调试如果不行 换个数据线

DevEco Studio要下载5.0.0版本的,官网最新是5.0.1,识别不了收到的手机。

1赞

感谢,降级确实可以看到手机设备,不过 USB 连手机后电脑还是显示不了

嗯,默认是开了 USB 调试,数据线和手机都换了,线是ok的

可以下载这个版本试试:

下载中心 | 华为开发者联盟-HarmonyOS开发者官网,共建鸿蒙生态

另外,这个真机调试,每次这里运行到这一步,设备就会自动重启,安装不上,看不到什么效果,调试确实有点麻烦,不知道各位大佬都是怎么调试的呢?

这个是开发版还是手机?

请大家本周务必上传仓库

是手机,升级了最新的系统的手机,另外也尝试恢复出厂设置了,不怎么行

2.4.14 版本OpenHarmony 不支持脚本加密和MD5 Cache吗,构建面板中没有此选项,有大佬给建议可以如何加密混编吗