@coze-arch/cli 0.0.36-alpha.a7a716 → 0.0.36-alpha.af24fb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -114
- package/docs/deploy.md +10 -2
- package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +74 -18
- package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +1 -1
- package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +1 -1
- package/lib/__templates__/expo/client/metro.config.js +3 -1
- package/lib/__templates__/expo/pnpm-lock.yaml +5 -5
- package/lib/__templates__/expo/server/package.json +2 -2
- package/lib/__templates__/expo/server/src/index.ts +1 -1
- package/lib/__templates__/expo/template.config.js +11 -2
- package/lib/__templates__/native-static/.coze +2 -0
- package/lib/__templates__/native-static/scripts/serve.ps1 +7 -0
- package/lib/__templates__/nextjs/.coze +5 -0
- package/lib/__templates__/nextjs/package.json +1 -1
- package/lib/__templates__/nextjs/pnpm-lock.yaml +5 -5
- package/lib/__templates__/nextjs/scripts/build.ps1 +16 -0
- package/lib/__templates__/nextjs/scripts/dev.ps1 +63 -0
- package/lib/__templates__/nextjs/scripts/dev.sh +83 -2
- package/lib/__templates__/nextjs/scripts/prepare.ps1 +18 -0
- package/lib/__templates__/nextjs/scripts/start.ps1 +11 -0
- package/lib/__templates__/nextjs/scripts/validate.ps1 +8 -0
- package/lib/__templates__/nextjs/template.config.js +1 -1
- package/lib/__templates__/nuxt-vue/.coze +5 -0
- package/lib/__templates__/nuxt-vue/package.json +1 -1
- package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +5 -5
- package/lib/__templates__/nuxt-vue/scripts/build.ps1 +12 -0
- package/lib/__templates__/nuxt-vue/scripts/dev.ps1 +63 -0
- package/lib/__templates__/nuxt-vue/scripts/dev.sh +82 -1
- package/lib/__templates__/nuxt-vue/scripts/prepare.ps1 +12 -0
- package/lib/__templates__/nuxt-vue/scripts/start.ps1 +11 -0
- package/lib/__templates__/nuxt-vue/scripts/validate.ps1 +8 -0
- package/lib/__templates__/phaser/.coze +5 -0
- package/lib/__templates__/phaser/README.md +8 -0
- package/lib/__templates__/phaser/scripts/build.ps1 +12 -0
- package/lib/__templates__/phaser/scripts/dev.ps1 +49 -0
- package/lib/__templates__/phaser/scripts/prepare.ps1 +8 -0
- package/lib/__templates__/phaser/scripts/start.ps1 +49 -0
- package/lib/__templates__/phaser/scripts/validate.ps1 +7 -0
- package/lib/__templates__/phaser/src/global.d.ts +3 -0
- package/lib/__templates__/phaser/src/scene/BootScene.ts +4 -0
- package/lib/__templates__/phaser/src/scene/DevLoadingScene.ts +3 -0
- package/lib/__templates__/phaser/src/utils/mark-editable.ts +8 -1
- package/lib/__templates__/phaser/vite.config.ts +1 -1
- package/lib/__templates__/phaser-static/.coze +15 -0
- package/lib/__templates__/phaser-static/README.md +40 -0
- package/lib/__templates__/phaser-static/_gitignore +6 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
- package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/manifest.json +11 -0
- package/lib/__templates__/phaser-static/debug-runtime/flow-graph.json +20 -0
- package/lib/__templates__/phaser-static/index.html +17 -0
- package/lib/__templates__/phaser-static/scripts/serve.ps1 +7 -0
- package/lib/__templates__/phaser-static/src/assets.js +15 -0
- package/lib/__templates__/phaser-static/src/main.js +26 -0
- package/lib/__templates__/phaser-static/src/phaser.js +7 -0
- package/lib/__templates__/phaser-static/src/scene/BootScene.js +205 -0
- package/lib/__templates__/phaser-static/src/scene/DevLoadingScene.js +67 -0
- package/lib/__templates__/phaser-static/src/style.css +28 -0
- package/lib/__templates__/phaser-static/src/utils/asset-loader.js +267 -0
- package/lib/__templates__/phaser-static/src/utils/index.js +2 -0
- package/lib/__templates__/phaser-static/src/utils/mark-editable.js +3 -0
- package/lib/__templates__/phaser-static/template.config.js +35 -0
- package/lib/__templates__/pi-agent/package.json +1 -1
- package/lib/__templates__/pi-agent/pnpm-lock.yaml +5 -5
- package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +1 -1
- package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +150 -68
- package/lib/__templates__/taro/AGENTS.md +11 -7
- package/lib/__templates__/taro/README.md +4 -4
- package/lib/__templates__/taro/config/index.ts +10 -2
- package/lib/__templates__/taro/pnpm-lock.yaml +5 -5
- package/lib/__templates__/taro/server/package.json +1 -1
- package/lib/__templates__/taro/server/src/main.ts +8 -2
- package/lib/__templates__/templates.json +26 -1
- package/lib/__templates__/vite/.coze +5 -0
- package/lib/__templates__/vite/package.json +1 -1
- package/lib/__templates__/vite/pnpm-lock.yaml +5 -5
- package/lib/__templates__/vite/scripts/build.ps1 +16 -0
- package/lib/__templates__/vite/scripts/dev.ps1 +63 -0
- package/lib/__templates__/vite/scripts/dev.sh +82 -1
- package/lib/__templates__/vite/scripts/prepare.ps1 +18 -0
- package/lib/__templates__/vite/scripts/start.ps1 +11 -0
- package/lib/__templates__/vite/scripts/validate.ps1 +8 -0
- package/lib/__templates__/vite/template.config.js +1 -1
- package/lib/cli.js +435 -88
- package/lib/deploy/package-project.js +22 -4
- package/lib/deploy/package-project.py +18 -3
- package/package.json +1 -1
|
@@ -95,6 +95,7 @@ export class BootScene extends Phaser.Scene {
|
|
|
95
95
|
.sprite(centerX, centerY - 58, DEV_LOADING_RUNTIME_KEYS.texture)
|
|
96
96
|
.setScale(0.56)
|
|
97
97
|
.play(DEV_LOADING_RUNTIME_KEYS.animation),
|
|
98
|
+
{ label: '加载吉祥物' },
|
|
98
99
|
);
|
|
99
100
|
|
|
100
101
|
this.loadingText = markEditable(
|
|
@@ -107,11 +108,13 @@ export class BootScene extends Phaser.Scene {
|
|
|
107
108
|
LOADING_TEXT_STYLE,
|
|
108
109
|
)
|
|
109
110
|
.setOrigin(0.5),
|
|
111
|
+
{ label: '加载状态文案' },
|
|
110
112
|
);
|
|
111
113
|
|
|
112
114
|
this.progressBar = markEditable(
|
|
113
115
|
'boot.loading-progress-bar',
|
|
114
116
|
this.add.graphics(),
|
|
117
|
+
{ label: '加载进度条' },
|
|
115
118
|
);
|
|
116
119
|
this.renderProgressBar(0);
|
|
117
120
|
|
|
@@ -120,6 +123,7 @@ export class BootScene extends Phaser.Scene {
|
|
|
120
123
|
this.add
|
|
121
124
|
.text(centerX, centerY + 190, '0%', LOADING_TEXT_STYLE)
|
|
122
125
|
.setOrigin(0.5),
|
|
126
|
+
{ label: '加载进度文本' },
|
|
123
127
|
);
|
|
124
128
|
}
|
|
125
129
|
|
|
@@ -21,6 +21,7 @@ export class DevLoadingScene extends Phaser.Scene {
|
|
|
21
21
|
.sprite(centerX, centerY - 82, DEV_LOADING_RUNTIME_KEYS.texture)
|
|
22
22
|
.setScale(0.64)
|
|
23
23
|
.play(DEV_LOADING_RUNTIME_KEYS.animation),
|
|
24
|
+
{ label: '开发中吉祥物' },
|
|
24
25
|
);
|
|
25
26
|
|
|
26
27
|
markEditable(
|
|
@@ -33,6 +34,7 @@ export class DevLoadingScene extends Phaser.Scene {
|
|
|
33
34
|
fontStyle: 'bold',
|
|
34
35
|
})
|
|
35
36
|
.setOrigin(0.5),
|
|
37
|
+
{ label: '开发中标题' },
|
|
36
38
|
);
|
|
37
39
|
|
|
38
40
|
markEditable(
|
|
@@ -44,6 +46,7 @@ export class DevLoadingScene extends Phaser.Scene {
|
|
|
44
46
|
fontSize: '18px',
|
|
45
47
|
})
|
|
46
48
|
.setOrigin(0.5),
|
|
49
|
+
{ label: '开发中说明文案' },
|
|
47
50
|
);
|
|
48
51
|
|
|
49
52
|
const loadingDots = Array.from({ length: 3 }, (_value, index) =>
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type Phaser from 'phaser';
|
|
2
2
|
|
|
3
|
+
export interface MarkEditableOptions {
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
export const markEditable = <T extends Phaser.GameObjects.GameObject>(
|
|
4
8
|
locator: string,
|
|
5
9
|
gameObject: T,
|
|
6
|
-
|
|
10
|
+
options?: MarkEditableOptions,
|
|
11
|
+
): T =>
|
|
12
|
+
window.PhaserBridge?.markEditable?.(locator, gameObject, options) ??
|
|
13
|
+
gameObject;
|
|
@@ -4,7 +4,7 @@ import { defineConfig, type Plugin } from "vite";
|
|
|
4
4
|
import serveStatic from "serve-static";
|
|
5
5
|
|
|
6
6
|
const DEV_PHASER_BRIDGE_URL =
|
|
7
|
-
"https://
|
|
7
|
+
"https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-game/js/phaser-bridge.min.js";
|
|
8
8
|
|
|
9
9
|
function injectDevPhaserBridge(): Plugin {
|
|
10
10
|
return {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
entrypoint = "index.html"
|
|
3
|
+
requires = ["python-3.12"]
|
|
4
|
+
project_type = "game"
|
|
5
|
+
game_type = "phaser"
|
|
6
|
+
|
|
7
|
+
[dev]
|
|
8
|
+
build = []
|
|
9
|
+
run = ["sh", "-c", "python -m http.server ${DEPLOY_RUN_PORT} --bind 0.0.0.0"]
|
|
10
|
+
run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/serve.ps1"]
|
|
11
|
+
|
|
12
|
+
[deploy]
|
|
13
|
+
build = []
|
|
14
|
+
run = ["sh", "-c", "python -m http.server ${DEPLOY_RUN_PORT} --bind 0.0.0.0"]
|
|
15
|
+
run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/serve.ps1"]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# <%= appName %>
|
|
2
|
+
|
|
3
|
+
这是一个基于浏览器原生 JavaScript ESM 的 Phaser 2D 游戏项目,由扣子编程 CLI 创建。
|
|
4
|
+
|
|
5
|
+
Phaser 3.90.0 与 Phaser Bridge 从 CDN 加载;项目不依赖 npm、Vite 或 TypeScript。请用静态 HTTP 服务访问,直接打开 `index.html` 不支持 ESM 模块与素材加载。
|
|
6
|
+
|
|
7
|
+
## 快速开始
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
coze-dev dev
|
|
11
|
+
coze-dev build
|
|
12
|
+
coze-dev start
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`build` 没有编译步骤;开发与生产预览均由 Python `http.server` 提供静态文件服务。
|
|
16
|
+
|
|
17
|
+
## 文件结构
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
├── assets/ # 图片、序列帧、视频和音频
|
|
21
|
+
├── debug-runtime/ # 调试 Flow
|
|
22
|
+
├── src/assets.js # 素材 key 与路径
|
|
23
|
+
├── src/main.js # 游戏入口
|
|
24
|
+
├── src/phaser.js # Phaser 全局对象的 ESM 包装
|
|
25
|
+
├── src/scene/BootScene.js # 启动与全量加载
|
|
26
|
+
└── src/utils/asset-loader.js # 批量和单素材加载
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- 素材按类型放在 `assets/`,并登记到 `src/assets.js` 对应的分类表。
|
|
30
|
+
- 序列帧只登记文件夹;Loader 从 `manifest.json` 读取帧数和帧率。
|
|
31
|
+
- `BootScene` 加载游戏素材;运行时可用 `loadAsset(this, key)` 单独加载。
|
|
32
|
+
- 所有本地模块都使用原生 ESM 的显式 `.js` 后缀。
|
|
33
|
+
|
|
34
|
+
## 可视化编辑标识
|
|
35
|
+
|
|
36
|
+
用 `markEditable` 标记可在编辑器中调整的对象;第三个参数可选,仅用于编辑器展示名称:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
markEditable('ui.start-button', button, { label: '开始按钮' });
|
|
40
|
+
```
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0001.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0002.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0003.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0004.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0005.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0006.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0007.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0008.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0009.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0010.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0011.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0012.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0013.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0014.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0015.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0016.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0017.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0018.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0019.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0020.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0021.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0022.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0023.png
ADDED
|
Binary file
|
package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0024.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"graphs": [
|
|
4
|
+
{
|
|
5
|
+
"id": "main",
|
|
6
|
+
"label": "主流程",
|
|
7
|
+
"nodes": [
|
|
8
|
+
{
|
|
9
|
+
"id": "start",
|
|
10
|
+
"label": "开始游戏",
|
|
11
|
+
"input_schema": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"transitions": []
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="description" content="Phaser 纯静态游戏模板" />
|
|
7
|
+
<title><%= appName %></title>
|
|
8
|
+
<link rel="icon" href="data:," />
|
|
9
|
+
<link rel="stylesheet" href="./src/style.css" />
|
|
10
|
+
<script src="https://unpkg.byted-static.com/phaser/3.90.0/dist/phaser.min.js"></script>
|
|
11
|
+
<script src="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-game/js/phaser-bridge.min.js"></script>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<main id="game" aria-label="Phaser game canvas"></main>
|
|
15
|
+
<script type="module" src="./src/main.js"></script>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const IMAGES = {};
|
|
2
|
+
|
|
3
|
+
export const IMAGE_SEQUENCES = {
|
|
4
|
+
'coze-game-loading': 'assets/image_sequence/coze-game-loading',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const VIDEOS = {};
|
|
8
|
+
|
|
9
|
+
export const AUDIOS = {};
|
|
10
|
+
|
|
11
|
+
// 注册素材到 PhaserBridge,可以在扣子网页游戏开发中定位
|
|
12
|
+
window.PhaserBridge?.markImageAssetMap?.(IMAGES);
|
|
13
|
+
window.PhaserBridge?.markImageSequenceAssetMap?.(IMAGE_SEQUENCES);
|
|
14
|
+
window.PhaserBridge?.markVideoAssetMap?.(VIDEOS);
|
|
15
|
+
window.PhaserBridge?.markAudioAssetMap?.(AUDIOS);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Phaser } from './phaser.js';
|
|
2
|
+
import { BootScene } from './scene/BootScene.js';
|
|
3
|
+
import { DevLoadingScene } from './scene/DevLoadingScene.js';
|
|
4
|
+
|
|
5
|
+
const createGame = () =>
|
|
6
|
+
new Phaser.Game({
|
|
7
|
+
type: Phaser.AUTO,
|
|
8
|
+
pixelArt: true,
|
|
9
|
+
parent: 'game',
|
|
10
|
+
// TODO 根据游戏的要求进行尺寸
|
|
11
|
+
width: 540,
|
|
12
|
+
height: 960,
|
|
13
|
+
backgroundColor: '#ffffff',
|
|
14
|
+
scale: {
|
|
15
|
+
mode: Phaser.Scale.FIT,
|
|
16
|
+
autoCenter: Phaser.Scale.CENTER_BOTH,
|
|
17
|
+
},
|
|
18
|
+
scene: [BootScene, DevLoadingScene],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// 注册游戏到 PhaserBridge,可以在扣子网页游戏开发中编辑评论
|
|
22
|
+
if (window.PhaserBridge) {
|
|
23
|
+
window.PhaserBridge.bind({ launchGame: createGame });
|
|
24
|
+
} else {
|
|
25
|
+
createGame();
|
|
26
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { Phaser } from '../phaser.js';
|
|
2
|
+
import {
|
|
3
|
+
getAssetLabelFromFileKey,
|
|
4
|
+
getImageSequenceRuntimeKeys,
|
|
5
|
+
loadAssets,
|
|
6
|
+
markEditable,
|
|
7
|
+
registerImageSequenceAnimations,
|
|
8
|
+
} from '../utils/index.js';
|
|
9
|
+
import { AUDIOS, IMAGES, IMAGE_SEQUENCES, VIDEOS } from '../assets.js';
|
|
10
|
+
|
|
11
|
+
const LOADING_TEXT_STYLE = {
|
|
12
|
+
color: '#71717a',
|
|
13
|
+
fontFamily: '"PingFang SC", "Microsoft YaHei", sans-serif',
|
|
14
|
+
fontSize: '18px',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DEV_LOADING_ASSET_KEY = 'coze-game-loading';
|
|
18
|
+
const devLoadingSource = IMAGE_SEQUENCES[DEV_LOADING_ASSET_KEY];
|
|
19
|
+
|
|
20
|
+
if (!devLoadingSource) {
|
|
21
|
+
throw new Error('Image sequence asset not found: ' + DEV_LOADING_ASSET_KEY);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const BOOT_IMAGE_SEQUENCES = {
|
|
25
|
+
[DEV_LOADING_ASSET_KEY]: devLoadingSource,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const BOOT_ASSETS = {
|
|
29
|
+
imageSequences: BOOT_IMAGE_SEQUENCES,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const GAME_IMAGE_SEQUENCES = Object.fromEntries(
|
|
33
|
+
Object.entries(IMAGE_SEQUENCES).filter(
|
|
34
|
+
([assetKey]) => assetKey !== DEV_LOADING_ASSET_KEY,
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const GAME_ASSETS = {
|
|
39
|
+
images: IMAGES,
|
|
40
|
+
imageSequences: GAME_IMAGE_SEQUENCES,
|
|
41
|
+
videos: VIDEOS,
|
|
42
|
+
audios: AUDIOS,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const DEV_LOADING_RUNTIME_KEYS =
|
|
46
|
+
getImageSequenceRuntimeKeys(DEV_LOADING_ASSET_KEY);
|
|
47
|
+
|
|
48
|
+
export class BootScene extends Phaser.Scene {
|
|
49
|
+
loadingText;
|
|
50
|
+
|
|
51
|
+
progressBar;
|
|
52
|
+
|
|
53
|
+
progressText;
|
|
54
|
+
|
|
55
|
+
loadFailed = false;
|
|
56
|
+
|
|
57
|
+
constructor() {
|
|
58
|
+
super('boot');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
preload() {
|
|
62
|
+
loadAssets(this, BOOT_ASSETS);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
create() {
|
|
66
|
+
registerImageSequenceAnimations(this, BOOT_IMAGE_SEQUENCES);
|
|
67
|
+
this.createLoadingView();
|
|
68
|
+
|
|
69
|
+
const queuedFileCount = loadAssets(this, GAME_ASSETS);
|
|
70
|
+
if (queuedFileCount === 0) {
|
|
71
|
+
this.finishLoading();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.load.on(Phaser.Loader.Events.FILE_PROGRESS, this.onGameFile, this);
|
|
76
|
+
this.load.on(Phaser.Loader.Events.PROGRESS, this.onProgress, this);
|
|
77
|
+
this.load.once(
|
|
78
|
+
Phaser.Loader.Events.FILE_LOAD_ERROR,
|
|
79
|
+
this.onLoadError,
|
|
80
|
+
this,
|
|
81
|
+
);
|
|
82
|
+
this.load.once(Phaser.Loader.Events.COMPLETE, this.finishLoading, this);
|
|
83
|
+
this.load.start();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
createLoadingView() {
|
|
87
|
+
const { centerX, centerY } = this.cameras.main;
|
|
88
|
+
|
|
89
|
+
markEditable(
|
|
90
|
+
'boot.loading-mascot',
|
|
91
|
+
this.add
|
|
92
|
+
.sprite(centerX, centerY - 58, DEV_LOADING_RUNTIME_KEYS.texture)
|
|
93
|
+
.setScale(0.56)
|
|
94
|
+
.play(DEV_LOADING_RUNTIME_KEYS.animation),
|
|
95
|
+
{ label: '加载吉祥物' },
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.loadingText = markEditable(
|
|
99
|
+
'boot.loading-text',
|
|
100
|
+
this.add
|
|
101
|
+
.text(centerX, centerY + 120, '正在加载游戏资源…', LOADING_TEXT_STYLE)
|
|
102
|
+
.setOrigin(0.5),
|
|
103
|
+
{ label: '加载状态文案' },
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
this.progressBar = markEditable(
|
|
107
|
+
'boot.loading-progress-bar',
|
|
108
|
+
this.add.graphics(),
|
|
109
|
+
{ label: '加载进度条' },
|
|
110
|
+
);
|
|
111
|
+
this.renderProgressBar(0);
|
|
112
|
+
|
|
113
|
+
this.progressText = markEditable(
|
|
114
|
+
'boot.loading-progress',
|
|
115
|
+
this.add
|
|
116
|
+
.text(centerX, centerY + 190, '0%', LOADING_TEXT_STYLE)
|
|
117
|
+
.setOrigin(0.5),
|
|
118
|
+
{ label: '加载进度文本' },
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
onGameFile = file => {
|
|
123
|
+
const assetLabel = getAssetLabelFromFileKey(file.key, GAME_ASSETS);
|
|
124
|
+
this.loadingText?.setText('正在加载' + assetLabel);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
onProgress = progress => {
|
|
128
|
+
this.renderProgressBar(progress);
|
|
129
|
+
this.progressText?.setText(Math.round(progress * 100) + '%');
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
onLoadError = file => {
|
|
133
|
+
this.loadFailed = true;
|
|
134
|
+
const assetLabel = getAssetLabelFromFileKey(file.key, GAME_ASSETS);
|
|
135
|
+
this.loadingText?.setText(assetLabel + '加载失败');
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
renderProgressBar(progress) {
|
|
139
|
+
if (!this.progressBar) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const { centerX, centerY } = this.cameras.main;
|
|
144
|
+
const width = 300;
|
|
145
|
+
const height = 14;
|
|
146
|
+
const x = centerX - width / 2;
|
|
147
|
+
const y = centerY + 154;
|
|
148
|
+
const padding = 3;
|
|
149
|
+
const innerWidth = width - padding * 2;
|
|
150
|
+
const filledWidth = Phaser.Math.Clamp(progress, 0, 1) * innerWidth;
|
|
151
|
+
|
|
152
|
+
this.progressBar.clear();
|
|
153
|
+
this.progressBar.fillStyle(0x102536, 0.12);
|
|
154
|
+
this.progressBar.fillRoundedRect(x, y, width, height, height / 2);
|
|
155
|
+
this.progressBar.lineStyle(2, 0x102536, 0.28);
|
|
156
|
+
this.progressBar.strokeRoundedRect(x, y, width, height, height / 2);
|
|
157
|
+
|
|
158
|
+
if (filledWidth <= 0) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.progressBar.fillStyle(0xef648d, 1);
|
|
163
|
+
this.progressBar.fillRoundedRect(
|
|
164
|
+
x + padding,
|
|
165
|
+
y + padding,
|
|
166
|
+
filledWidth,
|
|
167
|
+
height - padding * 2,
|
|
168
|
+
(height - padding * 2) / 2,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
this.progressBar.fillStyle(0x165ca8, 1);
|
|
172
|
+
this.progressBar.fillCircle(
|
|
173
|
+
Phaser.Math.Clamp(
|
|
174
|
+
x + padding + filledWidth,
|
|
175
|
+
x + padding + 5,
|
|
176
|
+
x + width - padding - 5,
|
|
177
|
+
),
|
|
178
|
+
y + height / 2,
|
|
179
|
+
5,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
finishLoading = () => {
|
|
184
|
+
this.removeLoaderListeners();
|
|
185
|
+
|
|
186
|
+
if (this.loadFailed) {
|
|
187
|
+
this.progressText?.setText('请刷新页面重试');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
registerImageSequenceAnimations(this, GAME_IMAGE_SEQUENCES);
|
|
192
|
+
this.scene.start('dev-loading');
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
removeLoaderListeners() {
|
|
196
|
+
this.load.off(Phaser.Loader.Events.FILE_PROGRESS, this.onGameFile, this);
|
|
197
|
+
this.load.off(Phaser.Loader.Events.PROGRESS, this.onProgress, this);
|
|
198
|
+
this.load.off(
|
|
199
|
+
Phaser.Loader.Events.FILE_LOAD_ERROR,
|
|
200
|
+
this.onLoadError,
|
|
201
|
+
this,
|
|
202
|
+
);
|
|
203
|
+
this.load.off(Phaser.Loader.Events.COMPLETE, this.finishLoading, this);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Phaser } from '../phaser.js';
|
|
2
|
+
import { markEditable } from '../utils/index.js';
|
|
3
|
+
import { DEV_LOADING_RUNTIME_KEYS } from './BootScene.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 本场景用于为兜底场景展示
|
|
7
|
+
*/
|
|
8
|
+
export class DevLoadingScene extends Phaser.Scene {
|
|
9
|
+
constructor() {
|
|
10
|
+
super('dev-loading');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
create() {
|
|
14
|
+
const { centerX, centerY } = this.cameras.main;
|
|
15
|
+
|
|
16
|
+
markEditable(
|
|
17
|
+
'dev-loading.mascot',
|
|
18
|
+
this.add
|
|
19
|
+
.sprite(centerX, centerY - 82, DEV_LOADING_RUNTIME_KEYS.texture)
|
|
20
|
+
.setScale(0.64)
|
|
21
|
+
.play(DEV_LOADING_RUNTIME_KEYS.animation),
|
|
22
|
+
{ label: '开发中吉祥物' },
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
markEditable(
|
|
26
|
+
'dev-loading.title',
|
|
27
|
+
this.add
|
|
28
|
+
.text(centerX, centerY + 92, '游戏开发中', {
|
|
29
|
+
color: '#18181b',
|
|
30
|
+
fontFamily: '"PingFang SC", "Microsoft YaHei", sans-serif',
|
|
31
|
+
fontSize: '32px',
|
|
32
|
+
fontStyle: 'bold',
|
|
33
|
+
})
|
|
34
|
+
.setOrigin(0.5),
|
|
35
|
+
{ label: '开发中标题' },
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
markEditable(
|
|
39
|
+
'dev-loading.description',
|
|
40
|
+
this.add
|
|
41
|
+
.text(centerX, centerY + 138, '请稍后,游戏世界即将呈现', {
|
|
42
|
+
color: '#71717a',
|
|
43
|
+
fontFamily: '"PingFang SC", "Microsoft YaHei", sans-serif',
|
|
44
|
+
fontSize: '18px',
|
|
45
|
+
})
|
|
46
|
+
.setOrigin(0.5),
|
|
47
|
+
{ label: '开发中说明文案' },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const loadingDots = Array.from({ length: 3 }, (_value, index) =>
|
|
51
|
+
this.add.circle(centerX + (index - 1) * 18, centerY + 178, 4, 0xf43f75),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
loadingDots.forEach((dot, index) => {
|
|
55
|
+
this.tweens.add({
|
|
56
|
+
targets: dot,
|
|
57
|
+
alpha: 0.25,
|
|
58
|
+
scale: 0.7,
|
|
59
|
+
duration: 520,
|
|
60
|
+
delay: index * 160,
|
|
61
|
+
ease: 'Sine.inOut',
|
|
62
|
+
repeat: -1,
|
|
63
|
+
yoyo: true,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: dark;
|
|
3
|
+
font-family: Arial, sans-serif;
|
|
4
|
+
background: #000;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
* {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
html,
|
|
12
|
+
body,
|
|
13
|
+
#game {
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
margin: 0;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
background: #000;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#game {
|
|
22
|
+
min-width: 0;
|
|
23
|
+
min-height: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#game canvas {
|
|
27
|
+
display: block;
|
|
28
|
+
}
|