Initial Cocos Creator port of main-site Unity WebGL game.
Includes core gameplay, 600 exported levels, visual assets, web bridge, and bootstrap scene. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
43
web-template/cocos-bridge.js
Normal file
43
web-template/cocos-bridge.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 主站页面对接层:在 Cocos 启动后提供与 Unity WebGL 相同的 unityInstance.SendMessage API
|
||||
* 用法:构建产物 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)); }
|
||||
|
||||
global.processData = processData;
|
||||
global.processVehicleData = processVehicleData;
|
||||
global.externalResult = externalResult;
|
||||
global.externalLevelInfo = externalLevelInfo;
|
||||
global.coinsData = coinsData;
|
||||
|
||||
// 动态 processPlayerA1 等
|
||||
['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)); };
|
||||
});
|
||||
|
||||
function waitInstance(maxMs) {
|
||||
maxMs = maxMs || 30000;
|
||||
return new Promise(function (resolve, reject) {
|
||||
var t0 = Date.now();
|
||||
(function tick() {
|
||||
if (global.cocosIns || global.unityInstance) return resolve(global.cocosIns || global.unityInstance);
|
||||
if (Date.now() - t0 > maxMs) return reject(new Error('Cocos instance timeout'));
|
||||
requestAnimationFrame(tick);
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
global.tfrhReady = waitInstance;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
waitInstance().then(function () {
|
||||
console.log('[tfrh] Cocos bridge ready, use unityInstance.SendMessage(...)');
|
||||
}).catch(function (e) { console.warn('[tfrh]', e.message); });
|
||||
});
|
||||
})(typeof window !== 'undefined' ? window : globalThis);
|
||||
24
web-template/index.html
Normal file
24
web-template/index.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<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; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bar">加载中…</div>
|
||||
<div id="GameDiv"></div>
|
||||
<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)); }
|
||||
</script>
|
||||
<!-- 构建后将 Cocos 生成的 index.js 引入此页 -->
|
||||
</body>
|
||||
</html>
|
||||
77
web-template/main-site.html
Normal file
77
web-template/main-site.html
Normal file
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
||||
<title>主站 · Cocos 关卡引擎</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; height: 100%; background: #1a1a2e; font-family: system-ui, sans-serif; }
|
||||
#layout { display: flex; flex-direction: column; height: 100%; }
|
||||
#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; }
|
||||
#log { height: 120px; overflow: auto; background: #0d1117; color: #8b949e; font: 12px/1.4 monospace; padding: 8px; }
|
||||
</style>
|
||||
<!-- ① 先挂回调(与 Unity Template/index.html 一致) -->
|
||||
<script src="cocos-bridge.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="layout">
|
||||
<div id="toolbar">
|
||||
<strong>主站 Cocos 联调</strong>
|
||||
<button type="button" id="btn-l1">关卡 1</button>
|
||||
<button type="button" id="btn-l21">关卡 21(载具)</button>
|
||||
<button type="button" id="btn-move">前进 2 格</button>
|
||||
<button type="button" id="btn-info">获取坐标</button>
|
||||
<button type="button" id="btn-end">结束输入</button>
|
||||
</div>
|
||||
<div id="game-wrap">
|
||||
<!-- ② Cocos 构建后替换为 build 目录中的容器,常见为 #GameDiv -->
|
||||
<div id="GameDiv">
|
||||
<div id="Cocos3dGameContainer">
|
||||
<canvas id="GameCanvas" tabindex="0"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="log"></pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const logEl = document.getElementById('log');
|
||||
function log(msg) {
|
||||
logEl.textContent += msg + '\n';
|
||||
logEl.scrollTop = logEl.scrollHeight;
|
||||
}
|
||||
|
||||
window.__tfrhOnExternalLevelInfo = (j) => log('关卡就绪: ' + j);
|
||||
window.__tfrhOnProcessData = (j) => log('坐标: ' + j);
|
||||
window.__tfrhOnExternalResult = (j) => log('结果: ' + j);
|
||||
|
||||
function send(obj, method, arg) {
|
||||
const ins = window.unityInstance || window.cocosIns;
|
||||
if (!ins) { log('实例未就绪'); return; }
|
||||
if (arg === undefined) ins.SendMessage(obj, method);
|
||||
else ins.SendMessage(obj, method, arg);
|
||||
}
|
||||
|
||||
document.getElementById('btn-l1').onclick = () => send('GameController', 'SwitchLevel', 1);
|
||||
document.getElementById('btn-l21').onclick = () => send('GameController', 'SwitchLevel', 21);
|
||||
document.getElementById('btn-move').onclick = () => send('Player', 'CallMove', 2);
|
||||
document.getElementById('btn-info').onclick = () => send('Player', 'CallPlayerInfo');
|
||||
document.getElementById('btn-end').onclick = () => send('GameController', 'CallSetIsInputEnd', 1);
|
||||
</script>
|
||||
|
||||
<!-- ③ 在 Cocos 构建输出的 index.html 中,将 systemjs / index.js 等脚本复制到本页 GameDiv 之后 -->
|
||||
<!-- 示例(路径按实际构建目录修改):
|
||||
<script src="src/polyfills.bundle.js"></script>
|
||||
<script src="src/system.bundle.js"></script>
|
||||
<script src="src/import-map.json" type="systemjs-importmap"></script>
|
||||
<script>
|
||||
System.import('./index.js').catch(function(e){ console.error(e); });
|
||||
</script>
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
204
web-template/主站对接说明.md
Normal file
204
web-template/主站对接说明.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# 主站 Web 对接完整步骤(Cocos tfrh001)
|
||||
|
||||
## 一、在 Cocos Creator 中构建 Web Desktop
|
||||
|
||||
### 1. 打开工程
|
||||
|
||||
```
|
||||
/Users/liuyufei/tfrh/cocos/tfrh001
|
||||
```
|
||||
|
||||
确认已存在 `assets/scenes/main.scene`,且节点上挂了 **AppBootstrap**。
|
||||
|
||||
### 2. 设置启动场景
|
||||
|
||||
**项目 → 项目设置 → 项目数据 → 启动场景** → 选择 `main`。
|
||||
|
||||
### 3. 构建发布
|
||||
|
||||
1. 菜单 **项目 → 构建发布**(或顶部 **构建** 按钮)
|
||||
2. **发布平台**:选 **Web Desktop**(不要选 Web Mobile,除非只做手机)
|
||||
3. **构建路径**:默认 `build/web-desktop`(可保持默认)
|
||||
4. **初始场景**:`main`
|
||||
5. 建议勾选:
|
||||
- **内联所有 SpriteFrame**(减少请求数,可选)
|
||||
- **MD5 Cache**(按需)
|
||||
6. 点击 **构建**
|
||||
7. 构建成功后点击 **运行** 可先本地测一遍
|
||||
|
||||
### 4. 构建产物位置
|
||||
|
||||
```
|
||||
tfrh001/build/web-desktop/
|
||||
├── index.html ← 含 Cocos 启动 script 列表
|
||||
├── index.js
|
||||
├── src/
|
||||
│ ├── system.bundle.js
|
||||
│ ├── polyfills.bundle.js
|
||||
│ └── ...
|
||||
├── assets/ ← 资源
|
||||
└── ...
|
||||
```
|
||||
|
||||
> 若 `build/web-desktop` 不存在,说明尚未在编辑器里点过「构建」。
|
||||
|
||||
---
|
||||
|
||||
## 二、合并到主站静态目录
|
||||
|
||||
### 方式 A:自动脚本(推荐)
|
||||
|
||||
在终端执行(先完成上一节构建):
|
||||
|
||||
```bash
|
||||
cd /Users/liuyufei/tfrh/cocos/tfrh001
|
||||
|
||||
# 部署到主站 Template 下(与 Unity 模板并列,便于对比)
|
||||
bash tools/deploy-to-main.sh \
|
||||
--build build/web-desktop \
|
||||
--target "/Users/liuyufei/tfrh/主站文件/主站/Template/cocos"
|
||||
```
|
||||
|
||||
部署后目录:
|
||||
|
||||
```
|
||||
主站/Template/
|
||||
├── index.html ← 原 Unity 页(参考)
|
||||
├── cocos-bridge.js ← 新增:JS 桥
|
||||
├── cocos-demo.html ← 新增:联调页
|
||||
└── cocos/ ← Cocos 构建产物
|
||||
├── index.html
|
||||
└── src/ ...
|
||||
```
|
||||
|
||||
### 方式 B:手动复制
|
||||
|
||||
| 复制源 | 复制到 |
|
||||
|--------|--------|
|
||||
| `build/web-desktop/*` | 主站静态目录下的 `cocos/` |
|
||||
| `web-template/cocos-bridge.js` | 与主站 `index.html` **同级** |
|
||||
|
||||
---
|
||||
|
||||
## 三、修改主站 index.html
|
||||
|
||||
### 1. 引入 cocos-bridge(在 Unity 脚本之前)
|
||||
|
||||
```html
|
||||
<script src="cocos-bridge.js"></script>
|
||||
```
|
||||
|
||||
`cocos-bridge.js` 会注册:
|
||||
|
||||
- `processData` / `processVehicleData` / `externalResult` / `externalLevelInfo` / `coinsData`
|
||||
- 等待 `window.unityInstance` 就绪
|
||||
|
||||
### 2. 删除 Unity 加载段
|
||||
|
||||
删除类似内容:
|
||||
|
||||
```html
|
||||
<script src="Build/build.loader.js"></script>
|
||||
<script>
|
||||
createUnityInstance(canvas, config, ...).then((unityInstance) => {
|
||||
window.unityInstance = unityInstance;
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3. 粘贴 Cocos 启动脚本
|
||||
|
||||
构建完成后运行(自动生成粘贴清单):
|
||||
|
||||
```bash
|
||||
node tools/patch-main-index.js build/web-desktop
|
||||
```
|
||||
|
||||
将输出的 `<script src="cocos/...">` 按主站实际路径写入 `index.html`。
|
||||
|
||||
**路径规则**:
|
||||
|
||||
- 主站页面与 `cocos/` 同级 → `src="cocos/src/system.bundle.js"`
|
||||
- 游戏在根目录 → 不加 `cocos/` 前缀
|
||||
|
||||
### 4. 游戏容器
|
||||
|
||||
保留或添加 Cocos 构建页中的结构:
|
||||
|
||||
```html
|
||||
<div id="GameDiv">
|
||||
<div id="Cocos3dGameContainer">
|
||||
<canvas id="GameCanvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
若主站原用 `#unity-canvas`,可只改 id 为 `GameCanvas`,或保留原 id 并在构建模板里改 canvas id(需改构建配置,一般直接用 Cocos 默认即可)。
|
||||
|
||||
### 5. unityInstance 无需手写
|
||||
|
||||
游戏启动后 `GameController` 会自动执行:
|
||||
|
||||
```javascript
|
||||
window.unityInstance = { SendMessage: ... };
|
||||
window.cocosIns = 同上;
|
||||
```
|
||||
|
||||
主站 Blockly 代码 **不用改**:
|
||||
|
||||
```javascript
|
||||
unityInstance.SendMessage("Player", "CallMove", n);
|
||||
unityInstance.SendMessage("GameController", "SwitchLevel", levelId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、本地预览
|
||||
|
||||
### 仅预览 Cocos 构建(未合并主站)
|
||||
|
||||
用 Cocos 构建面板里的 **运行**,或:
|
||||
|
||||
```bash
|
||||
cd build/web-desktop
|
||||
npx --yes serve . -p 8080
|
||||
# 打开 http://localhost:8080
|
||||
```
|
||||
|
||||
### 预览合并后的主站目录
|
||||
|
||||
```bash
|
||||
cd "/Users/liuyufei/tfrh/主站文件/主站/Template"
|
||||
npx --yes serve . -p 8080
|
||||
```
|
||||
|
||||
- 联调页:`http://localhost:8080/cocos-demo.html`
|
||||
- 若已改主站 index:`http://localhost:8080/index.html`
|
||||
|
||||
---
|
||||
|
||||
## 五、联调自检清单
|
||||
|
||||
| 步骤 | 期望 |
|
||||
|------|------|
|
||||
| 打开页面 | 控制台无 404(检查 cocos/*.js 路径) |
|
||||
| 加载完成 | `[GameController] unityInstance.SendMessage 已就绪` |
|
||||
| | `[tfrh] Cocos bridge ready` |
|
||||
| `SwitchLevel(1)` | 日志 `externalLevelInfo` |
|
||||
| `CallMove(2)` | 角色移动 |
|
||||
| `CallPlayerInfo` | 日志 `processData` |
|
||||
|
||||
---
|
||||
|
||||
## 六、生产环境注意
|
||||
|
||||
1. **HTTPS**:与 Unity 相同,WebGL/Canvas 在混合内容下可能受限
|
||||
2. **缓存**:构建带 MD5 时,更新后清 CDN 缓存
|
||||
3. **跨域**:`cocos/` 与主站同域部署最省事
|
||||
4. **回退**:可保留 Unity `Build/` 目录,通过配置开关切换加载 Unity 或 Cocos
|
||||
|
||||
---
|
||||
|
||||
## 七、关卡
|
||||
|
||||
已导入 Levels600 共 **600** 关,`SwitchLevel(1..600)` 与 Unity 一致。
|
||||
Reference in New Issue
Block a user