123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- import { _decorator, Component, Node, tween, Vec3 } from "cc";
- import BaseUI from "../../scripts/base/BaseUI";
- import { Hall } from "../hall/Hall";
- import { RewardLayer } from "../layer/RewardLayer";
- import { GoodsId } from "../../scripts/api/GoodsId";
- import { Label } from "cc";
- import UserM from "../../scripts/api/UserM";
- import Utils from "../../scripts/utils/Utils";
- import { CritLayer } from "../layer/CritLayer";
- import { UIOpacity } from "cc";
- import UIUtils from "../../scripts/base/UIUtils";
- import { Animation } from "cc";
- import { isValid } from "cc";
- import { Sprite } from "cc";
- import { FlyContainer } from "../hall/FlyContainer";
- import GameM, { GameSpinResult } from "../../scripts/api/GameM";
- import ItemsM from "../../scripts/mgr/ItemsM";
- import { Widget } from "cc";
- const { ccclass, property } = _decorator;
- @ccclass("WheelDialog")
- export class WheelDialog extends BaseUI {
- static async show(gameId: number) {
- let dialog = await Hall.ins.showLayer("prefab/play/WheelDialog");
- dialog.getComponent(WheelDialog).init(gameId);
- }
- private gameId: number;
- init(gameId: number) {
- this.gameId = gameId;
- this.requestAndStartSpin();
- }
- private static mock = 0;
- private data: GameSpinResult;
- async requestAndStartSpin() {
- let result: GameSpinResult = await GameM.ins.gameSpin(this.gameId);
- if (!result) {
- return;
- }
- this.data = result;
- let pog = this.data.spinPog;
- let index = 0;
- for (let i = 0; i < WheelDialog.REWARDS.length; i++) {
- let reward = WheelDialog.REWARDS[i];
- if (reward == pog) {
- index = i;
- break;
- }
- }
- this.spinToIndex(index);
- }
- private rotateSprite: Node;
- private isSpinning: boolean = false;
- private currentAngle: number = 0;
- @property(Number)
- public wheelRewardAllCount: number = 8;
- @property(Number)
- public spinDuration: number = 3.0; // 轉動持續時間
- @property(Number)
- public spinRounds: number = 5; // 轉動圈數
- private static readonly REWARDS = [
- 25, 50, 100, 200, 500, 1200, 2500, 5000, 10000, 0,
- ];
- private btn_use_crit_card: Node;
- private _rewardIndex: number = 0;
- protected onLoad(): void {
- super.onLoad();
- this.btn_use_crit_card = this.FindNode("btn_use_crit_card");
- this.btn_use_crit_card.active = false;
- this.rotateSprite = this.FindNode("rotateSprite");
- this.FindNode("wheel3").active = true;
- this.setText(
- "lbl_crit_card_count",
- "x" + UserM.ins.getGoodsCount(GoodsId.POG_CRITICAL_CARD)
- );
- }
- protected simpleOnBtnClick(name: string): void {
- if (name.startsWith("btn_start_")) {
- let to = parseInt(name.replace("btn_start_", "")) - 1;
- console.warn("to", to);
- this.spinToIndex(to);
- return;
- }
- switch (name) {
- case "btn_spin":
- if (!this.isSpinning) {
- // this.spinToIndex(2);
- }
- break;
- case "btn_use_crit_card":
- this.useCritCard();
- break;
- }
- }
- useCritCard() {
- if (!this.canUserCrit()) {
- return;
- }
- let reward = this.data?.totalPog;
- if (reward > 0) {
- CritLayer.show(this.gameId, this.data.spinId, reward);
- this.resetWheel();
- this.closePage();
- }
- }
- /**
- * 轉動到指定索引的獎品
- * @param index 獎品索引 (0 到 wheelRewardAllCount-1)
- */
- onStartSpin() {
- this.btn_use_crit_card.active = false;
- let anim_layout = this.FindNode("anim_layout");
- for (let i = 0; i < anim_layout.children.length; i++) {
- let child = anim_layout.children[i];
- child.active = false;
- }
- }
- spinToIndex(index: number) {
- this._rewardIndex = index;
- if (this.isSpinning) {
- console.warn("轉盤正在轉動中,請稍後再試");
- return;
- }
- this.onStartSpin();
- this.resetWheel();
- // 確保索引在有效範圍內
- if (index < 0 || index >= this.wheelRewardAllCount) {
- console.error(
- `無效的獎品索引: ${index}, 有效範圍: 0-${this.wheelRewardAllCount - 1}`
- );
- return;
- }
- this.isSpinning = true;
- // 計算每個獎品的角度
- const anglePerReward = 360 / this.wheelRewardAllCount;
- // 計算目標角度
- // 轉盤順時針轉動,索引0在頂部12點鐘方向
- // 每個獎品區域的中心角度
- const targetAngle = anglePerReward * index + anglePerReward / 2;
- // 計算總轉動角度(多轉幾圈然後停在目標位置)
- // 從當前角度開始轉動
- const totalRotation =
- this.currentAngle + this.spinRounds * 360 + targetAngle;
- // 停止之前的動畫
- tween(this.rotateSprite).stop();
- // 開始新的轉動動畫
- tween(this.rotateSprite)
- .to(
- this.spinDuration,
- { angle: totalRotation },
- {
- easing: "expoOut", // 使用指數緩出效果,快速開始然後急劇減速
- }
- )
- .call(() => {
- // 動畫完成後的回調
- this.currentAngle = totalRotation;
- this.onSpinComplete(index);
- })
- .start();
- }
- /**
- * 轉動完成後的回調
- * @param index 最終停止的獎品索引
- */
- private onSpinComplete(index: number) {
- this.isSpinning = false;
- console.log(`轉盤停止在獎品索引: ${index}`);
- this.btn_use_crit_card.active = true;
- if (this.canUserCrit()) {
- this.FindAs("btn_use_crit_card", Sprite).grayscale = false;
- } else {
- this.FindAs("btn_use_crit_card", Sprite).grayscale = true;
- }
- // 這裡可以添加獲獎邏輯
- this.onReward(index);
- }
- canUserCrit() {
- let can =
- !this.isSpinning &&
- this._rewardIndex != 9 &&
- UserM.ins.getGoodsCount(GoodsId.POG_CRITICAL_CARD) > 0;
- return can;
- }
- protected update(dt: number): void {
- if (this.FindNode("bottom") == null) {
- return;
- }
- this.FindAs("bottom", Widget).updateAlignment();
- }
- /**
- * 獲獎處理
- * @param index 獎品索引
- */
- private onReward(index: number) {
- let self = this;
- console.log(`恭喜獲得獎品索引: ${index}`);
- let first_value = this.data.spinPog;
- this.setText("lbl_add_value_1", "+" + first_value);
- // let rank_percent = this.data.ranKAddition / 100;
- this.setText("lbl_add_value_rank_percent", this.data.ranKAddition+ "%");
- // let pass_percent = this.data.gamePassAddition / 100;
- this.setText("lbl_add_value_pass_percent", this.data.gamePassAddition + "%");
- this.setText(
- "lbl_add_value_2",
- "+" + Utils.formatNumber(this.data.rankPog, 2)
- );
- this.setText(
- "lbl_add_value_3",
- "+" + Utils.formatNumber(this.data.gamePassPog, 2)
- );
- this.setText(
- "lbl_add_value_4",
- "+" + Utils.formatNumber(this.data.totalPog, 2)
- );
- let layout = this.FindNode("anim_layout");
- for (let i = 0; i < layout.children.length - 1; i++) {
- let child = layout.children[i];
- child.active = true;
- child.getComponent(UIOpacity).opacity = 255;
- UIUtils.fadeIn(child, 0.4 * i);
- }
- setTimeout(() => {
- if (!isValid(self.node)) {
- return;
- }
- let final = layout.children[layout.children.length - 1].children[0];
- final.parent.active = true;
- final.setPosition(0, -300, 0);
- UIUtils.AnimBezierMoveAndScale(final, new Vec3(0, 0, 0), 1.2, 0.5, () => {
- if (!isValid(self.node)) {
- return;
- }
- if (self.data.totalPog <= 0) {
- self.closePage();
- return;
- }
- // let changeGoodList = [
-
- // ];
- // UserM.ins.data.goodList.forEach((item) => {
- // if (item.id == GoodsId.POG) {
- // item.count += self.data.totalPog;
- // }
- // });
- UserM.ins.refreshGoods(self.data.goodList);
- // ItemsM.ins.itemChange(changeGoodList,self.data.goodList );
- });
- }, 1000);
- }
- /**
- * 重置轉盤角度
- */
- public resetWheel() {
- tween(this.rotateSprite).stop();
- this.rotateSprite.angle = 0;
- this.currentAngle = 0;
- this.isSpinning = false;
- }
- /**
- * 檢查轉盤是否正在轉動
- */
- public getIsSpinning(): boolean {
- return this.isSpinning;
- }
- /**
- * 開始轉動到指定索引
- * @param index 要轉到的獎品索引
- */
- public startSpin(index: number) {
- if (!this.isSpinning) {
- this.spinToIndex(index);
- }
- }
- }
|