feat: 新增技能图标组件与UI优化

1. 新增SSkillBoxComp技能小图标组件,支持技能展示与状态控制
2. 优化CardLiteComp选中态动画,改为缩放高亮效果
3. 为英雄列表、任务主页添加顶部栏显示控制逻辑
4. 调整部分预制件布局与节点配置
This commit is contained in:
pan
2026-08-25 10:50:28 +08:00
parent 8ce83dc5e2
commit a8aa876a74
10 changed files with 5604 additions and 824 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "c887ba55-bb80-4c4b-b0e1-0d265b3f58e0",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "sibox"
}
}

View File

@@ -22,10 +22,10 @@
"__id__": 2
},
{
"__id__": 268
"__id__": 285
},
{
"__id__": 277
"__id__": 267
}
],
"_active": true,
@@ -107,7 +107,7 @@
}
],
"_prefab": {
"__id__": 267
"__id__": 284
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -3802,6 +3802,9 @@
"tals_btn": {
"__id__": 212
},
"top_bar_node": {
"__id__": 267
},
"heros_page": {
"__id__": 88
},
@@ -3817,6 +3820,214 @@
"__type__": "cc.CompPrefabInfo",
"fileId": "96KsLaZWJF7YqZMqE+112D"
},
{
"__type__": "cc.Node",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_prefab": {
"__id__": 268
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 267
},
"asset": {
"__uuid__": "56aee962-4a5e-45ae-a779-999444d06d18",
"__expectedType__": "cc.Prefab"
},
"fileId": "cboM54s0hM07XCtrpFp0/b",
"instance": {
"__id__": 269
},
"targetOverrides": null
},
{
"__type__": "cc.PrefabInstance",
"fileId": "2fMXacmbRNHo6Tx0XZe8OP",
"prefabRootNode": {
"__id__": 1
},
"mountedChildren": [],
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 270
},
{
"__id__": 272
},
{
"__id__": 273
},
{
"__id__": 274
},
{
"__id__": 275
},
{
"__id__": 277
},
{
"__id__": 278
},
{
"__id__": 279
},
{
"__id__": 280
},
{
"__id__": 282
}
],
"removedComponents": []
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 271
},
"propertyPath": [
"_name"
],
"value": "top"
},
{
"__type__": "cc.TargetInfo",
"localID": [
"cboM54s0hM07XCtrpFp0/b"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 271
},
"propertyPath": [
"_lpos"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 1175,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 271
},
"propertyPath": [
"_lrot"
],
"value": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 271
},
"propertyPath": [
"_euler"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 276
},
"propertyPath": [
"_top"
],
"value": 70
},
{
"__type__": "cc.TargetInfo",
"localID": [
"52mhkKH89DVKECWS3HY4Qh"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 276
},
"propertyPath": [
"_alignFlags"
],
"value": 17
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 276
},
"propertyPath": [
"_bottom"
],
"value": 1193.667
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 271
},
"propertyPath": [
"_active"
],
"value": true
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
},
"propertyPath": [
"_active"
],
"value": false
},
{
"__type__": "cc.TargetInfo",
"localID": [
"71PjuREPhL54gIRBLnZ//L"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 283
},
"propertyPath": [
"_active"
],
"value": false
},
{
"__type__": "cc.TargetInfo",
"localID": [
"41v9yb+khAT5fF0JOnsr2d"
]
},
{
"__type__": "cc.PrefabInfo",
"root": {
@@ -3837,14 +4048,14 @@
"__id__": 1
},
"_prefab": {
"__id__": 269
"__id__": 286
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 268
"__id__": 285
},
"asset": {
"__uuid__": "26bff847-cd29-48a5-bbfa-c3e2dbda688d",
@@ -3852,7 +4063,7 @@
},
"fileId": "5a9CMsVQhKP5Y+UJfTKPbx",
"instance": {
"__id__": 270
"__id__": 287
},
"targetOverrides": null
},
@@ -3866,19 +4077,19 @@
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 271
"__id__": 288
},
{
"__id__": 273
"__id__": 290
},
{
"__id__": 274
"__id__": 291
},
{
"__id__": 275
"__id__": 292
},
{
"__id__": 276
"__id__": 293
}
],
"removedComponents": []
@@ -3886,7 +4097,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 272
"__id__": 289
},
"propertyPath": [
"_name"
@@ -3902,7 +4113,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 272
"__id__": 289
},
"propertyPath": [
"_lpos"
@@ -3917,148 +4128,8 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 272
},
"propertyPath": [
"_lrot"
],
"value": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 272
},
"propertyPath": [
"_euler"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 272
},
"propertyPath": [
"_active"
],
"value": false
},
{
"__type__": "cc.Node",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_prefab": {
"__id__": 278
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 277
},
"asset": {
"__uuid__": "56aee962-4a5e-45ae-a779-999444d06d18",
"__expectedType__": "cc.Prefab"
},
"fileId": "cboM54s0hM07XCtrpFp0/b",
"instance": {
"__id__": 279
},
"targetOverrides": null
},
{
"__type__": "cc.PrefabInstance",
"fileId": "2fMXacmbRNHo6Tx0XZe8OP",
"prefabRootNode": {
"__id__": 1
},
"mountedChildren": [],
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 280
},
{
"__id__": 282
},
{
"__id__": 283
},
{
"__id__": 284
},
{
"__id__": 285
},
{
"__id__": 287
},
{
"__id__": 288
},
{
"__id__": 289
},
{
"__id__": 290
},
{
"__id__": 292
}
],
"removedComponents": []
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
},
"propertyPath": [
"_name"
],
"value": "top"
},
{
"__type__": "cc.TargetInfo",
"localID": [
"cboM54s0hM07XCtrpFp0/b"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
},
"propertyPath": [
"_lpos"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 1175,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
},
"propertyPath": [
"_lrot"
],
@@ -4073,7 +4144,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
"__id__": 289
},
"propertyPath": [
"_euler"
@@ -4088,81 +4159,13 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 286
},
"propertyPath": [
"_top"
],
"value": 70
},
{
"__type__": "cc.TargetInfo",
"localID": [
"52mhkKH89DVKECWS3HY4Qh"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 286
},
"propertyPath": [
"_alignFlags"
],
"value": 17
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 286
},
"propertyPath": [
"_bottom"
],
"value": 1193.667
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 281
},
"propertyPath": [
"_active"
],
"value": true
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 291
"__id__": 289
},
"propertyPath": [
"_active"
],
"value": false
},
{
"__type__": "cc.TargetInfo",
"localID": [
"71PjuREPhL54gIRBLnZ//L"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 293
},
"propertyPath": [
"_active"
],
"value": false
},
{
"__type__": "cc.TargetInfo",
"localID": [
"41v9yb+khAT5fF0JOnsr2d"
]
},
{
"__type__": "cc.UITransform",
"_name": "GameUI<UITransform>",
@@ -4275,10 +4278,10 @@
],
"nestedPrefabInstanceRoots": [
{
"__id__": 277
"__id__": 267
},
{
"__id__": 268
"__id__": 285
},
{
"__id__": 212

View File

@@ -37,6 +37,9 @@ const { ccclass, property } = _decorator;
export class CardLiteComp extends CCComp {
private debugMode: boolean = false;
/** 选中态放大倍率 */
private static readonly SELECT_SCALE: number = 1.08;
// ======================== 编辑器绑定节点 ========================
@property(Node)
@@ -109,12 +112,15 @@ export class CardLiteComp extends CCComp {
}
/**
* 设置选中态:切换根节点下 `active` 子节点的显隐(不再通过缩放表达选中)。
* 设置选中态:选中卡微微放大,取消选中恢复原尺寸。
* @param selected 是否选中
*/
setSelected(selected: boolean) {
const mark = this.node.getChildByName("active");
if (mark) mark.active = selected;
Tween.stopAllByTarget(this.node);
const target = selected ? CardLiteComp.SELECT_SCALE : 1;
tween(this.node)
.to(0.12, { scale: new Vec3(target, target, 1) }, { easing: 'quadOut' })
.start();
}
// ======================== 事件绑定 ========================

View File

@@ -87,6 +87,9 @@ export class HerosListComp extends CCComp {
@property(Node)
chip_node = null!
/** 技能描述节点() */
@property(Node)
infos_node = null!
/** 升级特效动画节点(内含升级效果 Animation,点击升级时从头播放) */
@property(Node)
upgrade_anim_node = null!

View File

@@ -54,6 +54,9 @@ export class MissionHomeComp extends CCComp {
/** 天赋按钮节点 */
@property(Node)
tals_btn = null!
/** 顶部栏节点(仅主页显示) */
@property(Node)
top_bar_node = null!
@property(Node)
@@ -197,6 +200,9 @@ export class MissionHomeComp extends CCComp {
}
private showPage(page: Node) {
// 进入分页时隐藏顶部栏,仅主页显示
this.top_bar_node.active = false
this.heros_page.active = (page === this.heros_page)
this.talents_page.active = (page === this.talents_page)
this.ranks_page.active = (page === this.ranks_page)
@@ -208,6 +214,9 @@ export class MissionHomeComp extends CCComp {
}
private hideAllPages() {
// 回到主页时恢复顶部栏显示
this.top_bar_node.active = true
this.heros_page.active = false
this.talents_page.active = false
this.ranks_page.active = false

View File

@@ -0,0 +1,148 @@
import { _decorator, Node, Sprite, Label } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { CardTriggerType } from "../common/config/CardSet";
import { EquipPoolList } from "../common/config/EquipSet";
import { SkillSet, FieldSkillSet } from "../common/config/SkillSet";
import { FieldEntry } from "../common/config/heroSet";
import { smc } from "../common/SingletonModuleComp";
const { ccclass, property } = _decorator;
/**
* 技能小图标组件
*
* 由 MissSkillsComp.addSkill() 实例化并初始化。
* 在战场上以图标 + 剩余次数的形式呈现。
*/
@ccclass('SSkillBoxComp')
@ecs.register('SSkillBoxComp', false)
export class SSkillBoxComp extends CCComp {
/** 技能图标节点 */
@property({ type: Node })
private icon_node: Node = null;
/** 技能图标节点:下面有 green blue purple red yellow 5个不同颜色节点*/
@property({ type: Node })
private bg_node: Node = null;
/** 技能等级标签 */
@property(Label)
private lv_label: Label = null;
/** 锁定遮罩节点(active 时表示技能未激活) */
@property({ type: Node })
private locked: Node = null;
/** 技能 UUID */
private s_uuid: number = 0;
/** 卡牌等级 */
private card_lv: number = 1;
/** 卡牌自定义图标ID(优先级最高,未定义则按 trigger_type 自动取) */
private card_icon?: string;
/** 触发类型(默认即时,保持向后兼容) */
private trigger_type: CardTriggerType = CardTriggerType.Instant;
/** 驻场技能词条列表(uuid 指向 FieldSkillSet 底座,value 为生效数值) */
public field: FieldEntry[] = [];
/**
* 初始化技能卡效果:
* 1. 从 EquipPoolList 查询装备卡的触发配置(含 trigger_type)。
* 2. 更新 UI 显示(图标 + 次数)。
*
* @param uuid 卡牌 UUID
* @param card_lv 技能卡等级
*/
init(uuid: number, card_lv: number) {
this.card_lv = card_lv;
// 装备卡配置已迁移至 EquipPoolList
const config = EquipPoolList.find(c => c.uuid === uuid);
if (config) {
this.s_uuid = config.skill ?? uuid; // 获取实际的技能 UUID
this.card_icon = config.icon; // 保存卡牌自定义图标(优先级最高)
this.trigger_type = config.trigger_type ?? CardTriggerType.Instant;
} else {
this.s_uuid = uuid;
}
this.updateUI();
}
/**
* 设置技能激活状态:
* - locked = true → 显示锁定遮罩,技能未激活
* - locked = false → 隐藏锁定遮罩,技能已激活
*/
setLocked(locked: boolean) {
if (this.locked) {
this.locked.active = locked;
}
}
/**
* 根据技能等级切换 bg_node 下的颜色子节点显示。
* 等级与颜色对应关系(技能卡 wave 档位):
* card_lv 1 (wave 1) → green
* card_lv 2 (wave 5) → blue
* card_lv 3 (wave 8) → purple
*/
private updateBgNode() {
if (!this.bg_node) return;
const lvToColor: Record<number, string> = {
1: "green",
2: "blue",
3: "purple",
};
const targetColor = lvToColor[this.card_lv];
this.bg_node.children.forEach(child => {
child.active = (child.name === targetColor);
});
}
/**
* 更新 UI:
* - 背景:根据技能等级切换对应颜色子节点显示
* - 图标:从 uicons 图集获取
* - 等级标签:显示技能卡等级
*/
updateUI() {
// 按技能等级切换背景颜色节点(与 getLvColor 等级配色一致)
this.updateBgNode();
// 加载技能图标
if (this.icon_node) {
// 优先使用卡牌自定义 icon;未定义则按 trigger_type 自动取
let iconId: string | undefined = this.card_icon;
if (!iconId) {
if (this.trigger_type === CardTriggerType.Interval) {
iconId = this.s_uuid ? SkillSet[this.s_uuid]?.icon : undefined;
} else if (this.trigger_type === CardTriggerType.Field) {
const fieldUuid = this.field?.[0]?.uuid;
iconId = fieldUuid ? FieldSkillSet[fieldUuid]?.icon : undefined;
}
}
if (this.icon_node && this.icon_node.isValid) {
let sprite = this.icon_node.getComponent(Sprite) || this.icon_node.addComponent(Sprite);
if (smc.uiconsAtlas && iconId) {
const frame = smc.uiconsAtlas.getSpriteFrame(iconId);
sprite.spriteFrame = frame || null; // 取不到时清空,避免残留
} else {
sprite.spriteFrame = null;
}
}
}
// 显示技能等级
if (this.lv_label) {
this.lv_label.string = `${this.card_lv}`;
}
}
/** ECS 组件移除时销毁节点 */
reset() {
if (this.node && this.node.isValid) {
this.node.destroy();
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "36150383-6711-44b9-83d7-0d7af167584d",
"files": [],
"subMetas": {},
"userData": {}
}