MatchMaster/assets/testSeven/TestSeven.ts

161 lines
7.5 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 NumberToImage from "../Script/NumberToImage";
const { ccclass, property } = cc._decorator;
/** 仅编辑器预览使用。通过真实 Prefab 的视图接口模拟,不调用正式 Runtime。 */
@ccclass
export default class TestSeven extends cc.Component {
@property(cc.Prefab) rewardPrefab: cc.Prefab = null;
@property(cc.SpriteAtlas) rewardFont: cc.SpriteAtlas = null;
private previousFont: any = null;
private gift: cc.Node = null;
private view: any = null;
private info: any = null;
private status: cc.Label = null;
private busy = false;
private failNext = false;
start() {
if (!CC_PREVIEW) {
cc.error("[testSeven] 仅允许编辑器预览,请从构建中排除 testSeven。");
return;
}
this.status = this.label("正在加载 seven_day_gift…", 0, 850, 26);
if (!this.rewardPrefab || !this.rewardFont) return this.report("测试场景缺少奖励弹窗或数字图集引用");
this.previousFont = NumberToImage.font;
NumberToImage.font = this.rewardFont;
cc.assetManager.loadBundle("seven_day_gift", (error, bundle) => {
if (!cc.isValid(this.node, true)) return;
if (error) return this.report("分包加载失败:" + error.message);
bundle.load("prefab/sevenDayGift", cc.Prefab, (loadError, prefab: cc.Prefab) => {
if (!cc.isValid(this.node, true)) return;
if (loadError) return this.report("Prefab 加载失败:" + loadError.message);
this.gift = cc.instantiate(prefab);
this.node.addChild(this.gift);
this.gift.setPosition(0, 0);
this.view = this.gift.getComponent("SevenDayGift");
if (!this.view) return this.report("缺少 SevenDayGift 组件");
this.view.setCloseHandler(() => this.report("已关闭,可选择状态重新打开"));
// 控制面板在遮罩上方,使用与活动一致的 1080 × 1920 设计尺寸。
for (let day = 1; day <= 7; day++) {
this.button("第" + day + "天", (day - 4) * 140, -670, () => this.select(day));
}
this.button("今日已领", -330, -755, () => this.select(this.info.nextRewardDay, "claimed"));
this.button("全部完成", -110, -755, () => this.select(7, "completed"));
this.button("已过期", 110, -755, () => this.select(3, "expired"));
this.button("自动领取", 330, -755, () => this.open(true));
this.button("下次失败", -220, -840, () => {
this.failNext = true;
this.report("下一次领取将在 1.2 秒后失败,可再次点击重试");
});
this.button("重新打开", 0, -840, () => this.open(false));
this.button("重置", 220, -840, () => { this.failNext = false; this.select(1); });
this.select(1);
});
});
}
private select(day: number, state: string = "active") {
if (this.busy) return;
const claimedCount = state === "completed" ? 7 : state === "claimed" ? day : day - 1;
const items = [
[{ type: "coin", count: 100 }],
[{ type: "hammer", count: 2 }],
[{ type: "freeze", count: 2 }, { type: "coin", count: 200 }],
[{ type: "magic_wand", count: 2 }],
[{ type: "infinite_health", count: 30 }],
[{ type: "coin", count: 300 }, { type: "hammer", count: 2 }, { type: "freeze", count: 2 }],
[{ type: "cat_skin", count: 1, itemId: 1 }],
];
this.info = {
serverNow: Date.now(), activityId: "testSeven-memory", status: state === "claimed" ? "active" : state,
triggerLevel: 23, triggerReached: true, startAt: Date.now() - 86400000,
endAt: Date.now() + (state === "expired" ? -1 : 7 * 86400000),
claimedCount, todayClaimed: state === "claimed" || state === "completed",
canClaim: state === "active", nextRewardDay: day,
rewards: items.map((reward, index) => ({ day: index + 1, items: reward, claimed: index < claimedCount })),
};
this.open(false);
}
private open(autoClaim: boolean) {
if (this.busy || !this.view || !this.info) return;
this.bindData();
this.view.show(autoClaim);
this.report("本地模拟 | 第" + this.info.nextRewardDay + "天 | " + this.info.status + " | 已领 " + this.info.claimedCount + "/7");
}
private bindData() {
this.view.setData(this.info, (done: (success: boolean) => void) => {
if (this.busy || !this.info.canClaim) return done(false);
this.busy = true;
this.report("模拟领取中…请检查重复点击和关闭拦截");
this.scheduleOnce(() => {
this.busy = false;
if (this.failNext) {
this.failNext = false;
done(false);
return this.report("模拟领取失败,可点击当前奖励重试");
}
const reward = this.info.rewards[this.info.nextRewardDay - 1];
reward.claimed = true;
this.info.claimedCount++;
this.info.todayClaimed = true;
this.info.canClaim = false;
if (this.info.claimedCount === 7) this.info.status = "completed";
// 更新视图仍沿用本地回调,不调用 initializeRuntime。
this.bindData();
done(true);
this.showRewardWindow(reward.items);
this.report("模拟领取成功(不写入资产):" + reward.items.map(item => item.type + " × " + item.count).join(" / "));
}, 1.2);
});
}
private showRewardWindow(items: any[]) {
const node = cc.instantiate(this.rewardPrefab);
this.node.addChild(node);
node.setPosition(0, 0);
node.zIndex = 1001;
const reward = node.getComponent("Reward");
if (!reward) {
node.destroy();
this.report("奖励弹窗缺少 Reward 组件");
return;
}
this.busy = true;
reward.init(items.map(item => ({
type: item.type === "magic_wand" ? "magic" : item.type,
count: Math.max(0, Number(item.count !== undefined ? item.count : item.amount) || 0),
spriteFrame: item.type === "cat_skin" ? this.view.catArt : null,
})).filter(item => item.count > 0), () => { this.busy = false; });
}
onDestroy() {
if (CC_PREVIEW && NumberToImage.font === this.rewardFont) NumberToImage.font = this.previousFont;
}
private report(message: string) { this.status.string = message; }
private label(text: string, x: number, y: number, size: number): cc.Label {
const node = new cc.Node("testSevenLabel");
this.node.addChild(node);
node.setPosition(x, y);
node.zIndex = 1000;
const label = node.addComponent(cc.Label);
label.string = text;
label.fontSize = size;
label.lineHeight = size + 6;
return label;
}
private button(text: string, x: number, y: number, action: () => void) {
const label = this.label(text, x, y, 28);
label.node.color = cc.color(110, 225, 255);
label.node.on(cc.Node.EventType.TOUCH_END, (event: cc.Event) => {
event.stopPropagation();
if (!this.busy) action();
});
}
}