概述
Cocos Creator 微信小游戏的启动流程是一个多阶段、跨平台的复杂过程,涉及从原生代码到 JavaScript 的执行环境搭建。整个流程可以分为以下几个主要阶段:
- 原生引擎初始化
- JavaScript 运行时环境准备
- 游戏脚本加载与执行
- 微信小游戏平台适配
这个流程在 Cocos Creator 引擎的多个文件中都有体现,特别是在 native 目录下的 Game.cpp 和 RuntimeJsImpl.h 等文件中。
1. 原生引擎初始化
1.1 Game 类的初始化
在 native/tools/simulator/frameworks/runtime-src/Classes/Game.cpp 文件中,Game 类的 init() 方法负责初始化游戏窗口和引擎核心组件。
int Game::init() {
cc::pipeline::GlobalDSManager::setDescriptorSetLayout();
SimulatorApp::getInstance()->init();
std::call_once(_windowCreateFlag, [&]() {
cc::ISystemWindowInfo info;
info.width= SimulatorApp::getInstance()->getWidth();
info.height = SimulatorApp::getInstance()->getHeight();
#if (CC_PLATFORM == CC_PLATFORM_WINDOWS)
info.x = (GetSystemMetrics(SM_CXSCREEN) - info.width) / 2;
info.y = (GetSystemMetrics(SM_CYSCREEN) - info.height) / 2;
#elif (CC_PLATFORM == CC_PLATFORM_MACOS)
auto mainDisplayId = CGMainDisplayID();
info.x = (CGDisplayPixelsWide(mainDisplayId) - info.width) / 2;
info.y = (CGDisplayPixelsHigh(mainDisplayId) - info.height) / 2;
#endif
info.title = "My Game";
info.flags = cc::ISystemWindow::CC_WINDOW_SHOWN |
cc::ISystemWindow::CC_WINDOW_RESIZABLE |
cc::ISystemWindow::CC_WINDOW_INPUT_FOCUS;
cc::ISystemWindowManager* windowMgr = CC_GET_PLATFORM_INTERFACE(cc::ISystemWindowManager);
windowMgr->createWindow(info);
});
SimulatorApp::getInstance()->run();
auto parser = ConfigParser::getInstance();
setDebugIpAndPort("0.0.0.0", 5086, parser->isWaitForConnect());
int ret = cc::CocosApplication::init();
if (ret != 0) {
return ret;
}
auto runtimeEngine = RuntimeEngine::getInstance();
runtimeEngine->setEventTrackingEnable(true);
auto jsRuntime = RuntimeJsImpl::create();
runtimeEngine->addRuntime(jsRuntime, kRuntimeEngineJs);
runtimeEngine->start();
setXXTeaKey("");
runScript("jsb-adapter/web-adapter.js");
runScript("main.js");
// Runtime end
CC_LOG_DEBUG("iShow!");
return 0;
}
这段代码主要完成了以下工作:
- 初始化全局描述符集管理器
- 创建游戏窗口并设置窗口属性
- 初始化 Cocos 应用程序
- 创建并启动 JavaScript 运行时
- 设置脚本加密密钥
- 加载并运行适配器脚本和主脚本
Game.cpp:61:120
1.2 窗口创建
窗口创建部分代码展示了如何根据平台创建游戏窗口:
cc::ISystemWindowInfo info;
info.width= SimulatorApp::getInstance()->getWidth();
info.height = SimulatorApp::getInstance()->getHeight();
#if (CC_PLATFORM == CC_PLATFORM_WINDOWS)
info.x = (GetSystemMetrics(SM_CXSCREEN) - info.width) / 2;
info.y = (GetSystemMetrics(SM_CYSCREEN) - info.height) / 2;
#elif (CC_PLATFORM == CC_PLATFORM_MACOS)
auto mainDisplayId = CGMainDisplayID();
info.x = (CGDisplayPixelsWide(mainDisplayId) - info.width) / 2;
info.y = (CGDisplayPixelsHigh(mainDisplayId) - info.height) / 2;
#endif
info.title = "My Game";
info.flags = cc::ISystemWindow::CC_WINDOW_SHOWN |
cc::ISystemWindow::CC_WINDOW_RESIZABLE |
cc::ISystemWindow::CC_WINDOW_INPUT_FOCUS;
cc::ISystemWindowManager* windowMgr = CC_GET_PLATFORM_INTERFACE(cc::ISystemWindowManager);
windowMgr->createWindow(info);
这段代码根据平台创建了游戏窗口,并设置了窗口的位置、大小和属性。
Game.cpp:61:90
2. JavaScript 运行时环境准备
2.1 RuntimeJsImpl 类
在 native/tools/simulator/frameworks/runtime-src/Classes/ide-support/RuntimeJsImpl.h 文件中定义了 RuntimeJsImpl 类,负责创建和管理 JavaScript 运行时环境。
class RuntimeJsImpl : public RuntimeProtocol
{
public:
static RuntimeJsImpl* create();
void startScript(const std::string& file);
void onStartDebuger(const rapidjson::Document& dArgParse, rapidjson::Document& dReplyParse);
void onClearCompile(const rapidjson::Document& dArgParse, rapidjson::Document& dReplyParse);
void onPrecompile(const rapidjson::Document& dArgParse, rapidjson::Document& dReplyParse);
void onReload(const rapidjson::Document& dArgParse, rapidjson::Document& dReplyParse);
void onRemove(const std::string &filename);
void end();
bool startWithDebugger();
private:
RuntimeJsImpl();
bool initJsEnv();
bool loadScriptFile(const std::string& file);
};
这个类实现了 JavaScript 运行时的基本功能,包括脚本加载、调试支持等。
RuntimeJsImpl.h:31:60
2.2 JavaScript 环境初始化
在 Game.cpp 中,创建并启动 JavaScript 运行时:
auto runtimeEngine = RuntimeEngine::getInstance();
runtimeEngine->setEventTrackingEnable(true);
auto jsRuntime = RuntimeJsImpl::create();
runtimeEngine->addRuntime(jsRuntime, kRuntimeEngineJs);
runtimeEngine->start();
这段代码创建了 JavaScript 运行时实例,并将其添加到运行时引擎中,然后启动运行时。
Game.cpp:91:105
3. 游戏脚本加载与执行
3.1 脚本加载
在 Game.cpp 中,加载并执行了两个关键的 JavaScript 脚本:
setXXTeaKey("");
runScript("jsb-adapter/web-adapter.js");
runScript("main.js");
web-adapter.js:这是微信小游戏平台的适配器脚本,负责处理平台特定的功能main.js:这是游戏的主脚本,包含游戏的初始化和启动代码
Game.cpp:106:115
3.2 脚本执行流程
微信小游戏的启动流程中,脚本执行主要涉及以下几个步骤:
- 加载适配器脚本:
web-adapter.js负责初始化微信小游戏平台的特定功能,如网络请求、本地存储等 - 加载主脚本:
main.js包含游戏的初始化代码,通常会调用 Cocos Creator 的启动函数 - 游戏初始化:在 JavaScript 中完成游戏场景、资源等的加载和初始化
- 游戏循环启动:开始游戏的主循环,处理用户输入、更新游戏状态和渲染画面
4. 微信小游戏平台适配
4.1 平台适配机制
Cocos Creator 通过适配器模式实现了对微信小游戏平台的支持。在 templates/harmonyos-next/entry/src/main/ets/workers/cocos_worker.ts 文件中,可以看到平台适配的相关代码:
import worker from '@ohos.worker';
import cocos from 'libcocos.so';
import hilog from '@ohos.hilog';
import { ContextType } from '../common/Constants';
<% if(!useV8) { %>
import { launchEngine } from '../cocos/game';
<% } %>
import { PortProxy } from '../common/PortProxy';
<% if(useV8) { %>
globalThis.importPolyfill = async function () {
await import('../cocos/oh-adapter/sys-ability-polyfill.js');
}
globalThis.importPolyfill();
globalThis.oh = {};
<% } %>
if (!(console as any).assert) {
(console as any).assert = function(cond, msg) {
if (!cond) {
throw new Error(msg);
}
};
}
const nativeContext = cocos.getContext(ContextType.WORKER_INIT);
nativeContext.workerInit();
const nativeEditBox = cocos.getContext(ContextType.EDITBOX_UTILS);
const nativeWebView = cocos.getContext(ContextType.WEBVIEW_UTILS);
const appLifecycle = cocos.getContext(ContextType.APP_LIFECYCLE);
const nativeVideo = cocos.getContext(ContextType.VIDEO_UTILS);
let uiPort = new PortProxy(worker.workerPort);
nativeContext.postMessage = function (msgType: string, msgData: string): void {
uiPort.postMessage(msgType, msgData);
}
nativeContext.postSyncMessage = async function (msgType: string, msgData: string): Promise<boolean | string | number> {
const result = await uiPort.postSyncMessage(msgType, msgData) as boolean | string | number;
return result;
}
// The purpose of this is to avoid being GC
nativeContext.setPostMessageFunction.call(nativeContext, nativeContext.postMessage)
nativeContext.setPostSyncMessageFunction.call(nativeContext, nativeContext.postSyncMessage)
globalThis.terminateProcess = function () {
uiPort.postMessage("exitGame",0);
}
uiPort._messageHandle = function (e) {
var data = e.data;
var msg = data.data;
switch (msg.name) {
case "onXCLoad":
const renderContext = cocos.getContext(ContextType.NATIVE_RENDER_API);
renderContext.nativeEngineInit();
<% if(!useV8) { %>
launchEngine().then(() => {
console.info('launch CC engine finished');
}).catch(e => {
console.error('launch CC engine failed');
});
<% } %>
// @ts-ignore
globalThis.oh.postMessage = nativeContext.postMessage;
// @ts-ignore
globalThis.oh.postSyncMessage = nativeContext.postSyncMessage;
renderContext.nativeEngineStart();
break;
case "onTextInput":
nativeEditBox.onTextChange(msg.param);
break;
case "onComplete":
nativeEditBox.onComplete(msg.param);
break;
case "onConfirm":
nativeEditBox.onConfirm(msg.param);
break;
case "onPageBegin":
nativeWebView.shouldStartLoading(msg.param.viewTag, msg.param.url);
break;
case "onPageEnd":
nativeWebView.finishLoading(msg.param.viewTag, msg.param.url);
break;
case "onErrorReceive":
nativeWebView.failLoading(msg.param.viewTag, msg.param.url);
break;
case "onVideoEvent":
nativeVideo.onVideoEvent(JSON.stringify(msg.param));
break;
case "backPress":
appLifecycle.onBackPress();
break;
default:
console.error("cocos worker: message type unknown");
break;
}
}
这段代码展示了如何在微信小游戏平台上初始化 Cocos 引擎,并处理平台特定的事件和消息。
cocos_worker.ts:1:129
启动流程图解
1. 整体启动流程图
2. JavaScript 运行时初始化流程
3. 微信小游戏平台适配流程
总结
Cocos Creator 微信小游戏的完整启动流程是一个多阶段、跨平台的过程,涉及从原生代码到 JavaScript 的执行环境搭建。整个流程可以总结为以下几个关键步骤:
- 原生引擎初始化:创建游戏窗口并初始化引擎核心组件
- JavaScript 运行时环境准备:创建并启动 JavaScript 运行时
- 游戏脚本加载与执行:加载适配器脚本和主游戏脚本
- 微信小游戏平台适配:处理平台特定的事件和消息
这个流程在 Cocos Creator 引擎的多个文件中都有体现,特别是在 native 目录下的 Game.cpp 和 RuntimeJsImpl.h 等文件中。通过理解这些文件的内容和交互,可以更好地掌握 Cocos Creator 微信小游戏的启动机制。
4024

被折叠的 条评论
为什么被折叠?



