feat(天赋系统): 实现天赋选择功能并完善卡片交互逻辑

添加天赋选择事件触发机制,在战斗开始时触发天赋选择界面
重构MissionCardComp类,实现天赋卡片的随机生成、显示和选择功能
为卡片添加选中状态标记和交互处理
更新prefab资源以支持新的天赋选择界面
This commit is contained in:
walkpan
2026-01-04 19:03:00 +08:00
parent f7622202f8
commit 71026ae9a5
4 changed files with 2222 additions and 1651 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -38,19 +38,25 @@
}, },
{ {
"__id__": 56 "__id__": 56
},
{
"__id__": 64
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 64 "__id__": 74
}, },
{ {
"__id__": 66 "__id__": 76
},
{
"__id__": 78
} }
], ],
"_prefab": { "_prefab": {
"__id__": 68 "__id__": 80
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -1492,6 +1498,234 @@
"targetOverrides": null, "targetOverrides": null,
"nestedPrefabInstanceRoots": null "nestedPrefabInstanceRoots": null
}, },
{
"__type__": "cc.Node",
"_name": "selected",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [
{
"__id__": 65
}
],
"_active": true,
"_components": [
{
"__id__": 71
}
],
"_prefab": {
"__id__": 73
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "GreenTick",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 64
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 66
},
{
"__id__": 68
}
],
"_prefab": {
"__id__": 70
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": -76.645,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 65
},
"_enabled": true,
"__prefab": {
"__id__": 67
},
"_contentSize": {
"__type__": "cc.Size",
"width": 54,
"height": 54
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f0xTeEhHVEmY81KJd5/ryK"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 65
},
"_enabled": true,
"__prefab": {
"__id__": 69
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": {
"__uuid__": "deedea09-8f2b-400f-9803-4cfd38e45d1a@55373",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 0,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "63qWzhuPFLV6vEcEmhLEAC"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "e8g5MwfEhD6Y0m0e23zag4",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 64
},
"_enabled": true,
"__prefab": {
"__id__": 72
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "acA6HyWsxC3bepdLREshZ3"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "29hkGgh2lDpJ8GAA6r1xOh",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{ {
"__type__": "cc.UITransform", "__type__": "cc.UITransform",
"_name": "", "_name": "",
@@ -1502,7 +1736,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 65 "__id__": 75
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -1530,7 +1764,7 @@
}, },
"_enabled": false, "_enabled": false,
"__prefab": { "__prefab": {
"__id__": 67 "__id__": 77
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -1565,6 +1799,62 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "609hAwCWtPmqZXRsnP0C+8" "fileId": "609hAwCWtPmqZXRsnP0C+8"
}, },
{
"__type__": "cc.Button",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 79
},
"clickEvents": [],
"_interactable": true,
"_transition": 3,
"_normalColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_hoverColor": {
"__type__": "cc.Color",
"r": 211,
"g": 211,
"b": 211,
"a": 255
},
"_pressedColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_disabledColor": {
"__type__": "cc.Color",
"r": 124,
"g": 124,
"b": 124,
"a": 255
},
"_normalSprite": null,
"_hoverSprite": null,
"_pressedSprite": null,
"_disabledSprite": null,
"_duration": 0.1,
"_zoomScale": 1.2,
"_target": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "85rZYvTXxBq4pJCoHruVwe"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {

View File

@@ -1,73 +1,169 @@
import { _decorator, Label, Node } from "cc"; import { _decorator, Label, Node } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { talConf, ItalConf } from "../common/config/TalSet";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
/** 视图层对象 */ /** 视图层对象 */
@ccclass('ModuleViewComp') @ccclass('MissionCardComp')
@ecs.register('ModuleView', false) @ecs.register('MissionCard', false)
export class ModuleViewComp extends CCComp { export class MissionCardComp extends CCComp {
/** 视图层逻辑代码分离演示 */ /** 视图层逻辑代码分离演示 */
@property(Node) @property(Node)
card1:Node = null card1:Node = null!
@property(Node) @property(Node)
card2:Node = null card2:Node = null!
@property(Node) @property(Node)
card3:Node = null card3:Node = null!
@property(Node) @property(Node)
card4:Node = null card4:Node = null!
card1_data:ItalConf = null!
card2_data:ItalConf = null!
card3_data:ItalConf = null!
card4_data:ItalConf = null!
onLoad() {
oops.message.on(GameEvent.TalentSelect, this.onTalentSelect, this);
}
onDestroy() {
oops.message.off(GameEvent.TalentSelect, this.onTalentSelect, this);
this.ent.destroy();
}
card1_data:any = {}
card2_data:any = {}
card3_data:any = {}
card4_data:any = {}
start() { start() {
this.card1.active=true // 初始隐藏或显示逻辑
this.card2.active=true this.node.active = false;
this.card3.active=true this.resetCardStates();
this.card4.active=true
} }
private resetCardStates() {
const cards = [this.card1, this.card2, this.card3, this.card4];
cards.forEach(card => {
if (card) {
const selected = card.getChildByName("selected");
if (selected) selected.active = false;
}
});
}
// 是否已经选择了天赋
private hasSelected: boolean = false;
private onTalentSelect(event: string, args: any) {
this.node.active = true;
this.hasSelected = false; // 重置选择状态
this.resetCardStates(); // 每次刷新前重置卡片状态
this.refCards();
}
refCards(){ refCards(){
// 随机获取4个不一样的天赋
const allTalents = Object.values(talConf);
const result: ItalConf[] = [];
const temp = [...allTalents];
// 简单的随机抽取算法
for (let i = 0; i < 4 && temp.length > 0; i++) {
const index = Math.floor(Math.random() * temp.length);
result.push(temp[index]);
temp.splice(index, 1);
}
// 更新卡片
if (result.length > 0) this.updateCardData(1, result[0]);
if (result.length > 1) this.updateCardData(2, result[1]);
if (result.length > 2) this.updateCardData(3, result[2]);
if (result.length > 3) this.updateCardData(4, result[3]);
} }
updateCardInfo(card:Node,data:any){
updateCardInfo(card:Node, data:ItalConf){
if(!card) return if(!card) return
card.active = true;
// 隐藏选中状态
const selected = card.getChildByName("selected");
if(selected) selected.active = false;
let name = card.getChildByName("name") let name = card.getChildByName("name")
if(name){ if(name){
name.getComponent(Label).string = data.name name.getComponent(Label)!.string = data.name
} }
let info = card.getChildByName("info").getChildByName("Label") let info = card.getChildByName("info")?.getChildByName("Label")
if(info){ if(info){
info.getComponent(Label).string = data.info info.getComponent(Label)!.string = data.desc
} }
} }
updateCardData(index:number,data:any){
updateCardData(index:number, data:ItalConf){
switch (index) { switch (index) {
case 1: case 1:
this.card1_data = data this.card1_data = data
this.updateCardInfo(this.card1, data);
break; break;
case 2: case 2:
this.card2_data = data this.card2_data = data
this.updateCardInfo(this.card2, data);
break; break;
case 3: case 3:
this.card3_data = data this.card3_data = data
this.updateCardInfo(this.card3, data);
break; break;
case 4: case 4:
this.card4_data = data this.card4_data = data
this.updateCardInfo(this.card4, data);
break; break;
} }
} }
selectCard(index:number){
selectCard(e:any,index:string){
console.log("selectCard",index)
let _index = parseInt(index);
// 如果已经选择过,则不再处理
if(this.hasSelected) return;
let selectedTalent: ItalConf | null = null;
let selectedCardNode: Node | null = null;
switch (_index) {
case 1:
selectedTalent = this.card1_data;
selectedCardNode = this.card1;
break;
case 2:
selectedTalent = this.card2_data;
selectedCardNode = this.card2;
break;
case 3:
selectedTalent = this.card3_data;
selectedCardNode = this.card3;
break;
case 4:
selectedTalent = this.card4_data;
selectedCardNode = this.card4;
break;
}
if (selectedTalent && selectedCardNode) {
this.hasSelected = true;
console.log("选择天赋:", selectedTalent.name);
// 显示当前选中的 selected 节点
const selected = selectedCardNode.getChildByName("selected");
if(selected) selected.active = true;
// 发送事件
oops.message.dispatchEvent(GameEvent.UseTalentCard, selectedTalent.uuid);
// 延迟关闭界面,让玩家看到选中效果
// this.scheduleOnce(() => {
// this.node.active = false;
// }, 0.5);
}
} }
/** 全局消息逻辑处理 */
// private onHandler(event: string, args: any) {
// switch (event) {
// case ModuleEvent.Cmd:
// break;
// }
// }
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() { reset() {

View File

@@ -147,6 +147,7 @@ export class MissionComp extends CCComp {
to_fight(){ to_fight(){
smc.mission.in_fight=true smc.mission.in_fight=true
oops.message.dispatchEvent(GameEvent.FightStart) //GameSetMonComp 监听刷怪 oops.message.dispatchEvent(GameEvent.FightStart) //GameSetMonComp 监听刷怪
oops.message.dispatchEvent(GameEvent.TalentSelect)
} }