Complete Cocos Creator port with level bundles, themes, and tooling.

Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-16 15:30:58 +08:00
parent cba5105908
commit d393302388
6248 changed files with 17322729 additions and 11036 deletions

View File

@@ -3,11 +3,48 @@
* 用法:构建产物 index.html 末尾引入本脚本,或在主站模板中引入
*/
(function (global) {
function processData(json) { global.__tfrhOnProcessData?.(json); console.log('[processData]', JSON.parse(json)); }
function processVehicleData(json) { global.__tfrhOnProcessVehicleData?.(json); console.log('[processVehicleData]', JSON.parse(json)); }
function externalResult(json) { global.__tfrhOnExternalResult?.(json); console.log('[externalResult]', JSON.parse(json)); }
function externalLevelInfo(json) { global.__tfrhOnExternalLevelInfo?.(json); console.log('[externalLevelInfo]', JSON.parse(json)); }
function coinsData(json) { global.__tfrhOnCoinsData?.(json); console.log('[coinsData]', JSON.parse(json)); }
function wrap(name, hookKey) {
return function (json) {
var hook = global[hookKey];
if (typeof hook === 'function') hook(json);
try {
console.log('[' + name + ']', JSON.parse(json));
} catch (e) {
console.log('[' + name + ']', json);
}
};
}
function processData(json) { wrap('processData', '__tfrhOnProcessData')(json); }
function processVehicleData(json) { wrap('processVehicleData', '__tfrhOnProcessVehicleData')(json); }
function externalResult(json) { wrap('externalResult', '__tfrhOnExternalResult')(json); }
function externalLevelInfo(json) { wrap('externalLevelInfo', '__tfrhOnExternalLevelInfo')(json); }
function coinsData(json) { wrap('coinsData', '__tfrhOnCoinsData')(json); }
/** Editor 注册真实回调;同时写入 hook 与 window.processData 等全局名 */
global.tfrhBindUnityCallbacks = function (hooks) {
if (!hooks || typeof hooks !== 'object') return;
if (typeof hooks.processData === 'function') {
global.__tfrhOnProcessData = hooks.processData;
global.processData = wrap('processData', '__tfrhOnProcessData');
}
if (typeof hooks.processVehicleData === 'function') {
global.__tfrhOnProcessVehicleData = hooks.processVehicleData;
global.processVehicleData = wrap('processVehicleData', '__tfrhOnProcessVehicleData');
}
if (typeof hooks.externalResult === 'function') {
global.__tfrhOnExternalResult = hooks.externalResult;
global.externalResult = wrap('externalResult', '__tfrhOnExternalResult');
}
if (typeof hooks.externalLevelInfo === 'function') {
global.__tfrhOnExternalLevelInfo = hooks.externalLevelInfo;
global.externalLevelInfo = wrap('externalLevelInfo', '__tfrhOnExternalLevelInfo');
}
if (typeof hooks.coinsData === 'function') {
global.__tfrhOnCoinsData = hooks.coinsData;
global.coinsData = wrap('coinsData', '__tfrhOnCoinsData');
}
};
global.processData = processData;
global.processVehicleData = processVehicleData;
@@ -16,7 +53,7 @@
global.coinsData = coinsData;
// 动态 processPlayerA1 等
['A1','A2','A3','B1','B2','B3'].forEach(function (id) {
['A1', 'A2', 'A3', 'B1', 'B2', 'B3'].forEach(function (id) {
global['processPlayer' + id] = function (json) { console.log('[processPlayer' + id + ']', JSON.parse(json)); };
global['processVehicle' + id] = function (json) { console.log('[processVehicle' + id + ']', JSON.parse(json)); };
});

View File

@@ -4,20 +4,27 @@
<meta charset="utf-8" />
<title>主站 Cocos Web</title>
<style>
html, body { margin: 0; padding: 0; height: 100%; background: #1a1a2e; }
#GameDiv { width: 100%; height: 100%; }
#bar { color: #fff; font-family: sans-serif; padding: 8px; }
html, body {
margin: 0; padding: 0; min-height: 100%;
background: #1a1a2e;
display: flex; flex-direction: column; align-items: center;
}
/* 与 Unity Web 模板一致:桌面固定 960×600 */
#GameDiv { width: 960px; height: 600px; flex-shrink: 0; }
#bar { color: #fff; font-family: sans-serif; padding: 8px; width: 960px; }
</style>
</head>
<body>
<div id="bar">加载中…</div>
<div id="GameDiv"></div>
<!-- 与 Unity Template 一致:先挂 JS 回调,再启动 Cocos -->
<script src="cocos-bridge.js"></script>
<script>
function processData(json) { console.log('processData', JSON.parse(json)); }
function processVehicleData(json) { console.log('processVehicleData', JSON.parse(json)); }
function externalResult(json) { console.log('externalResult', JSON.parse(json)); }
function externalLevelInfo(json) { console.log('externalLevelInfo', JSON.parse(json)); }
function coinsData(json) { console.log('coinsData', JSON.parse(json)); }
// 主站可覆写钩子接收关卡 ID
window.__tfrhOnExternalLevelInfo = function (json) {
const data = JSON.parse(json);
console.log('关卡就绪 LevelID=', data.LevelID, data);
};
</script>
<!-- 构建后将 Cocos 生成的 index.js 引入此页 -->
</body>

View File

@@ -11,8 +11,13 @@
#toolbar { padding: 8px 12px; background: #16213e; color: #eee; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
#toolbar button { padding: 6px 12px; cursor: pointer; border: none; border-radius: 4px; background: #0f3460; color: #fff; }
#toolbar button:hover { background: #e94560; }
#game-wrap { flex: 1; position: relative; min-height: 0; }
#GameDiv, #Cocos3dGameContainer, #GameCanvas { width: 100% !important; height: 100% !important; }
#game-wrap {
flex: 1; position: relative; min-height: 0;
display: flex; justify-content: center; align-items: center;
}
/* 与 Unity Web 模板一致:游戏区 960×600 */
#GameDiv { width: 960px; height: 600px; flex-shrink: 0; }
#GameDiv #Cocos3dGameContainer, #GameDiv #GameCanvas { width: 100% !important; height: 100% !important; }
#log { height: 120px; overflow: auto; background: #0d1117; color: #8b949e; font: 12px/1.4 monospace; padding: 8px; }
</style>
<!-- ① 先挂回调(与 Unity Template/index.html 一致) -->

File diff suppressed because it is too large Load Diff

View File

@@ -190,7 +190,82 @@ npx --yes serve . -p 8080
---
## 六、生产环境注意
## 六、CDN 整包发布(对标 Unity mstest5
与 Unity 把 `mstest5/` 整目录上传 CDN 一样Cocos 也支持**单目录静态部署**,无需 Node 服务器。
### 1. 构建 + 打 CDN 包(与 Unity 参考包文件树 100% 一致)
参考 Unity 包:`/Users/liuyufei/tfrh/竞赛/mstest5`
```bash
cd /Users/liuyufei/tfrh/cocos/tfrh001
# ① Cocos Creator项目 → 构建发布 → Web Desktop → 构建
# ② 打成与 Unity 完全相同的目录/文件名
bash tools/package-for-cdn.sh --build build/web-desktop-001
# 输出到竞赛目录旁(便于对比)
bash tools/package-for-cdn.sh --build build/web-desktop-001 --out "/Users/liuyufei/tfrh/竞赛/mstest5-cocos"
```
### 2. 产物结构(与 Unity 参考逐文件对齐)
```
mstest5/
├── index.html
├── Build/
│ ├── mstest5.loader.js
│ ├── mstest5.data.br
│ ├── mstest5.framework.js.br
│ └── mstest5.wasm.br
├── StreamingAssets/aa/
│ ├── catalog.json
│ ├── settings.json
│ ├── AddressablesLink/link.xml
│ └── WebGL/
│ ├── 3a39a2f..._unitybuiltinshaders_....bundle
│ ├── defaultlocalgroup_assets_all_1baf4413....bundle ← Cocos 资源 zip
│ └── defaultlocalgroup_scenes_all_44c83ead....bundle ← Cocos 引擎 zip
└── TemplateData/11 个文件,与 Unity 相同)
```
`index.html` / `TemplateData` / `catalog.json` / `settings.json` / `link.xml` / `unitybuiltinshaders.bundle` **直接复制 Unity 参考包**Cocos 运行时打进两个 `defaultlocalgroup_*.bundle`,由自定义 `mstest5.loader.js` 解压并启动。
### 3. 上传与访问
1.`mstest5/` 内**全部文件**上传到 CDN 的 **mstest5** 目录(覆盖原 Unity 包)
2. 浏览器打开 `https://你的CDN域名/mstest5/index.html`
3. 主站 iframe 嵌入URL 与 Unity 时代相同,只换引擎):
```html
<iframe src="https://cdn.example.com/mstest5/index.html" width="960" height="600"></iframe>
```
### 4. 构建面板建议CDN 场景)
| 选项 | 建议 |
|------|------|
| 发布平台 | **Web Desktop** |
| 资源服务器地址 `server` | **留空**(资源与页面同域相对路径加载) |
| MD5 Cache | 生产可开启,更新后需刷新 CDN 缓存 |
| 主包压缩 | 默认 `merge_dep` 即可 |
若资源与页面不在同一路径,在构建面板填写 CDN 根 URL 到「资源服务器地址」,例如 `https://cdn.example.com/tfrh001/`
### 5. 与 Unity mstest5 对比
| | Unity mstest5 | Cocos mstest5 |
|--|---------------|-------------------|
| 入口 | `index.html` | `index.html` |
| 运行时 | `Build/*.br` (WASM) | `cocos-js/` + `src/` (JS) |
| 关卡资源 | `StreamingAssets/aa/*.bundle` | `assets/` (JSON + 贴图) |
| JS 桥 | 需主站页挂回调 | 已含 `cocos-bridge.js` |
| Brotli | 需要 `Content-Encoding: br` | 普通静态文件即可 |
---
## 七、生产环境注意
1. **HTTPS**:与 Unity 相同WebGL/Canvas 在混合内容下可能受限
2. **缓存**:构建带 MD5 时,更新后清 CDN 缓存
@@ -199,6 +274,6 @@ npx --yes serve . -p 8080
---
## 、关卡
## 、关卡
已导入 Levels600 共 **600** 关,`SwitchLevel(1..600)` 与 Unity 一致。