feat: 优化关卡以及选关 UI
This commit is contained in:
@@ -75,21 +75,21 @@
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 516
|
||||
},
|
||||
{
|
||||
"__id__": 518
|
||||
},
|
||||
{
|
||||
"__id__": 520
|
||||
},
|
||||
{
|
||||
"__id__": 522
|
||||
},
|
||||
{
|
||||
"__id__": 524
|
||||
},
|
||||
{
|
||||
"__id__": 526
|
||||
},
|
||||
{
|
||||
"__id__": 528
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 524
|
||||
"__id__": 530
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -9476,19 +9476,22 @@
|
||||
},
|
||||
{
|
||||
"__id__": 491
|
||||
},
|
||||
{
|
||||
"__id__": 511
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 511
|
||||
"__id__": 517
|
||||
},
|
||||
{
|
||||
"__id__": 513
|
||||
"__id__": 519
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 515
|
||||
"__id__": 521
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -9565,7 +9568,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 97.33,
|
||||
"y": 203.25,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -9577,9 +9580,9 @@
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0.738,
|
||||
"y": 0.738,
|
||||
"z": 0.738
|
||||
"x": 1.099,
|
||||
"y": 1.099,
|
||||
"z": 1.099
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 1073741824,
|
||||
@@ -9604,7 +9607,7 @@
|
||||
"__id__": 395
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 401
|
||||
@@ -9876,7 +9879,7 @@
|
||||
"__id__": 393
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 407
|
||||
@@ -10012,7 +10015,7 @@
|
||||
"__id__": 393
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 413
|
||||
@@ -11411,7 +11414,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -244.611,
|
||||
"y": -168.276,
|
||||
"y": -130.956,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -11911,7 +11914,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 256.705,
|
||||
"y": -171.25,
|
||||
"y": -133.93,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -12377,6 +12380,142 @@
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "pose",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 392
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 512
|
||||
},
|
||||
{
|
||||
"__id__": 514
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 516
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -13.206,
|
||||
"y": 1647.284,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.088,
|
||||
"y": 1.088,
|
||||
"z": 1.088
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 1073741824,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 511
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 513
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 308.05999755859375,
|
||||
"height": 170.60000610351562
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.49344282189031463,
|
||||
"y": 0.5101406545465734
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "4c/jNwWQBLtp+QzZzYvv05"
|
||||
},
|
||||
{
|
||||
"__type__": "sp.Skeleton",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 511
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 515
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_skeletonData": {
|
||||
"__uuid__": "443e4aca-50d0-4d49-9c21-c1daeb44116d",
|
||||
"__expectedType__": "sp.SkeletonData"
|
||||
},
|
||||
"defaultSkin": "default",
|
||||
"defaultAnimation": "1",
|
||||
"_premultipliedAlpha": true,
|
||||
"_timeScale": 1,
|
||||
"_preCacheMode": 0,
|
||||
"_cacheMode": 0,
|
||||
"_sockets": [],
|
||||
"_useTint": false,
|
||||
"_debugMesh": false,
|
||||
"_debugBones": false,
|
||||
"_debugSlots": false,
|
||||
"_enableBatch": false,
|
||||
"loop": false,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "fehSRPzc5Axb5i4/efoZga"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "66Wms7/8FMI67++4Kw81Ab",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
@@ -12387,7 +12526,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 512
|
||||
"__id__": 518
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
@@ -12415,7 +12554,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 514
|
||||
"__id__": 520
|
||||
},
|
||||
"_alignFlags": 20,
|
||||
"_target": null,
|
||||
@@ -12464,7 +12603,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 517
|
||||
"__id__": 523
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
@@ -12492,7 +12631,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 519
|
||||
"__id__": 525
|
||||
},
|
||||
"_alignFlags": 0,
|
||||
"_target": null,
|
||||
@@ -12528,7 +12667,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 521
|
||||
"__id__": 527
|
||||
},
|
||||
"_clip": null,
|
||||
"_loop": false,
|
||||
@@ -12550,7 +12689,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 523
|
||||
"__id__": 529
|
||||
},
|
||||
"inputLayout": {
|
||||
"__id__": 307
|
||||
@@ -12670,6 +12809,12 @@
|
||||
"caidaiSkeleton": {
|
||||
"__id__": 389
|
||||
},
|
||||
"poseNode": {
|
||||
"__id__": 511
|
||||
},
|
||||
"poseSkeleton": {
|
||||
"__id__": 514
|
||||
},
|
||||
"clickAudio": {
|
||||
"__uuid__": "a68a6314-fb7c-48a9-bd6c-0a65ef665d50",
|
||||
"__expectedType__": "cc.AudioClip"
|
||||
|
||||
@@ -41,7 +41,7 @@ export class PageLevel extends BaseView {
|
||||
private static readonly DEFAULT_STAMINA_MAX = 50;
|
||||
|
||||
/** 答案正确后到弹出通关弹窗之间的停留时间(不论是否有谐音梗都保持一致) */
|
||||
private static readonly PASS_MODAL_DELAY_MS = 2000;
|
||||
private static readonly PASS_MODAL_DELAY_MS = 1000;
|
||||
|
||||
/** 图片2描述默认文案 */
|
||||
private static readonly DEFAULT_IMAGE2_DESCRIPTION = '这是什么?';
|
||||
@@ -91,6 +91,17 @@ export class PageLevel extends BaseView {
|
||||
/** 彩带 spine 动画名(一次播放) */
|
||||
private static readonly CAIDAI_ANIMATION_NAME = 'open';
|
||||
|
||||
/**
|
||||
* 通关赞美 spine(pose 节点)档位:[最小通关数, 动画名],倒序匹配。
|
||||
* 1-5 关 → "1",6-10 关 → "2",11+ 关 → "3"。
|
||||
* count <= 0 不会匹配任何档位,自然不播放。
|
||||
*/
|
||||
private static readonly POSE_TIERS: ReadonlyArray<readonly [number, string]> = [
|
||||
[11, '3'],
|
||||
[6, '2'],
|
||||
[1, '1'],
|
||||
];
|
||||
|
||||
// ========== 节点引用 ==========
|
||||
@property(Node)
|
||||
inputLayout: Node | null = null;
|
||||
@@ -236,6 +247,14 @@ export class PageLevel extends BaseView {
|
||||
@property(sp.Skeleton)
|
||||
caidaiSkeleton: sp.Skeleton | null = null;
|
||||
|
||||
/** 通关赞美 spine 节点(PassNode 子节点,根据本场通关数选择 1/2/3 动画) */
|
||||
@property(Node)
|
||||
poseNode: Node | null = null;
|
||||
|
||||
/** 通关赞美 sp.Skeleton 组件,动画名 "1" / "2" / "3",loop=false */
|
||||
@property(sp.Skeleton)
|
||||
poseSkeleton: sp.Skeleton | null = null;
|
||||
|
||||
// ========== 配置属性 ==========
|
||||
@property(AudioClip)
|
||||
clickAudio: AudioClip | null = null;
|
||||
@@ -330,6 +349,15 @@ export class PageLevel extends BaseView {
|
||||
/** 通关页所用「已通关数量」(业务数据,给成就体系展示用) */
|
||||
private _passCompletedLevelCount: number | null = null;
|
||||
|
||||
/**
|
||||
* 本次进入 PageLevel 后累计通关数(onViewLoad / _reinitLevelSession 时归零)。
|
||||
* 普通模式 / 分享模式都计入;用于驱动 pose 赞美动画档位。
|
||||
*/
|
||||
private _sessionPassCount: number = 0;
|
||||
|
||||
/** pose Spine 隐藏延时定时器(setTimeout 句柄);切关 / 关页时需清理避免穿屏触发 */
|
||||
private _poseHideTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/** 通关页动画起点(通关前)的已通关数量;为 null 表示不播跨称号过渡 */
|
||||
private _passPreviousCompletedLevelCount: number | null = null;
|
||||
|
||||
@@ -388,6 +416,9 @@ export class PageLevel extends BaseView {
|
||||
onViewLoad(): void {
|
||||
console.log('[PageLevel] onViewLoad');
|
||||
|
||||
// 本次进入答题页的会话通关数归零;普通 / 分享模式都重新开始计数
|
||||
this._sessionPassCount = 0;
|
||||
|
||||
// 必须在任何可能改动 InputLayout/punchLayout 位置的逻辑之前记录原始位置
|
||||
this._captureActionOriginalPositions();
|
||||
|
||||
@@ -489,6 +520,9 @@ export class PageLevel extends BaseView {
|
||||
private _reinitLevelSession(shareMode: boolean): void {
|
||||
this._isShareMode = shareMode;
|
||||
|
||||
// 跨模式切换视为新的"本次进入"会话,赞美动画从最低档位重新开始
|
||||
this._sessionPassCount = 0;
|
||||
|
||||
// 上一场可能遗留的弹窗 / 倒计时一并清掉,避免主线模式还看到分享态弹窗
|
||||
this._resetPassNode();
|
||||
this._closeWrongModal();
|
||||
@@ -1726,13 +1760,6 @@ export class PageLevel extends BaseView {
|
||||
this.playSound(this.successAudio);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放通关成功音效
|
||||
*/
|
||||
private playSuccessSound(): void {
|
||||
this.playSound(this.successAudio);
|
||||
}
|
||||
|
||||
// ========== 倒计时相关方法 ==========
|
||||
|
||||
/**
|
||||
@@ -2099,12 +2126,18 @@ export class PageLevel extends BaseView {
|
||||
|
||||
this._isPassNodeShown = true;
|
||||
|
||||
// 记录本次进入答题页的累计通关数(普通 / 分享模式都计入)。
|
||||
// 放在 _showPassNode 而不是 reportLevelCompleted:分享模式不会经过 reportLevelCompleted,
|
||||
// 但两种模式都经过 _showPassNode,且 _isPassNodeShown 防重入保证只 +1 一次。
|
||||
this._sessionPassCount++;
|
||||
|
||||
// 配置成就体系数据 / 按钮文案 / 事件
|
||||
this._setupPassNodeContent();
|
||||
this._bindPassNodeEvents();
|
||||
|
||||
// 启动彩带 + 滑入动画 + 淡出底部UI + 通关音效
|
||||
// 启动彩带 + 滑入动画 + 淡出底部UI + 通关音效 + 赞美 spine
|
||||
this._playCaidai();
|
||||
this._playPosePraise(this._sessionPassCount);
|
||||
this._playPassNodeShowAnimation();
|
||||
this.playSuccessSound();
|
||||
|
||||
@@ -2185,6 +2218,14 @@ export class PageLevel extends BaseView {
|
||||
if (this.caidaiNode) {
|
||||
this.caidaiNode.active = false;
|
||||
}
|
||||
|
||||
// pose 节点 prefab 默认 active=true 且 defaultAnimation="1",运行时必须先关掉,
|
||||
// 否则进入 PageLevel 时 pose 会立即显示并自动跑一次动画。
|
||||
if (this.poseNode) {
|
||||
this.poseNode.active = false;
|
||||
}
|
||||
this._clearPoseHideTimer();
|
||||
|
||||
this._isPassNodeShown = false;
|
||||
this._isPassNodeAnimating = false;
|
||||
}
|
||||
@@ -2274,6 +2315,12 @@ export class PageLevel extends BaseView {
|
||||
this.caidaiNode.active = false;
|
||||
}
|
||||
|
||||
// 关掉赞美 spine(PassNode 一关 pose 自然不可见,仍显式置 false 防御下次显示残留帧)
|
||||
if (this.poseNode) {
|
||||
this.poseNode.active = false;
|
||||
}
|
||||
this._clearPoseHideTimer();
|
||||
|
||||
this._unbindPassNodeEvents();
|
||||
this._titleAnimator?.stop();
|
||||
this._isPassNodeShown = false;
|
||||
@@ -2298,6 +2345,12 @@ export class PageLevel extends BaseView {
|
||||
this.caidaiNode.active = false;
|
||||
}
|
||||
|
||||
// 同步清掉赞美 spine,防止跨模式 / 切关 / 销毁时残留
|
||||
if (this.poseNode) {
|
||||
this.poseNode.active = false;
|
||||
}
|
||||
this._clearPoseHideTimer();
|
||||
|
||||
this._restoreBottomLayersImmediate();
|
||||
this._unbindPassNodeEvents();
|
||||
this._titleAnimator?.stop();
|
||||
@@ -2365,6 +2418,35 @@ export class PageLevel extends BaseView {
|
||||
this.caidaiSkeleton.setAnimation(0, PageLevel.CAIDAI_ANIMATION_NAME, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据本次会话累计通关数选择并播放赞美 spine 动画(pose 节点)。
|
||||
* 档位匹配规则见 PageLevel.POSE_TIERS:1-5 → "1",6-10 → "2",11+ → "3"。
|
||||
* 单次 spine 动画太短,这里用 loop=true 持续播放,配合 POSE_DISPLAY_DURATION
|
||||
* 定时强制隐藏 poseNode。切关 / 销毁会通过 _clearPoseHideTimer 取消定时器。
|
||||
*/
|
||||
private _playPosePraise(count: number): void {
|
||||
if (!this.poseNode || !this.poseSkeleton) return;
|
||||
|
||||
const tier = PageLevel.POSE_TIERS.find(([min]) => count >= min);
|
||||
if (!tier) return;
|
||||
const [, animName] = tier;
|
||||
|
||||
// 重置上一次可能仍在排队的隐藏定时器(极端情况下连击通关)
|
||||
this._clearPoseHideTimer();
|
||||
|
||||
this.poseNode.active = true;
|
||||
|
||||
this.poseSkeleton.setAnimation(0, animName, false);
|
||||
}
|
||||
|
||||
/** 清理 pose 隐藏定时器(用于切关 / 销毁 / 跨模式切换前的清场)。 */
|
||||
private _clearPoseHideTimer(): void {
|
||||
if (this._poseHideTimer !== null) {
|
||||
clearTimeout(this._poseHideTimer);
|
||||
this._poseHideTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 底部两层淡出(透明度 → 0),完成后 active = false */
|
||||
private _fadeOutBottomLayers(): void {
|
||||
for (const layer of [this.bottomLayoutNode, this.tipsLayout]) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 布局配置
|
||||
* view (ScrollView 的可视窗口) 宽 900,高 1000
|
||||
* view (ScrollView 的可视窗口) 宽 900,高 1100
|
||||
* 关卡 item 固定两列,纵向滚动
|
||||
*
|
||||
* item 的实际显示尺寸从 ListTpl 的 UITransform * scale 派生,
|
||||
@@ -29,7 +29,7 @@ const LAYOUT_CONFIG = {
|
||||
EDGE_PADDING_Y: 32,
|
||||
CENTER_ROWS: 2,
|
||||
VIEW_WIDTH: 900,
|
||||
VIEW_HEIGHT: 1000,
|
||||
VIEW_HEIGHT: 1300,
|
||||
};
|
||||
|
||||
/** 必须选择的关卡数量 */
|
||||
|
||||
Reference in New Issue
Block a user