const { ccclass, property, requireComponent } = cc._decorator; /** 挂到带 Sprite 的节点上,并在 Inspector 中指定 svip_title_shine.effect。 */ @ccclass @requireComponent(cc.Sprite) export default class ShopTitleShine extends cc.Component { @property(cc.EffectAsset) effectAsset: cc.EffectAsset = null; @property({ tooltip: '使用彩虹色扫光' }) rainbow: boolean = false; private material: cc.Material = null; private sprite: cc.Sprite = null; private frame: cc.SpriteFrame = null; private delayRemaining: number = 0.15; private elapsed: number = 0; protected onLoad(): void { this.sprite = this.getComponent(cc.Sprite); if (this.effectAsset) { this.createMaterial(); } else { cc.assetManager.getBundle('shop').load('effect/svip_title_shine', cc.EffectAsset, (error, effect: cc.EffectAsset) => { if (error || !cc.isValid(this.node)) return; this.effectAsset = effect; this.createMaterial(); }); } } private createMaterial(): void { let material = new cc.Material(); // @ts-ignore Cocos Creator 2.4 通过 effectAsset 创建运行时材质。 material.effectAsset = this.effectAsset; material.setProperty("shinePosition", -0.2); material.setProperty("shineAngle", 0.2); material.setProperty("shineColor", [1.0, 0.95, 0.68, 1.0]); this.material = material; this.setRainbow(this.rainbow); this.updateFrame(); this.sprite.setMaterial(0, material); } setRainbow(enabled: boolean): void { this.rainbow = enabled; if (!this.material) return; this.material.setProperty('rainbow', enabled ? 1 : 0); this.material.setProperty('shineWidth', enabled ? 0.10 : 0.06); this.material.setProperty('shineStrength', enabled ? 1.6 : 1.2); } private updateFrame(): void { const frame = this.sprite.spriteFrame; if (!frame || frame === this.frame) return; this.frame = frame; const rect = frame.getRect(), texture = frame.getTexture(), rotated = frame.isRotated(); texture.packable = false; this.material.setProperty('uvRect', [rect.x / texture.width, rect.y / texture.height, (rotated ? rect.height : rect.width) / texture.width, (rotated ? rect.width : rect.height) / texture.height]); this.material.setProperty('uvRotated', rotated ? 1 : 0); } protected update(dt: number): void { if (!this.material) { return; } this.updateFrame(); if (this.delayRemaining > 0) { this.delayRemaining = Math.max(0, this.delayRemaining - dt); return; } this.elapsed += dt; let progress = Math.min(1, this.elapsed / 0.8); this.material.setProperty("shinePosition", -0.2 + 1.4 * progress); if (progress >= 1) { this.elapsed = 0; this.delayRemaining = 1.25; this.material.setProperty("shinePosition", -0.2); } } protected onDestroy(): void { if (this.material && cc.isValid(this.material)) { this.material.destroy(); } this.material = null; } }