Files
heros/assets/script/game/map/HeroUiComp.ts

242 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator, resources, Sprite, SpriteAtlas ,Node, ProgressBar, tween, v3, Label, Animation, CCString, CCInteger, sp} 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 { GameEvent } from "../common/config/GameEvent";
import { CdType, SkillSet } from "../common/config/SkillSet";
import { smc } from "../common/SingletonModuleComp";
import { oops } from "db://oops-framework/core/Oops";
import { MissionEvent } from "../common/config/MissionEvent";
import { HeroInfo } from "../common/config/heroSet";
const { ccclass, property } = _decorator;
/** 英雄数据接口 */
interface HeroData {
uuid: number;
name: string;
type: number; // 1 被动 0 主动
level: number;
quality: number;
cd: number;
cd_time: number;
active: boolean;
}
/** 视图层对象 */
@ccclass('HeroUiComp')
@ecs.register('HeroUi', false)
export class HeroUiComp extends CCComp {
heroes: HeroData[] = []
private readonly MAX_HEROES = 3
private readonly HERO_NODE_NAMES = ['hero1', 'hero2', 'hero3']
/** 视图层逻辑代码分离演示 */
onLoad() {
this.on(GameEvent.FightReady,this.fight_ready,this)
this.on(GameEvent.UseHeroCard,this.get_hero,this)
this.on(GameEvent.FightEnd,this.fight_end,this)
// this.node.getChildByName("icon").getChildByName("cd").active=false
}
start(){
this.fight_ready()
}
fight_end(){
this.heroes=[]
this.clearAllHeroIcons()
}
fight_ready(){
console.log("[HeroUiComp]: fight_ready",this.node)
this.heroes = []
for(let i = 0; i < this.MAX_HEROES; i++) {
this.heroes.push(this.createDefaultHero())
}
}
private createDefaultHero(): HeroData {
return {
uuid: 0,
name: "hero",
type: 0, //1 被动 0 主动
level: 1,
quality: 0,
cd: 0,
cd_time: 0,
active: false,
}
}
update(dt: number): void {
if(!smc.mission.play||smc.mission.pause) return
}
get_hero(e: GameEvent, data: { uuid: number }) {
console.log("[HeroUiComp]: get_hero", data)
// 尝试升级现有英雄
if (this.tryUpgradeExistingHero(data.uuid)) {
return
}
// 添加新英雄
this.addNewHero(data)
}
/**
* 尝试升级现有英雄
* @param uuid 英雄UUID
* @returns 是否成功升级
*/
private tryUpgradeExistingHero(uuid: number): boolean {
for (let i = 0; i < this.heroes.length; i++) {
if (this.heroes[i].uuid === uuid) {
this.heroes[i].level++
// 播放升级动画
this.playCardScaleAnimation(i)
return true
}
}
return false
}
/**
* 添加新英雄
* @param data 英雄数据
*/
private addNewHero(data: { uuid: number }) {
const heroInfo = HeroInfo[data.uuid]
if (!heroInfo) {
console.error("[HeroUiComp]: Hero info not found for uuid:", data.uuid)
return
}
// 查找空闲位置
const emptySlotIndex = this.findEmptyHeroSlot()
if (emptySlotIndex === -1) {
console.warn("[HeroUiComp]: No empty slot available for new hero")
return
}
// 设置英雄数据
this.heroes[emptySlotIndex] = {
uuid: data.uuid,
name: heroInfo.name,
type: heroInfo.type,
level: 1,
quality: heroInfo.quality,
cd: 0,
cd_time: 0,
active: false,
}
// 更新UI
this.updateHeroUI(emptySlotIndex, heroInfo)
// 播放新卡牌动画
this.playCardScaleAnimation(emptySlotIndex)
}
/**
* 查找空闲英雄槽位
* @returns 空闲槽位索引,-1表示没有空闲槽位
*/
private findEmptyHeroSlot(): number {
for (let i = 0; i < this.heroes.length; i++) {
if (this.heroes[i].uuid === 0) {
return i
}
}
return -1
}
/**
* 更新英雄UI图标和信息
* @param heroIndex 英雄索引
* @param heroInfo 英雄信息
*/
private updateHeroUI(heroIndex: number, heroInfo: { path: string }) {
const heroNodeName = this.HERO_NODE_NAMES[heroIndex]
const heroNode = this.node.getChildByName(heroNodeName)
if (!heroNode) return
const iconNode = heroNode.getChildByName("icon")
if (iconNode) {
iconNode.active = true
this.loadHeroIcon(iconNode, heroInfo.path)
}
}
/**
* 加载英雄图标
* @param iconNode 图标节点
* @param heroPath 英雄路径
*/
private loadHeroIcon(iconNode: Node, heroPath: string) {
iconNode.parent.getChildByName("iconbg").active=false
const icon_path = "game/heros/heros/"+heroPath
resources.load(icon_path, sp.SkeletonData, (err, skeleton) => {
const spine = iconNode.getComponent(sp.Skeleton);
if (spine) {
spine.skeletonData = skeleton;
spine.setAnimation(0, "Idle", true);
}
});
}
/**
* 播放卡牌缩放动画
* @param heroIndex 英雄索引
*/
private playCardScaleAnimation(heroIndex: number) {
const heroNodeName = this.HERO_NODE_NAMES[heroIndex]
const heroNode = this.node.getChildByName(heroNodeName)
if (!heroNode) return
// 停止可能存在的动画
tween(heroNode).stop()
// 播放缩放动画:放大 -> 恢复原始大小
tween(heroNode)
.to(0.1, { scale: v3(1.2, 1.2, 1) }, { easing: 'backOut' })
.to(0.15, { scale: v3(1, 1, 1) }, { easing: 'backOut' })
.start()
}
/**
* 清空英雄图标
* @param heroIndex 英雄索引
*/
private clearHeroIcon(heroIndex: number) {
const heroNodeName = this.HERO_NODE_NAMES[heroIndex]
const heroNode = this.node.getChildByName(heroNodeName)
if (!heroNode) return
const iconNode = heroNode.getChildByName("icon")
if (iconNode) {
iconNode.active = false
}
heroNode.getChildByName("iconbg").active=true
}
/**
* 清空所有英雄图标
*/
public clearAllHeroIcons() {
for (let i = 0; i < this.MAX_HEROES; i++) {
this.clearHeroIcon(i)
}
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}