MatchMaster/assets/res/effect/JungleShine.ts
2026-09-29 18:57:56 +08:00

94 lines
3.6 KiB
TypeScript
Raw Permalink 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.

const { ccclass, property, requireComponent } = cc._decorator;
/** 挂到带 Sprite 的节点上,并在 Inspector 中指定 jungle_shine.effect。 */
@ccclass
@requireComponent(cc.Sprite)
export default class JungleShine extends cc.Component {
@property(cc.EffectAsset)
effectAsset: cc.EffectAsset = null;
private material: cc.Material = null;
private retainedEffect: cc.EffectAsset = null;
private delayRemaining: number = 0.15;
private elapsed: number = 0;
protected onLoad(): void {
let sprite = this.getComponent(cc.Sprite);
if (!sprite) return;
if (this.isEffectReady(this.effectAsset)) {
this.createMaterial(sprite, this.effectAsset);
} else {
// 旧预制体可能仍持有已释放的 EffectAsset,非空不代表可用。
cc.assetManager.loadBundle("publicUI", (error, bundle) => {
if (!cc.isValid(this, true)) return;
if (error) {
cc.error("[JungleShine] 加载 publicUI 失败", error);
return;
}
bundle.load("jungle_shine", cc.EffectAsset, (error, effect: cc.EffectAsset) => {
if (!cc.isValid(this, true)) return;
if (error || !this.isEffectReady(effect)) {
cc.error("[JungleShine] 加载扫光特效失败", error || "EffectAsset 数据无效");
return;
}
this.effectAsset = effect;
this.createMaterial(sprite, effect);
});
});
}
}
private isEffectReady(effect: cc.EffectAsset): boolean {
if (!cc.isValid(effect, true)) return false;
// Creator 2.4 的类型声明未包含 techniques。
const techniques = (effect as any).techniques;
return Array.isArray(techniques) && techniques.length > 0
&& techniques.every(technique => technique && Array.isArray(technique.passes) && technique.passes.length > 0);
}
private createMaterial(sprite: cc.Sprite, effect: cc.EffectAsset): void {
// 运行时创建的材质由本组件持有,同时保留其特效资源。
this.retainedEffect = effect.addRef();
let material = new cc.Material();
// @ts-ignore Cocos Creator 2.4 通过 effectAsset 创建运行时材质。
material.effectAsset = effect;
material.setProperty("shinePosition", -0.35);
material.setProperty("shineWidth", 0.075);
material.setProperty("shineStrength", 1.8);
material.setProperty("shineAngle", 0.2);
material.setProperty("shineColor", [1.0, 0.95, 0.68, 1.0]);
this.material = material;
sprite.setMaterial(0, material);
}
protected update(dt: number): void {
if (!this.material) {
return;
}
if (this.delayRemaining > 0) {
this.delayRemaining = Math.max(0, this.delayRemaining - dt);
return;
}
this.elapsed += dt;
let progress = Math.min(1, this.elapsed / 0.72);
this.material.setProperty("shinePosition", -0.35 + 1.7 * progress);
if (progress >= 1) {
this.elapsed = 0;
this.delayRemaining = 1.25;
this.material.setProperty("shinePosition", -0.35);
}
}
protected onDestroy(): void {
if (this.material && cc.isValid(this.material)) {
this.material.destroy();
}
this.material = null;
if (cc.isValid(this.retainedEffect, true)) {
this.retainedEffect.decRef();
}
this.retainedEffect = null;
}
}