52 lines
2.1 KiB
TypeScript
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]);
|
|
}
|
|
}
|