Files
heros/assets/script/game/map/HInfoComp.ts
panw 53cf25d7a5 refactor(游戏对象): 调整英雄位置和动画关键帧数值
- 修改hm2.prefab中英雄的y坐标位置
- 简化HInfoComp中节点查找路径
- 更新lr3.anim动画关键帧数值和编辑器额外属性
2025-11-04 14:46:28 +08:00

358 lines
13 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, Animation, AnimationClip, Component, instantiate, Label, Node, Prefab, resources, Sprite, SpriteFrame, v3, tween, Vec3, ProgressBar } from 'cc';
import { oops } from 'db://oops-framework/core/Oops';
import { getHeroList, getPreAttr, HeroConf, HeroInfo, HType, HTypeName } from '../common/config/heroSet';
import { smc } from '../common/SingletonModuleComp';
import { GameEvent } from '../common/config/GameEvent';
import { CCComp } from 'db://oops-framework/module/common/CCComp';
import { ecs } from 'db://oops-framework/libs/ecs/ECS';
const { ccclass, property } = _decorator;
@ccclass('HInfoComp')
@ecs.register('HInfoComp', false)
export class HInfoComp extends CCComp {
h_uuid:number=0
name_node:any=null
type_node:any=null
ap_node:any=null
hp_node:any=null
def_node:any=null
mp_node:any=null
map_node:any=null
mdef_node:any=null
// 重新定义节点映射,使名称更清晰
// 当前显示的英雄节点数组7个位置
heroNodes: (Node | null)[] = [null, null, null, null, null, null, null];
// 英雄位置定义
hero_pos:any={
0:v3(420,-30,0), // 不在屏幕内
1:v3(280,-30,0),
2:v3(160,-33,0),
3:v3(0,-40,0),
4:v3(-160,-33,0),
5:v3(-280,-30,0),
6:v3(-420,-30,0), // 不在屏幕内
}
// 动画锁定标志:防止快速点击导致的动画冲突
private isMoving: boolean = false;
// 保存待处理的setTimeout句柄用于取消前一个异步操作
private moveTimeoutId: any = null;
protected onLoad(): void {
// this.on(GameEvent.MissionStart,this.mission_start,this)
}
// 位置索引常量
private static center_pos = 3;
/**
* 根据位置索引获取英雄缩放值
* @param posIndex 位置索引 (0-6)
* @returns Vec3 缩放向量
*/
private getHeroScale(posIndex: number): Vec3 {
switch(posIndex) {
case 2:
case 4:
return v3(-1.6, 1.6, 1); // 2、4位置1.2倍缩放
case 3:
return v3(-1.8, 1.8, 1); // 3位置中心1.5倍缩放
default:
return v3(-1.4, 1.4, 1); // 其他位置1倍缩放
}
}
start() {
this.name_node=this.node.getChildByName("hname").getChildByName("name")
this.type_node=this.node.getChildByName("hname").getChildByName("type")
this.ap_node=this.node.getChildByName("info").getChildByName("base").getChildByName("ap")
this.hp_node=this.node.getChildByName("info").getChildByName("base").getChildByName("hp")
this.def_node=this.node.getChildByName("info").getChildByName("base").getChildByName("def")
this.mdef_node=this.node.getChildByName("info").getChildByName("base").getChildByName("mdef")
this.map_node=this.node.getChildByName("info").getChildByName("base").getChildByName("map")
this.mp_node=this.node.getChildByName("info").getChildByName("base").getChildByName("mp")
this.h_uuid=smc.fight_hero
this.update_data(this.h_uuid)
this.load_all_hero(this.h_uuid)
}
update(deltaTime: number) {
}
update_data(uuid:number){
this.h_uuid=uuid
this.name_node.getComponent(Label).string=HeroInfo[uuid].name
this.type_node.getComponent(Label).string=HTypeName[HeroInfo[uuid].type]
this.ap_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].ap.toString()
this.hp_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].hp.toString()
this.def_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].def.toString()
this.mdef_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].mdef.toString()
this.map_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].map.toString()
this.mp_node.getChildByName("num").getComponent(Label).string=HeroInfo[uuid].mp.toString()
let bar_num=getPreAttr(uuid)
this.ap_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.ap
this.hp_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.hp
this.def_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.def
this.mdef_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.mdef
this.map_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.map
this.mp_node.getChildByName("bar").getComponent(ProgressBar).progress=bar_num.mp
}
load_all_hero(uuid:number){
// 清除之前的英雄节点
this.claear_hero();
// 获取英雄列表(优先显示拥有的英雄)
let heros = getHeroList();
let currentIndex = heros.indexOf(uuid);
// 载入7个英雄节点当前英雄及前后各3个
for(let i = 0; i < 7; i++) {
// 计算索引位置(考虑循环)
let indexOffset = i - 3; // -3, -2, -1, 0, 1, 2, 3
let heroIndex = currentIndex + indexOffset;
// 处理循环边界
if(heroIndex < 0) {
heroIndex = heros.length + heroIndex;
} else if(heroIndex >= heros.length) {
heroIndex = heroIndex - heros.length;
}
// 获取英雄UUID
let heroUuid = heros[heroIndex];
// 载入英雄预制体并设置位置
this.heroNodes[i] = this.load_hui(heroUuid, i);
// 添加初始缩放动画,根据位置设置不同的缩放值
if (this.heroNodes[i]) {
let targetScale = this.getHeroScale(i);
tween(this.heroNodes[i])
.to(0.2, { scale: targetScale })
.start();
}
}
this.show_lock()
}
load_hui(uuid:number, pos_index: number){
var path = "game/gui/hui";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
// 将节点添加到父节点下
this.node.getChildByName("hero").addChild(node);
// 设置节点位置
node.setPosition(this.hero_pos[pos_index]);
// node.setSiblingIndex(0);
// 根据位置设置不同的缩放值
node.setScale(this.getHeroScale(pos_index));
// 加载并播放动画
let anm_path=HeroInfo[uuid].path;
resources.load("game/heros/hero/"+anm_path+"/idle", AnimationClip, (err, clip) => {
if (!err && clip) {
let animComponent = node.getComponent(Animation);
if(animComponent) {
animComponent.addClip(clip);
animComponent.play("idle");
}
} else {
console.error(`[HInfoComp]: Failed to load animation for hero ${uuid}`, err);
}
});
return node;
}
mission_start(){
this.claear_hero()
}
is_own(){
return smc.heros.includes(this.h_uuid)
}
show_lock(){
this.node.getChildByName("buy").active=!this.is_own()
this.node.getChildByName("lock").active=!this.is_own()
}
claear_hero(){
for (let i = 0; i < this.heroNodes.length; i++) {
if (this.heroNodes[i]) {
this.heroNodes[i].destroy();
this.heroNodes[i] = null;
}
}
}
next_hero(){
// 检查是否正在动画中,防止快速点击导致的冲突
if (this.isMoving) return;
// 获取英雄列表(优先显示拥有的英雄)
let heros = getHeroList();
let index = heros.indexOf(this.h_uuid);
index++;
if(index == heros.length) index = 0;
let nextHero = heros[index];
// 更新数据
this.h_uuid = nextHero;
smc.updateFihgtHero(nextHero)
this.update_data(nextHero);
// 执行平滑移动动画
this.moveHeroesRight();
this.show_lock()
}
prev_hero(){
// 检查是否正在动画中,防止快速点击导致的冲突
if (this.isMoving) return;
// 获取英雄列表(优先显示拥有的英雄)
let heros = getHeroList();
let index = heros.indexOf(this.h_uuid);
index--;
if(index == -1) index = heros.length - 1;
let prevHero = heros[index];
// 更新数据
this.h_uuid = prevHero;
smc.updateFihgtHero(prevHero)
this.update_data(prevHero);
// 执行平滑移动动画
this.moveHeroesLeft();
this.show_lock()
}
buy_hero(){
console.info("[HInfoComp]:buy_hero",this.h_uuid)
if(smc.vmdata.gold < HeroConf.COST) {
oops.gui.toast("金币不足")
return
}
smc.addHero(this.h_uuid)
this.load_all_hero(this.h_uuid)
this.show_lock()
}
start_mission() {
oops.message.dispatchEvent(GameEvent.MissionStart, {})
this.node.active=false;
}
moveHeroesLeft() {
// 取消前一个待处理的异步操作
if (this.moveTimeoutId !== null) {
clearTimeout(this.moveTimeoutId);
}
// 设置动画锁定
this.isMoving = true;
// 在动画开始前直接销毁hero_pos[6]上的节点
if (this.heroNodes[6]) {
this.heroNodes[6].destroy();
this.heroNodes[6] = null;
}
// 移动所有现有节点向左除了已销毁的heroNodes[6]
for (let i = 0; i < 6; i++) {
if (this.heroNodes[i]) {
// 计算目标位置:向左移动
let targetPos = this.hero_pos[i + 1];
// 使用Tween执行平滑移动和缩放动画
let targetScale = this.getHeroScale(i + 1);
tween(this.heroNodes[i])
.to(0.2, { position: targetPos, scale: targetScale })
.start();
}
}
// 延迟重排数组和创建新节点,等待动画完成
this.moveTimeoutId = setTimeout(() => {
// 移动数组元素(向后平移)
for (let i = 6; i > 0; i--) {
this.heroNodes[i] = this.heroNodes[i - 1];
}
// 创建新节点放在hero_pos[0]位置
let heros = getHeroList();
let currentIndex = heros.indexOf(this.h_uuid);
let newIndex = currentIndex - 3; // 新的最左侧英雄索引
// 处理循环边界
if (newIndex < 0) {
newIndex = heros.length + newIndex;
}
this.heroNodes[0] = this.load_hui(heros[newIndex], 0);
// 确保新创建的节点使用正确的缩放值
if (this.heroNodes[0]) {
this.heroNodes[0].setScale(this.getHeroScale(0));
}
// 动画完成,解除锁定
this.isMoving = false;
this.moveTimeoutId = null;
}, 200); // 与动画时间保持一致
}
moveHeroesRight() {
// 取消前一个待处理的异步操作
if (this.moveTimeoutId !== null) {
clearTimeout(this.moveTimeoutId);
}
// 设置动画锁定
this.isMoving = true;
// 在动画开始前直接销毁hero_pos[0]上的节点
if (this.heroNodes[0]) {
this.heroNodes[0].destroy();
this.heroNodes[0] = null;
}
// 移动所有现有节点向右除了已销毁的heroNodes[0]
for (let i = 1; i < this.heroNodes.length; i++) {
if (this.heroNodes[i]) {
// 计算目标位置:向右移动
let targetPos = this.hero_pos[i - 1];
// 使用Tween执行平滑移动和缩放动画
let targetScale = this.getHeroScale(i - 1);
tween(this.heroNodes[i])
.to(0.2, { position: targetPos, scale: targetScale })
.start();
}
}
// 延迟重排数组和创建新节点,等待动画完成
this.moveTimeoutId = setTimeout(() => {
// 移动数组元素(向前平移)
for (let i = 0; i < 6; i++) {
this.heroNodes[i] = this.heroNodes[i + 1];
}
// 创建新节点放在hero_pos[6]位置
let heros = getHeroList();
let currentIndex = heros.indexOf(this.h_uuid);
let newIndex = currentIndex + 3; // 新的最右侧英雄索引
// 处理循环边界
if (newIndex >= heros.length) {
newIndex = newIndex - heros.length;
}
this.heroNodes[6] = this.load_hui(heros[newIndex], 6);
// 确保新创建的节点使用正确的缩放值
if (this.heroNodes[6]) {
this.heroNodes[6].setScale(this.getHeroScale(6));
}
// 动画完成,解除锁定
this.isMoving = false;
this.moveTimeoutId = null;
}, 200); // 与动画时间保持一致
}
reset() {
this.node.destroy()
}
}