MatchMaster/assets/Script/RainbowBottleWater.ts
2026-09-15 20:14:07 +08:00

52 lines
2.1 KiB
TypeScript

const { ccclass, property, requireComponent } = cc._decorator;
/** 保留 fillRange 作为能量读数,改由 Shader 绘制起伏液面。 */
@ccclass
@requireComponent(cc.Sprite)
export default class RainbowBottleWater extends cc.Component {
@property({ tooltip: "液面波浪高度(像素)", min: 0 })
waveHeight: number = 4;
@property({ tooltip: "液体流动速度", min: 0 })
waveSpeed: number = 1;
private sprite: cc.Sprite = null;
private material: cc.Material = null;
private elapsed = 0;
onLoad(): void {
this.sprite = this.getComponent(cc.Sprite);
const frame = this.sprite.spriteFrame;
const texture = frame.getTexture();
// 在异步加载材质前禁止打图集,保持液面 Shader 的 UV 范围稳定。
texture.packable = false;
cc.resources.load("shader/rainbow_bottle", cc.Material, (error: Error, material: cc.Material) => {
if (!cc.isValid(this, true)) return;
if (error) {
cc.warn("彩虹瓶子波浪材质加载失败", error);
return;
}
this.sprite.setMaterial(0, material);
this.material = this.sprite.getMaterial(0);
if (cc.sys.glExtension("OES_standard_derivatives")) {
this.material.define("CC_SUPPORT_standard_derivatives", true);
}
const rect = frame.getRect();
const rotated = frame.isRotated();
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);
this.sprite.type = cc.Sprite.Type.SIMPLE;
this.lateUpdate(0);
});
}
lateUpdate(dt: number): void {
if (!this.material) return;
this.elapsed += dt * this.waveSpeed;
this.material.setProperty("water", [this.sprite.fillRange, this.elapsed,
this.waveHeight / this.node.height, 1 / this.node.height]);
}
}