feat: 重构英雄编队逻辑,优化出生与排队规则

1. 移除英雄出生落点偏移,改为按职业优先级从右向左排队
2. 重构英雄卡点击逻辑,支持点击整张卡牌选取
3. 新增英雄血量背景预制体与UI按钮样式
4. 优化AOE技能目标选取逻辑,使用中排基准点
This commit is contained in:
panFD
2026-08-19 22:52:17 +08:00
parent 0ec27b09a4
commit 6c82c632b6
14 changed files with 6667 additions and 6588 deletions

View File

@@ -6,7 +6,7 @@
* 1. 渲染单个英雄卡的显示信息(名称、等级、描述、图标、费用),
* 展示方式与 SCardComp 一致(图集静态图标 + ★等级 + 描述词条)。
* 同时支持动态升级卡SpecialUpgrade + target_hero_eid按英雄卡样式渲染。
* 2. 处理购买点击 → UseHeroCard 上限校验(guard) → 扣费 → 派发 CallHero 召唤英雄。
* 2. 处理卡牌点击(点击卡牌任意区域即选取) → UseHeroCard 上限校验(guard) → 派发 CallHero 召唤英雄。
* 特殊卡(升级/刷新)则派发 UseSpecialCard。
* 3. 使用成功后派发 CardUsed 事件,通知 MissionCardComp 刷新英雄卡池。
*
@@ -33,7 +33,7 @@ const { ccclass, property } = _decorator;
* CHeroComp —— 英雄卡池单个英雄卡项
*
* 由 MissionCardComp.cacheCardComps() 实例化。
* 以图标 + 名称 + 描述词条 + 购买按钮的形式呈现。
* 以图标 + 名称 + 描述词条 + 费用角标的形式呈现,点击卡牌任意区域即选取
*/
@ccclass('CHeroComp')
@ecs.register('CHeroComp', false)
@@ -72,7 +72,7 @@ export class CHeroComp extends CCComp {
@property(Label)
private level_label: Label = null;
/** 购买按钮节点 */
/** 费用显示节点(原购买按钮,现仅展示费用,不再承担点击) */
@property({ type: Node })
private buy_node: Node = null;
@@ -118,9 +118,10 @@ export class CHeroComp extends CCComp {
fied3: !!this.fied3,
buy_node: !!this.buy_node
});
this.buy_node?.on(NodeEventType.TOUCH_START, this.onBuyTouchStart, this);
this.buy_node?.on(NodeEventType.TOUCH_END, this.onBuyClick, this);
this.buy_node?.on(NodeEventType.TOUCH_CANCEL, this.onBuyTouchCancel, this);
// 点击整张卡牌选取英雄:监听挂载在卡牌根节点,命中区域由根节点 UITransformer 决定
this.node.on(NodeEventType.TOUCH_START, this.onCardTouchStart, this);
this.node.on(NodeEventType.TOUCH_END, this.onCardClick, this);
this.node.on(NodeEventType.TOUCH_CANCEL, this.onCardTouchCancel, this);
// 缓存透明度组件(用于淡入淡出动画)
this.opacityComp = this.node.getComponent(UIOpacity) || this.node.addComponent(UIOpacity);
@@ -134,10 +135,10 @@ export class CHeroComp extends CCComp {
onDestroy() {
super.onDestroy();
if (this.buy_node && this.buy_node.isValid) {
this.buy_node.off(NodeEventType.TOUCH_START, this.onBuyTouchStart, this);
this.buy_node.off(NodeEventType.TOUCH_END, this.onBuyClick, this);
this.buy_node.off(NodeEventType.TOUCH_CANCEL, this.onBuyTouchCancel, this);
if (this.node && this.node.isValid) {
this.node.off(NodeEventType.TOUCH_START, this.onCardTouchStart, this);
this.node.off(NodeEventType.TOUCH_END, this.onCardClick, this);
this.node.off(NodeEventType.TOUCH_CANCEL, this.onCardTouchCancel, this);
}
}
@@ -303,7 +304,7 @@ export class CHeroComp extends CCComp {
this.updateHeroAnimation(this.icon_node, renderUuid, this.iconVisualToken);
}
// 购买按钮费用显示
// 费用显示(原购买按钮节点,现仅作费用角标)
if (this.buy_node) {
this.buy_node.active = true;
const costLabel = this.cost_label
@@ -372,7 +373,7 @@ export class CHeroComp extends CCComp {
/**
* 播放购买动画卡牌放大scale 1→1.1+ 淡出,结束后隐藏节点。
* 动画结束由 onBuyClick 的后续逻辑CardUsed 刷新卡池)接管。
* 动画结束由 onCardClick 的后续逻辑CardUsed 刷新卡池)接管。
*/
private playPurchaseAnim() {
Tween.stopAllByTarget(this.node);
@@ -413,44 +414,44 @@ export class CHeroComp extends CCComp {
}
}
// ======================== 按钮动画 ========================
// ======================== 点击反馈动画 ========================
/** 按钮正常缩放 */
private readonly btnNormalScale: number = 1;
/** 按钮按下缩放 */
private readonly btnPressScale: number = 0.92;
/** 按钮点击回弹峰值缩放 */
private readonly btnClickScale: number = 1.08;
/** 卡牌正常缩放 */
private readonly cardNormalScale: number = 1;
/** 卡牌按下缩放 */
private readonly cardPressScale: number = 0.92;
/** 卡牌点击回弹峰值缩放 */
private readonly cardClickScale: number = 1.08;
/** 购买按钮按下:缩小反馈 */
private onBuyTouchStart() {
this.playBtnScaleTo(this.btnPressScale, 0.06);
/** 卡牌按下:缩小反馈 */
private onCardTouchStart() {
this.playCardScaleTo(this.cardPressScale, 0.06);
}
/** 购买按钮取消:恢复缩放 */
private onBuyTouchCancel() {
this.playBtnScaleTo(this.btnNormalScale, 0.08);
/** 卡牌取消(滑出卡牌区域):恢复缩放 */
private onCardTouchCancel() {
this.playCardScaleTo(this.cardNormalScale, 0.08);
}
/** 按钮缩放动画(通用) */
private playBtnScaleTo(scale: number, duration: number) {
if (!this.buy_node || !this.buy_node.isValid) return;
Tween.stopAllByTarget(this.buy_node);
tween(this.buy_node)
/** 卡牌缩放动画(通用) */
private playCardScaleTo(scale: number, duration: number) {
if (!this.node || !this.node.isValid) return;
Tween.stopAllByTarget(this.node);
tween(this.node)
.to(duration, { scale: new Vec3(scale, scale, 1) })
.start();
}
/** 按钮点击回弹动画:先弹到峰值再回到正常 */
private playBtnClickAnim(onComplete?: () => void) {
if (!this.buy_node || !this.buy_node.isValid) {
/** 卡牌点击回弹动画:先弹到峰值再回到正常 */
private playCardClickAnim(onComplete?: () => void) {
if (!this.node || !this.node.isValid) {
onComplete?.();
return;
}
Tween.stopAllByTarget(this.buy_node);
tween(this.buy_node)
.to(0.05, { scale: new Vec3(this.btnClickScale, this.btnClickScale, 1) })
.to(0.08, { scale: new Vec3(this.btnNormalScale, this.btnNormalScale, 1) })
Tween.stopAllByTarget(this.node);
tween(this.node)
.to(0.05, { scale: new Vec3(this.cardClickScale, this.cardClickScale, 1) })
.to(0.08, { scale: new Vec3(this.cardNormalScale, this.cardNormalScale, 1) })
.call(() => onComplete?.())
.start();
}
@@ -561,20 +562,20 @@ export class CHeroComp extends CCComp {
// ======================== 购买逻辑 ========================
/**
* 购买点击处理:
* 1. 播放按钮点击回弹动画。
* 卡牌点击处理(点击卡牌任意区域即选取)
* 1. 播放卡牌点击回弹动画。
* 2. 英雄卡先通过 UseHeroCard 事件做数量上限校验guard 模式,可被取消)。
* 3. 按卡牌类型分发效果:英雄卡 → CallHero 召唤英雄;特殊卡 → UseSpecialCard。
* 4. 派发 CardUsed 通知 MissionCardComp 刷新英雄卡池。
* 5. 标记已购买,隐藏购买按钮
* 5. 标记已购买,隐藏费用角标
*
* 注:购买不花费金币(免费获取),原扣费逻辑已移除。
*/
private onBuyClick() {
private onCardClick() {
if (!this.cardData || this.isPurchased) return;
// 播放按钮点击回弹动画(视觉反馈,不阻塞后续逻辑)
this.playBtnClickAnim();
// 播放卡牌点击回弹动画(视觉反馈,不阻塞后续逻辑)
this.playCardClickAnim();
oops.audio.playEffect("music/button");