MatchMaster/assets/Script/RainbowOldVisual.ts
WIN-GKKD951VVMJ\Administrator 74cf4413b5 增加一版彩虹机制
2026-09-20 17:14:40 +08:00

79 lines
3.7 KiB
TypeScript
Raw 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.

import RainbowScroll from "./prop/RainbowScroll";
const { ccclass, property } = cc._decorator;
/** C 方案只覆盖底色,方块及其附件仍使用原节点。 */
@ccclass
export default class RainbowOldVisual extends cc.Component {
@property([cc.SpriteFrame])
shapeFrames: cc.SpriteFrame[] = [];
apply(block: any): void {
const icon: cc.Node = block.node.getChildByName("icon");
const frame = this.shapeFrames[block.block_Info.block];
// 100color 只有描边;遮罩复用原颜色图的实心轮廓,不修改真实颜色。
const maskFrame = icon.getComponent(cc.Sprite).spriteFrame;
const bg = this.node.getChildByName("bg");
const mask = this.node.getChildByName("mask");
this.node.setPosition(icon.position);
this.node.setAnchorPoint(icon.getAnchorPoint());
this.node.setContentSize(icon.getContentSize());
this.node.setScale(icon.scaleX, icon.scaleY);
this.node.angle = icon.angle;
this.node.setSiblingIndex(icon.getSiblingIndex());
const sprite = bg.getComponent(cc.Sprite);
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
sprite.trim = false;
sprite.spriteFrame = frame;
mask.getComponent(cc.Mask).spriteFrame = maskFrame;
this.alignFrame(bg, frame, icon);
this.alignFrame(mask, maskFrame, icon);
this.fitColors(mask);
const scroll = this.node.getComponent(RainbowScroll);
if (scroll) scroll.refreshGeometry();
icon.active = false;
}
/** Mask 按原画布绘制,Sprite 默认按裁剪矩形绘制,先还原透明边距。 */
private alignFrame(node: cc.Node, frame: cc.SpriteFrame, icon: cc.Node): void {
const rect = frame.getRect();
const original = frame.getOriginalSize();
const offset = frame.getOffset();
const sx = icon.width / rect.width;
const sy = icon.height / rect.height;
const left = -icon.anchorX * icon.width - (offset.x + (original.width - rect.width) / 2) * sx;
const bottom = -icon.anchorY * icon.height - (offset.y + (original.height - rect.height) / 2) * sy;
node.setAnchorPoint(0.5, 0.5);
node.setContentSize(original.width * sx, original.height * sy);
node.setPosition(left + node.width / 2, bottom + node.height / 2);
node.setScale(1, 1);
}
/** 两张镜像大纹理首尾相接;每一张都足以覆盖遮罩沿滚动轴的投影。 */
private fitColors(mask: cc.Node): void {
const colors = [mask.getChildByName("color1"), mask.getChildByName("color2")];
const radians = colors[0].angle * Math.PI / 180;
const cos = Math.cos(radians), sin = Math.sin(radians);
const direction = cc.v2(-sin, cos);
const width = Math.abs(mask.width * cos) + Math.abs(mask.height * sin) + 2;
const length = Math.abs(mask.width * sin) + Math.abs(mask.height * cos) + 2;
colors.forEach(color => {
const scale = Math.max(1, width / (color.width * Math.abs(color.scaleX)),
length / (color.height * Math.abs(color.scaleY)));
color.setScale(color.scaleX * scale, color.scaleY * scale);
});
let end = length / 2;
colors.forEach(color => {
const colorLength = color.height * Math.abs(color.scaleY);
const center = end - colorLength / 2;
const ox = (0.5 - color.anchorX) * color.width * color.scaleX;
const oy = (0.5 - color.anchorY) * color.height * color.scaleY;
color.setPosition(direction.x * center - (cos * ox - sin * oy),
direction.y * center - (sin * ox + cos * oy));
end -= colorLength;
});
}
}