feat(boss): tint boss sprite outline by phase (P2 green, P3 red)
Add FlashSprite.setOutlineByBossPhase with light/dark green shade option and red fallback; BossPhaseSystem drives HeroViewComp.applyBossPhaseOutline directly after phase switch (MON faction, no hero-level event semantics, pool-node safe); extract getFlashSprite/applyOutlineByLevel to dedupe the three outline call sites.
This commit is contained in:
@@ -19,6 +19,7 @@ import { SkillSet } from "../common/config/SkillSet";
|
|||||||
import { mLogger } from "../common/Logger";
|
import { mLogger } from "../common/Logger";
|
||||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||||
import { BossPhaseComp } from "./BossPhaseComp";
|
import { BossPhaseComp } from "./BossPhaseComp";
|
||||||
|
import { HeroViewComp } from "./HeroViewComp";
|
||||||
|
|
||||||
/** 阶段模块调试日志开关 */
|
/** 阶段模块调试日志开关 */
|
||||||
const DEBUG = true;
|
const DEBUG = true;
|
||||||
@@ -119,6 +120,13 @@ export class BossPhaseSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
|||||||
fromPhase: from,
|
fromPhase: from,
|
||||||
toPhase: phase.index,
|
toPhase: phase.index,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 直接驱动描边:Boss 是 MON 阵营,不走英雄 HeroLvUp 语义;
|
||||||
|
// 且对象池节点上挂全局事件监听易漏注销,直接调视图组件最稳
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
if (view && view.node && view.node.isValid) {
|
||||||
|
view.applyBossPhaseOutline(phase.index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TODO: 阶段退场表现(震屏/变暗等),后续迭代实现 */
|
/** TODO: 阶段退场表现(震屏/变暗等),后续迭代实现 */
|
||||||
|
|||||||
@@ -99,15 +99,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
this.node.setScale(this.scale * Math.abs(this.node.scale.x), 1 * this.node.scale.y); // 确保 scale.x 为正后再乘方向
|
this.node.setScale(this.scale * Math.abs(this.node.scale.x), 1 * this.node.scale.y); // 确保 scale.x 为正后再乘方向
|
||||||
|
|
||||||
// 🔥 重置描边
|
// 🔥 重置描边
|
||||||
if (this.model) {
|
this.applyOutlineByLevel();
|
||||||
let flashSprite = this.node.getComponent(FlashSprite);
|
|
||||||
if (!flashSprite) {
|
|
||||||
flashSprite = this.node.getComponentInChildren(FlashSprite);
|
|
||||||
}
|
|
||||||
if (flashSprite) {
|
|
||||||
flashSprite.setOutlineByLevel(this.model.lv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,17 +163,36 @@ export class HeroViewComp extends CCComp {
|
|||||||
this.spawnTimedFx("game/skill/buff/buff_lvup", this.node, 1.0);
|
this.spawnTimedFx("game/skill/buff/buff_lvup", this.node, 1.0);
|
||||||
|
|
||||||
// 升级时同步更新描边
|
// 升级时同步更新描边
|
||||||
if (this.model) {
|
this.applyOutlineByLevel();
|
||||||
let flashSprite = this.node.getComponent(FlashSprite);
|
}
|
||||||
if (!flashSprite) {
|
|
||||||
flashSprite = this.node.getComponentInChildren(FlashSprite);
|
/** 按英雄等级应用描边(升级/初始化共用入口) */
|
||||||
}
|
private applyOutlineByLevel() {
|
||||||
if (flashSprite) {
|
if (!this.model) return;
|
||||||
flashSprite.setOutlineByLevel(this.model.lv);
|
const flashSprite = this.getFlashSprite();
|
||||||
}
|
if (flashSprite) {
|
||||||
|
flashSprite.setOutlineByLevel(this.model.lv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 Boss 阶段应用描边(P2 绿 / P3 红)
|
||||||
|
* Why: 由 BossPhaseSystem 直接调用,不走英雄 HeroLvUp 事件语义
|
||||||
|
* (Boss 是 MON 阵营,且对象池节点挂全局监听易漏注销)
|
||||||
|
* @param phase 阶段索引:1=P2 / 2=P3
|
||||||
|
*/
|
||||||
|
public applyBossPhaseOutline(phase: number) {
|
||||||
|
const flashSprite = this.getFlashSprite();
|
||||||
|
if (flashSprite) {
|
||||||
|
flashSprite.setOutlineByBossPhase(phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查找 FlashSprite 组件(优先自身,回退子节点),描边三处调用点统一入口 */
|
||||||
|
private getFlashSprite(): FlashSprite | null {
|
||||||
|
return this.node.getComponent(FlashSprite) ?? this.node.getComponentInChildren(FlashSprite);
|
||||||
|
}
|
||||||
|
|
||||||
/** 攻击力提升特效 */
|
/** 攻击力提升特效 */
|
||||||
private ap_up() {
|
private ap_up() {
|
||||||
this.spawnTimedFx("game/skill/buff/buff_apup", this.node, 1.0);
|
this.spawnTimedFx("game/skill/buff/buff_apup", this.node, 1.0);
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ export class FlashSprite extends Component {
|
|||||||
@property({ type: Material, tooltip: '绿色描边材质(2级)' })
|
@property({ type: Material, tooltip: '绿色描边材质(2级)' })
|
||||||
outlineMatGreen: Material | null = null;
|
outlineMatGreen: Material | null = null;
|
||||||
|
|
||||||
|
@property({ type: Material, tooltip: '淡绿描边材质(Boss阶段2)' })
|
||||||
|
outlineMatGreenLight: Material | null = null;
|
||||||
|
|
||||||
|
@property({ type: Material, tooltip: '深绿描边材质(Boss阶段2备选)' })
|
||||||
|
outlineMatGreenDark: Material | null = null;
|
||||||
|
|
||||||
@property({ type: Material, tooltip: '蓝色描边材质(3级)' })
|
@property({ type: Material, tooltip: '蓝色描边材质(3级)' })
|
||||||
outlineMatBlue: Material | null = null;
|
outlineMatBlue: Material | null = null;
|
||||||
|
|
||||||
@@ -19,6 +25,9 @@ export class FlashSprite extends Component {
|
|||||||
@property({ type: Material, tooltip: '黄色描边材质(5级)' })
|
@property({ type: Material, tooltip: '黄色描边材质(5级)' })
|
||||||
outlineMatYellow: Material | null = null;
|
outlineMatYellow: Material | null = null;
|
||||||
|
|
||||||
|
@property({ type: Material, tooltip: '红色描边材质(Boss阶段3)' })
|
||||||
|
outlineMatRed: Material | null = null;
|
||||||
|
|
||||||
orginalFlashMaterial: Material | null = null;
|
orginalFlashMaterial: Material | null = null;
|
||||||
defaultMaterial: Material | null = null; // 缓存最原始的无描边材质
|
defaultMaterial: Material | null = null; // 缓存最原始的无描边材质
|
||||||
sprite: Sprite | null = null;
|
sprite: Sprite | null = null;
|
||||||
@@ -64,6 +73,37 @@ export class FlashSprite extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 Boss 阶段设置描边材质(优先级高于等级描边)
|
||||||
|
* Why: Boss 阶段是战斗强反馈(绿色警告 / 红色危险),与英雄等级成长是两套视觉语言,
|
||||||
|
* 用独立通道避免污染 setOutlineByLevel 的等级语义
|
||||||
|
* @param phase 阶段索引:1=P2 绿 / 2=P3 红 / 0=P1 恢复默认
|
||||||
|
* @param greenShade P2 绿色色调:'light' 淡绿(默认)/ 'dark' 深绿
|
||||||
|
*/
|
||||||
|
public setOutlineByBossPhase(phase: number, greenShade: 'light' | 'dark' = 'light') {
|
||||||
|
if (!this.sprite) {
|
||||||
|
this.sprite = this.node.getComponent(Sprite);
|
||||||
|
}
|
||||||
|
if (!this.sprite) return;
|
||||||
|
|
||||||
|
let targetMat: Material | null = null;
|
||||||
|
if (phase === 1) {
|
||||||
|
targetMat = greenShade === 'dark'
|
||||||
|
? (this.outlineMatGreenDark ?? this.outlineMatGreenLight ?? this.outlineMatGreen)
|
||||||
|
: (this.outlineMatGreenLight ?? this.outlineMatGreenDark ?? this.outlineMatGreen);
|
||||||
|
} else if (phase >= 2) {
|
||||||
|
targetMat = this.outlineMatRed ?? this.outlineMatYellow;
|
||||||
|
} else {
|
||||||
|
targetMat = this.defaultMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetMat) {
|
||||||
|
// 更新基础材质,确保闪白结束后恢复到这个阶段描边材质
|
||||||
|
this.orginalFlashMaterial = targetMat;
|
||||||
|
this.sprite.setSharedMaterial(targetMat, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public clickFlash() {
|
public clickFlash() {
|
||||||
if (!this.sprite || !this.hitFlashMaterial) return;
|
if (!this.sprite || !this.hitFlashMaterial) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user