@ganziliang/desktop-pet 0.1.0 → 0.1.1
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 +17 -8
- package/assets/awaken/README.md +3 -2
- package/assets/outfits.json +1 -0
- package/main.js +10 -2
- package/package.json +1 -1
- package/renderer/app.js +22 -10
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@ desktop-pet
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
包内自带 electron 依赖,命令行参数原样透传给主进程(`--snapshot`、`--anim=<walk|run|swim|awaken:seraph>`、`--no-auto`)。
|
|
27
|
+
首次启动会先下载 Electron 运行时(约 100MB,只在第一次),终端会打印 `Downloading Electron binary...`。
|
|
27
28
|
只发布运行需要的素材,`assets/source/`(生图原始图,约 39MB)与 `character_green*.png` 不进包。
|
|
28
29
|
|
|
29
30
|
|
|
@@ -59,21 +60,29 @@ desktop-pet
|
|
|
59
60
|
和特效事件共用同一条时间轴,所以「动作推到哪一帧」和「特效炸在哪一刻」是对死的:
|
|
60
61
|
|
|
61
62
|
```
|
|
62
|
-
0ms
|
|
63
|
-
180ms
|
|
64
|
-
560ms
|
|
63
|
+
0ms 切入(默认不铺暗幕,桌面直接透出去)
|
|
64
|
+
180ms 窗口放大(只向上、向两侧长,脚下那条线和水平中心都不动,所以看不到变形)
|
|
65
|
+
560ms 角色以「蓄力」序列帧亮相
|
|
65
66
|
蓄力 4 帧 × 360ms:合手聚气 → 抬手 → 上举 → 蓄力顶点
|
|
66
67
|
同时跑魔法阵、向心汇聚、脚下螺旋
|
|
67
68
|
2000ms 爆发(revealAt):白闪 + 抖屏 + 冲击波,切到「爆发」序列帧
|
|
68
69
|
爆发 4 帧 × 300ms:张臂 → 光爆 → 释放 → 收势
|
|
69
70
|
2200ms 光柱冲天 + 主爆星屑
|
|
70
71
|
2650ms 技能名落字
|
|
71
|
-
4400ms
|
|
72
|
-
5700ms
|
|
72
|
+
4400ms 窗口收回(同样只向上向两侧收,角色不动)
|
|
73
|
+
5700ms 回到站立
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
**演出期间窗口背景完全透明**:桌面上只看得到角色和光效,不会出现一块暗色矩形。
|
|
77
|
+
这一点靠 `assets/outfits.json` 的 `curtain` 控制,默认 `false`:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{ "curtain": false }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
要不要铺暗幕,取决于壁纸:加色混合的光效(金光、雷光)在**亮色壁纸**上本来就很难拉开对比,
|
|
84
|
+
垫一层暗底才亮得起来 —— 想回到老的「黑屏切入」就把 `curtain` 改成 `true`(代价是屏幕上会多一个暗窗)。
|
|
85
|
+
关掉时光效照跑,只是没有暗底垫着。
|
|
77
86
|
|
|
78
87
|
### 素材是两步,不是一步
|
|
79
88
|
|
|
@@ -315,7 +324,7 @@ npx electron . --snapshot
|
|
|
315
324
|
# --anim=<walk|run|swim> 先把角色摆到某个动作再截,用来查动作素材
|
|
316
325
|
npx electron . --snapshot --anim=swim
|
|
317
326
|
# 觉醒也能截:--anim=awaken:<id>;换 PET_SNAPSHOT_MS 就能逐帧看整场演出
|
|
318
|
-
PET_SNAPSHOT_MS=1200 npx electron . --snapshot --anim=awaken:seraph #
|
|
327
|
+
PET_SNAPSHOT_MS=1200 npx electron . --snapshot --anim=awaken:seraph # 蓄力:魔法阵 + 聚气
|
|
319
328
|
PET_SNAPSHOT_MS=3400 npx electron . --snapshot --anim=awaken:seraph # 亮相 + 技能名
|
|
320
329
|
PET_SNAPSHOT_MS=6500 npx electron . --snapshot --anim=awaken:seraph # 收招:窗口应该已还原
|
|
321
330
|
# PET_SNAPSHOT_MS 改截帧时刻。用两个不同值各截一张做差分,就能证明逐帧动画真的在推进:
|
package/assets/awaken/README.md
CHANGED
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
```js
|
|
19
19
|
sheet: { charge: { at: 560, step: 360 }, burst: { at: 2000, step: 300 } },
|
|
20
20
|
revealAt: 2000, // = burst.at,爆发那一刻(白闪 + 抖屏)
|
|
21
|
-
closeAt: 4400, //
|
|
21
|
+
closeAt: 4400, // 窗口收回(默认铺暗幕;见下)
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
蓄力 4 帧 × 360ms(560→1640),爆发 4 帧 × 300ms(2000→2900),之后停在最后一帧收招式。
|
|
25
|
-
|
|
25
|
+
暗幕默认**关**(`assets/outfits.json` 的 `curtain: false`):演出期间窗口背景全透明,墙上不会出现暗色矩形。
|
|
26
|
+
改成 `true` 就回到「黑屏切入」—— 起步全黑、`charge.at` 提到 0.6 的柔暗底,蓄力动作依然看得见。
|
|
26
27
|
|
|
27
28
|
## 怎么加一张
|
|
28
29
|
|
package/assets/outfits.json
CHANGED
package/main.js
CHANGED
|
@@ -128,12 +128,20 @@ function loadSpriteManifest() {
|
|
|
128
128
|
* 而不会因为少个 json 让整个右键菜单空掉。
|
|
129
129
|
*/
|
|
130
130
|
function loadOutfits() {
|
|
131
|
-
const fallback = {
|
|
131
|
+
const fallback = {
|
|
132
|
+
stage: {},
|
|
133
|
+
list: [{ id: 'seraph', name: '圣光 · 炽天使', skill: '圣裁之光' }],
|
|
134
|
+
curtain: false,
|
|
135
|
+
};
|
|
132
136
|
try {
|
|
133
137
|
const raw = JSON.parse(fs.readFileSync(OUTFITS_FILE, 'utf8'));
|
|
134
138
|
return {
|
|
135
139
|
stage: raw.stage || {},
|
|
136
140
|
list: Array.isArray(raw.list) && raw.list.length ? raw.list : fallback.list,
|
|
141
|
+
// 觉醒暗幕开关。默认关:演出期间窗口背景完全透明,桌面上只有角色和光效,
|
|
142
|
+
// 不会出现一块暗色矩形。显式写 true 才回到旧的「黑屏切入」
|
|
143
|
+
// (亮色壁纸下加色光效更清楚,代价是屏幕上多一个暗窗)。
|
|
144
|
+
curtain: raw.curtain === true,
|
|
137
145
|
};
|
|
138
146
|
} catch {
|
|
139
147
|
return fallback;
|
|
@@ -1002,7 +1010,7 @@ function registerIpc() {
|
|
|
1002
1010
|
roamGapMs: Number(process.env.PET_ROAM_GAP_MS) || null,
|
|
1003
1011
|
assets: spriteAssets(),
|
|
1004
1012
|
// 觉醒清单交给渲染层:菜单里的名字、角色缩放比例、窗口目标规模都从这取
|
|
1005
|
-
awaken: { list: outfits.list, stage: outfits.stage },
|
|
1013
|
+
awaken: { list: outfits.list, stage: outfits.stage, curtain: outfits.curtain },
|
|
1006
1014
|
httpPort: HTTP_PORT,
|
|
1007
1015
|
}));
|
|
1008
1016
|
|
package/package.json
CHANGED
package/renderer/app.js
CHANGED
|
@@ -716,18 +716,28 @@ function applyDemo(anim) {
|
|
|
716
716
|
|
|
717
717
|
/**
|
|
718
718
|
* 一场觉醒演出的时间线(毫秒):
|
|
719
|
-
* 0
|
|
719
|
+
* 0 切入(curtain=true 时是黑屏,默认直接把桌面透出去)
|
|
720
720
|
* 180 窗口放大 + 换上战斗服立绘 + 「镜头推近」
|
|
721
|
-
* revealAt
|
|
722
|
-
* closeAt 暗幕再进 +
|
|
721
|
+
* revealAt 亮相 + 白闪 + 画面抖动 + 主爆发(具体特效由各套觉醒的 build 排)
|
|
722
|
+
* closeAt 暗幕再进 + 窗口收回
|
|
723
723
|
* duration 暗幕退掉,回到站立
|
|
724
724
|
*
|
|
725
|
-
*
|
|
726
|
-
*
|
|
725
|
+
* 窗口尺寸是在「画面已经被盖住」之后才改的。默认 curtain=false,也就是不铺暗幕:
|
|
726
|
+
* 窗口只向上、向两侧长(见 main.js 的 awakenTarget),角色脚下那条线和水平中心都不动,
|
|
727
|
+
* 所以窗口变形这一帧本来就看不出来 —— 没必要为了藏它而多一块暗色矩形。
|
|
728
|
+
* 亮色壁纸下想让金光/雷光更亮,可以在 assets/outfits.json 里把 curtain 改成 true。
|
|
727
729
|
*/
|
|
728
730
|
|
|
729
731
|
let awakenToken = 0; // 每次演出一个令牌;旧演出的挂起回调拿它对不上号就自己失效
|
|
730
732
|
|
|
733
|
+
/**
|
|
734
|
+
* 暗幕开关(assets/outfits.json 的 curtain,默认 false = 不铺暗色底)。
|
|
735
|
+
* 关掉时所有 dim 的 alpha 都走 0:FX 那套渐变/时间轴一行不用改,
|
|
736
|
+
* 只是每帧的 drawDim 直接 return,画布上除角色和光效之外没有别的东西。
|
|
737
|
+
*/
|
|
738
|
+
const curtainOn = () => cfg.awaken?.curtain === true;
|
|
739
|
+
const curtainAlpha = (a) => (curtainOn() ? a : 0);
|
|
740
|
+
|
|
731
741
|
/** 角色当前的屏幕位置,事件在触发的那一刻现取(窗口刚被放大过) */
|
|
732
742
|
/**
|
|
733
743
|
* 觉醒演出的逐帧播放:直接写 backgroundPositionX,不走 steps() 帧动画。
|
|
@@ -806,8 +816,8 @@ async function playAwaken(id, { auto = false } = {}) {
|
|
|
806
816
|
}
|
|
807
817
|
holdShow();
|
|
808
818
|
|
|
809
|
-
// 1)
|
|
810
|
-
FX.dim(def.dimAlpha, 170, def.palette.stroke);
|
|
819
|
+
// 1) 先把屏幕压黑(curtain=false 时是 0,等于什么都不铺)
|
|
820
|
+
FX.dim(curtainAlpha(def.dimAlpha), 170, def.palette.stroke);
|
|
811
821
|
|
|
812
822
|
// 2) 暗幕盖满之后再把窗口放大,同时按新窗口高度算「镜头推近」的倍数
|
|
813
823
|
await new Promise((r) => setTimeout(r, 180));
|
|
@@ -858,7 +868,8 @@ async function playAwaken(id, { auto = false } = {}) {
|
|
|
858
868
|
|
|
859
869
|
// 蓄力:暗幕从全黑提到 0.6(soft),让玩家真的能看到蓄力动作在演,
|
|
860
870
|
// 而不是从头到尾一层黑幕摆完五秒 —— 那多帧素材就白做了。
|
|
861
|
-
|
|
871
|
+
// curtain=false 时这层不铺:桌面本来就透得出来,角色一直看得见。
|
|
872
|
+
if (sheet.charge && curtainOn()) {
|
|
862
873
|
events.push([sheet.charge.at, () => FX.dim(0.6, 420, def.palette.stroke, true)]);
|
|
863
874
|
}
|
|
864
875
|
|
|
@@ -885,8 +896,9 @@ async function playAwaken(id, { auto = false } = {}) {
|
|
|
885
896
|
def.closeAt,
|
|
886
897
|
() => {
|
|
887
898
|
if (token !== awakenToken) return;
|
|
888
|
-
FX.dim(def.dimAlpha, 240, def.palette.stroke);
|
|
889
|
-
//
|
|
899
|
+
FX.dim(curtainAlpha(def.dimAlpha), 240, def.palette.stroke);
|
|
900
|
+
// 窗口变回去的那一帧本来就不用遮(窗口只向上向两侧收回,角色不动),
|
|
901
|
+
// 这里留着只是让 curtain=true 的旧路径一样安全
|
|
890
902
|
setTimeout(() => {
|
|
891
903
|
if (token !== awakenToken) return;
|
|
892
904
|
el.stage.classList.remove('awakening', 'flashing', 'shaking');
|