162 lines
6.2 KiB
TypeScript
162 lines
6.2 KiB
TypeScript
import NumberToImage from "./NumberToImage";
|
|
|
|
const { ccclass } = cc._decorator;
|
|
|
|
export type ThreeWinsProp = "hourglass" | "rocket";
|
|
|
|
export interface ThreeWinsSelection {
|
|
hourglass: boolean;
|
|
rocket: boolean;
|
|
}
|
|
|
|
export interface ThreeWinsPanelData {
|
|
level: number;
|
|
threeWinStreak: number;
|
|
tenWinStreak: number;
|
|
hourglassAmount: number;
|
|
rocketAmount: number;
|
|
infiniteHourglass?: boolean;
|
|
infiniteRocket?: boolean;
|
|
}
|
|
|
|
export interface ThreeWinsPanelCallbacks {
|
|
onProp: (prop: ThreeWinsProp, selected: boolean) => void;
|
|
onStart: (selection: ThreeWinsSelection) => void;
|
|
}
|
|
|
|
/** 只管理预制体显示和选择;库存检查、购买及开局由 SceneManager 处理。 */
|
|
@ccclass
|
|
export default class ThreeWinsPanel extends cc.Component {
|
|
private atlas: cc.SpriteAtlas = null;
|
|
private data: ThreeWinsPanelData = null;
|
|
private callbacks: ThreeWinsPanelCallbacks = null;
|
|
private selected: ThreeWinsSelection = { hourglass: false, rocket: false };
|
|
private bound = false;
|
|
private entryScale: cc.Vec2 = null;
|
|
|
|
init(atlas: cc.SpriteAtlas, data: ThreeWinsPanelData, callbacks: ThreeWinsPanelCallbacks) {
|
|
this.atlas = atlas;
|
|
this.callbacks = callbacks;
|
|
this.selected = { hourglass: false, rocket: false };
|
|
if (!this.bound) {
|
|
this.node.getChildByName("hourglass").on("click", this.onHourglass, this);
|
|
this.node.getChildByName("rocket").on("click", this.onRocket, this);
|
|
this.node.getChildByName("begin").on("click", this.onStart, this);
|
|
this.bound = true;
|
|
}
|
|
this.refresh(data);
|
|
this.entryScale = cc.v2(this.node.scaleX, this.node.scaleY);
|
|
this.node.setScale(0);
|
|
}
|
|
|
|
playEntry() {
|
|
if (!this.entryScale) return;
|
|
const scale = this.entryScale;
|
|
this.entryScale = null;
|
|
cc.tween(this.node)
|
|
.to(0.28, { scaleX: scale.x * 1.06, scaleY: scale.y * 1.06 }, { easing: "cubicOut" })
|
|
.to(0.10, { scaleX: scale.x * 0.97, scaleY: scale.y * 0.97 }, { easing: "sineInOut" })
|
|
.to(0.12, { scaleX: scale.x, scaleY: scale.y }, { easing: "sineOut" })
|
|
.start();
|
|
}
|
|
|
|
refresh(data: ThreeWinsPanelData) {
|
|
this.data = data;
|
|
const tier = Math.min(3, Math.max(0, Math.floor(data.threeWinStreak || 0)));
|
|
const tenWins = Math.min(10, Math.max(0, Math.floor(data.tenWinStreak || 0)));
|
|
const box = this.node.getChildByName("box");
|
|
for (let i = 0; i <= 3; i++) box.getChildByName("box" + i).active = i === tier;
|
|
|
|
const three = this.node.getChildByName("three");
|
|
three.getChildByName("progress").getComponent(cc.Sprite).spriteFrame = this.atlas.getSpriteFrame("progress_" + tier);
|
|
for (let i = 1; i <= 3; i++) three.getChildByName("progress" + i).active = i <= tier;
|
|
this.node.getChildByName("progress").getComponent(cc.Sprite).fillRange = tenWins / 10;
|
|
|
|
this.renderNumber(this.node.getChildByName("custom"), data.level, "custom_", 44);
|
|
this.renderNumber(this.node.getChildByName("rainbowNumber"), tenWins, "rainbow", 34, true);
|
|
this.renderProp("hourglass");
|
|
this.renderProp("rocket");
|
|
}
|
|
|
|
refreshInventory(data: ThreeWinsPanelData) {
|
|
const previous = this.data;
|
|
this.data = data;
|
|
if (!previous || previous.hourglassAmount !== data.hourglassAmount || previous.infiniteHourglass !== data.infiniteHourglass) {
|
|
this.renderProp("hourglass");
|
|
}
|
|
if (!previous || previous.rocketAmount !== data.rocketAmount || previous.infiniteRocket !== data.infiniteRocket) {
|
|
this.renderProp("rocket");
|
|
}
|
|
}
|
|
|
|
setSelected(prop: ThreeWinsProp, selected: boolean) {
|
|
this.selected[prop] = selected;
|
|
this.renderProp(prop);
|
|
}
|
|
|
|
private onHourglass() {
|
|
if (this.callbacks) this.callbacks.onProp("hourglass", !this.selected.hourglass);
|
|
}
|
|
|
|
private onRocket() {
|
|
if (this.callbacks) this.callbacks.onProp("rocket", !this.selected.rocket);
|
|
}
|
|
|
|
private onStart() {
|
|
if (this.callbacks) this.callbacks.onStart({ ...this.selected });
|
|
}
|
|
|
|
private renderProp(prop: ThreeWinsProp) {
|
|
const node = this.node.getChildByName(prop);
|
|
const count = prop === "hourglass" ? this.data.hourglassAmount : this.data.rocketAmount;
|
|
const infinite = prop === "hourglass" ? this.data.infiniteHourglass : this.data.infiniteRocket;
|
|
const available = count > 0 || !!infinite;
|
|
if (!available) this.selected[prop] = false;
|
|
const selected = this.selected[prop];
|
|
node.getChildByName("add").active = !available;
|
|
node.getChildByName("select").active = selected;
|
|
const remaining = node.getChildByName("remaining");
|
|
remaining.active = available && !selected;
|
|
|
|
const amount = remaining.getChildByName("number");
|
|
if (infinite) {
|
|
this.clearNumber(amount);
|
|
this.addCountSymbol(amount, "∞", 0);
|
|
return;
|
|
}
|
|
|
|
this.renderNumber(amount, count, "prop_", 30);
|
|
}
|
|
|
|
private renderNumber(target: cc.Node, value: number, prefix: string, spacing: number, right = false) {
|
|
this.clearNumber(target);
|
|
const number = Math.max(0, Math.floor(value || 0));
|
|
NumberToImage.numberToImageNodesPublic(this.atlas, number, spacing, 0, prefix, target, false);
|
|
const offset = right ? (target.childrenCount - 1) * spacing : (target.childrenCount - 1) * spacing / 2;
|
|
for (const digit of target.children) digit.x -= offset;
|
|
}
|
|
|
|
private clearNumber(target: cc.Node) {
|
|
for (const child of target.children.slice()) child.destroy();
|
|
target.removeAllChildren();
|
|
}
|
|
|
|
private addCountSymbol(target: cc.Node, text: string, x: number) {
|
|
const node = new cc.Node("symbol");
|
|
node.parent = target;
|
|
node.x = x;
|
|
const label = node.addComponent(cc.Label);
|
|
label.string = text;
|
|
label.fontSize = 36;
|
|
label.lineHeight = 44;
|
|
label.enableBold = true;
|
|
const outline = node.addComponent(cc.LabelOutline);
|
|
outline.color = cc.color(126, 44, 20);
|
|
outline.width = 2;
|
|
}
|
|
|
|
onDestroy() {
|
|
this.callbacks = null;
|
|
}
|
|
}
|