123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- import { MathUtils } from "../../../SubGamePublic/PG_Public/Script/lib/utils/MathUtils";
- import MouseAvatar from "./MouseAvatar";
- import { MouseConst } from "./MouseConst";
- import MouseDecor from "./MouseDecor";
- import MouseIconCover from "./MouseIconCover";
- import MouseIconDetail from "./MouseIconDetail";
- import MouseIconItem from "./MouseIconItem";
- import MouseSuper from "./MouseSuper";
- const { ccclass, property, menu } = cc._decorator;
- const TopCount: number = 1; // 网格上面的格子数量
- const PREPARE_TWEEN_TAG = 101;
- const SCROLL_TWEEN_TAG = 102;
- @ccclass
- @menu("Game/Mouse/MouseIconView")
- export default class MouseIconView extends cc.Component {
- @property(cc.Prefab)
- iconItemPrefab: cc.Prefab = null;
- @property([sp.SkeletonData])
- iconSpines: sp.SkeletonData[] = [];
- @property(cc.Node)
- particleAnimNodeArr: cc.Node = null;
- @property(cc.Node)
- underlayNormal: cc.Node = null;
- @property(cc.Node)
- underlaySuper: cc.Node = null;
- @property(sp.Skeleton)
- spinSplash: sp.Skeleton = null;
- @property(cc.ParticleSystem)
- spinParticle: cc.ParticleSystem = null;
- @property(MouseAvatar)
- mouseAvatar: MouseAvatar = null;
- @property(MouseSuper)
- mouseSuper: MouseSuper = null;
- @property(MouseIconCover)
- mouseIconCover: MouseIconCover = null;
- @property(MouseDecor)
- mouseDecor: MouseDecor = null;
- @property(MouseIconDetail)
- mouseIconDetail: MouseIconDetail = null;
- @property(cc.Node)
- iconRoot: cc.Node = null;
- @property(cc.Node)
- nodeClick: cc.Node = null;
- _callback: Function = null;
- _gameResult: NSlots.ICommonResult = null;
- _iconItemMap: MouseIconItem[][] = []; //客户端显示第0行0列在左下角,服务端是在左上角
- _startRunAudioId: number = 0;
- SCALE_OFFSET = 150; // 放大/缩小偏移
- // =============== 滚动参数 ==================
- // 滚动圈数
- TURBO_ROLL_CIRCLES = [1, 1, 1]; // Turbo转圈数
- NORMAL_ROLL_CIRCLES = [1, 2, 3]; // 正常转圈数
- SUPER_ROLL_CIRCLES = [20, 21, 22]; // 超级转圈数
- rollSpeed = 4000;
- backOutHeight = 213;
- startPosYArr = this.getRowPosY();//各行icon初始的y坐标
- topPosY = MouseConst.IconSize.height * (TopCount + 1); //最上面看不见的位置
- endPosY = - MouseConst.IconSize.height * 2;//最下面看不见的位置,底部下面一个格子处
- oneRoundTime = Math.abs(this.endPosY - this.topPosY) / this.rollSpeed; // 滚动一圈的时间
- backOutTime = this.backOutHeight / this.rollSpeed;
- backOutTimeMutiple = 5; //缓冲系数
- // =============== 滚动参数 ==================
- isStartSuper = false;
- isSpinReady = false;
- gameFrameView: NSlots.GameFrameView = null;
- start() {
- this.gameFrameView = this.node.parent.getComponent('MouseGameFrameView');
- this.initView();
- }
- initView() {
- for (let i = 0; i < MouseConst.GAME_COLUMN; i++) {
- for (let j = MouseConst.GAME_ROW + TopCount - 1; j >= 0; j--) { // 下面的盖在上面
- let iconItem = cc.instantiate(this.iconItemPrefab).getComponent(MouseIconItem);
- iconItem.node.x = MouseConst.IconSize.width * (i - 1);
- iconItem.node.y = MouseConst.IconSize.height * (j - 1);
- iconItem.node.parent = this.iconRoot;
- iconItem.node.active = j < MouseConst.GAME_ROW; // 防止顶部冒出
- iconItem.init(this, i, j);
- iconItem.setItemInfo(this.getRandomId());
- this._iconItemMap[i] = this._iconItemMap[i] || [];
- this._iconItemMap[i][j] = iconItem;
- }
- }
- this.mouseIconCover.initView(this);
- }
- /**
- * 获取随机id
- */
- getRandomId() {
- return MathUtils.getRandomFromArray(MouseConst.NormalIds);
- }
- /**
- * 获取图标动画
- */
- getIconSpineById(spineIndex: number) {
- return this.iconSpines[spineIndex];
- }
- /**
- * 获取每行Y轴坐标
- */
- getRowPosY() {
- let ys: number[] = [];
- for (let index = 0; index < MouseConst.GAME_ROW + TopCount; index++) {
- ys[index] = MouseConst.IconSize.height * (index - 1);
- }
- return ys;
- }
- /**
- * 服务端顺序( 左-右 上-下)
- */
- getIconItemByIndex(index: number) {
- let x = index % MouseConst.GAME_COLUMN;
- let y = MouseConst.GAME_ROW - 1 - Math.floor(index / MouseConst.GAME_COLUMN);
- return this._iconItemMap[x][y];
- }
- /**
- * 本地行列转服务端index
- */
- getServerIndex(col: number, row: number) {
- return (MouseConst.GAME_ROW - 1 - row) * MouseConst.GAME_COLUMN + col;
- }
- /**
- * 转动结果id
- */
- getTrueId(col: number, row: number) {
- return this._gameResult.itemInfo[this.getServerIndex(col, row)];
- }
- /**
- * 开始动效
- */
- playStartRunAnim() {
- cc.warn("====>playStartRunAnim");
- this.spinParticle.node.active = true;
- this.spinParticle.resetSystem();
- this.spinSplash.node.active = true;
- this.spinSplash.setAnimation(0, "animation", false);
- this.spinSplash.setCompleteListener(() => {
- this.spinSplash.setCompleteListener(null);
- this.spinSplash.node.active = false;
- this.spinParticle.node.active = false;
- });
- }
- /**
- * 预滚动(等后台数据)
- */
- onSpinPre() {
- cc.Tween.stopAllByTag(PREPARE_TWEEN_TAG);
- cc.Tween.stopAllByTag(SCROLL_TWEEN_TAG);
- this.nodeClick.active = false;
- // 滚动开始音效
- AudioPlayer.playEffect(MouseConst.Sound.spinRun, true, 1, false, (audioID: number) => {
- this._startRunAudioId = audioID;
- });
- // 开始动效
- this.playStartRunAnim();
- let __run = (iconItem: MouseIconItem, col: number, row: number) => {
- iconItem.node.active = true;
- let stepFirstTime = Math.abs(this.endPosY - this.startPosYArr[row]) / this.rollSpeed;
- // 开始
- let start = cc.tween().to(stepFirstTime, { y: this.endPosY }).call(() => { iconItem.node.y = this.topPosY; });
- // 循环
- let repeatRoll = cc.tween().repeat(Number.MAX_VALUE, cc.tween().to(this.oneRoundTime, { y: this.endPosY }).call(() => {
- iconItem.node.y = this.topPosY;
- }));
- // =============== End =====================
- cc.tween(iconItem.node).tag(PREPARE_TWEEN_TAG).then(start).then(repeatRoll).start();
- };
- this._iconItemMap.forEach((icons, col) => {
- icons.forEach((icon, row) => {
- __run(icon, col, row);
- });
- });
- }
- /**
- * 数据已就绪
- */
- onSpinReady(result: any, callback: Function, hasSuperSpin?: boolean) {
- this._callback = callback;
- this._gameResult = result;
- this.isStartSuper = hasSuperSpin;
- this.isSpinReady = true;
- cc.Tween.stopAllByTag(PREPARE_TWEEN_TAG);
- cc.Tween.stopAllByTag(SCROLL_TWEEN_TAG);
- this.nodeClick.active = true;
- this.resetAllIconItemPos();
- if (this._startRunAudioId == 0) {
- // 滚动开始音效
- AudioPlayer.playEffect(MouseConst.Sound.spinRun, true, 1, false, (audioID: number) => {
- this._startRunAudioId = audioID;
- });
- }
- if (this.gameFrameView.isSuperSpin) {
- this.playStartRunAnim();
- }
- this.runSpin(hasSuperSpin, this.gameFrameView.bottomView.isTurbo);
- }
- runSpin(hasSuperSpin?: boolean, isTurbo?: boolean) {
- let __run = (iconItem: MouseIconItem, col: number, row: number) => {
- iconItem.node.active = true;
- let rpeatCount = hasSuperSpin ? this.SUPER_ROLL_CIRCLES[col] : (isTurbo ? this.TURBO_ROLL_CIRCLES[col] : this.NORMAL_ROLL_CIRCLES[col]);
- let stepFirstTime = Math.abs(this.endPosY - this.startPosYArr[row]) / this.rollSpeed;
- let stepEndPosY = this.startPosYArr[row] + this.backOutHeight;
- let stepEndTime = Math.abs(stepEndPosY - this.topPosY) / this.rollSpeed;
- let easeKind = row >= MouseConst.GAME_ROW ? 'sineIn' : 'backOut';
- // =============== 转动的四个步骤 =====================
- // 开始
- let start = cc.tween().to(stepFirstTime, { y: this.endPosY }).call(() => { iconItem.node.y = this.topPosY; });
- // 循环
- let repeatRoll = cc.tween().repeat(rpeatCount, cc.tween().to(this.oneRoundTime, { y: this.endPosY }).call(() => {
- iconItem.node.y = this.topPosY;
- })).call(() => {
- if (row >= MouseConst.GAME_ROW) {
- // 屏幕外, 忽略
- } else {
- // 设置服务端下发的值
- let self = this
- iconItem.setItemInfo(self.getTrueId(col, row));
- // 同步到覆盖层
- self.mouseIconCover.syncItemInfo(col, row, iconItem.iconId);
- }
- });
- // 结束
- let end = cc.tween().to(stepEndTime, { y: stepEndPosY }).call(() => {
- if (row == 0) {
- //音效有延时, 提前播放
- this.playReelStopEffect(col);
- } else if (row >= MouseConst.GAME_ROW) {
- iconItem.node.active = false;
- }
- });
- // 回弹
- let back = cc.tween().to(this.backOutTime * this.backOutTimeMutiple, { y: this.startPosYArr[row] }, { easing: easeKind })
- .call(() => this.onReelStop(row, col));
- // =============== End =====================
- cc.tween(iconItem.node).tag(SCROLL_TWEEN_TAG).then(start).then(repeatRoll).then(end).then(back).start();
- };
- this._iconItemMap.forEach((icons, col) => {
- icons.forEach((icon, row) => {
- if (this.gameFrameView.isSuperSpin && col == 1) {
- // 超级转中间位置固定
- } else {
- __run(icon, col, row);
- }
- });
- });
- }
- stopSpin() {
- cc.warn("=============>stopSpin");
- cc.Tween.stopAllByTag(PREPARE_TWEEN_TAG);
- cc.Tween.stopAllByTag(SCROLL_TWEEN_TAG);
- for (let i = 0; i < MouseConst.GAME_COLUMN; i++) {
- this.playReelStopEffect(i);
- for (let j = 0; j < MouseConst.GAME_ROW + TopCount; j++) {
- let iconItem = this._iconItemMap[i][j];
- iconItem.node.y = MouseConst.IconSize.height * (j - 1);
- if (j >= MouseConst.GAME_ROW) {
- iconItem.node.active = false;
- } else {
- // 设置服务端下发的值
- iconItem.setItemInfo(this.getTrueId(i, j));
- // 同步到覆盖层
- this.mouseIconCover.syncItemInfo(i, j, iconItem.iconId);
- }
- }
- }
- this.onReelStop(MouseConst.GAME_ROW - 1, MouseConst.GAME_COLUMN - 1);
- }
- /**
- * 一列停止音效
- */
- playReelStopEffect(col: number) {
- if (this.gameFrameView.isSuperSpin) {
- if (col != 1) {
- AudioPlayer.playEffect(`sound/superReelStop${col + 1}`, false);
- }
- // 超级转中每列停止随机老鼠声音
- AudioPlayer.playEffect(`sound/mouse${MathUtils.makeRandomInt(9, 1)}`, false);
- // for (let i = 0; i < MouseConst.GAME_ROW; i++) {
- // let iconId = this.getTrueId(col, i);
- // if (iconId == MouseConst.CT_WILD) { // 有老鼠
- // AudioPlayer.playEffect(`sound/mouse${MathUtils.makeRandomInt(9, 1)}`, false);
- // return;
- // }
- // }
- } else {
- AudioPlayer.playEffect(`sound/reelStop${col + 1}`, false);
- }
- }
- // 滚轮停下来
- onReelStop(row: number, col: number) {
- if (row == MouseConst.GAME_ROW - 1 && col == MouseConst.GAME_COLUMN - 1) {
- cc.error("stop effect: " + this._startRunAudioId);
- AudioPlayer.stopEffect(this._startRunAudioId);
- this.nodeClick.active = false;
- this.scheduleOnce(() => this.onSpinOver(), 0.5);
- }
- }
- /**
- * 转动结束
- */
- onSpinOver() {
- // 如有wild, 先播放wild动画,再播放连线
- this.playWildParticle(() => {
- this.playShineArea();
- // 结束回调
- this._callback?.();
- });
- }
- /**
- * 播放所有wild粒子动画
- */
- playWildParticle(cb: Function) {
- // 超级转老鼠已经在房顶了
- if (this.gameFrameView.isSuperSpin || !this._gameResult.itemInfo.includes(MouseConst.CT_WILD)) {
- cb?.();
- return;
- }
- // Wild粒子音效
- AudioPlayer.playEffect(MouseConst.Sound.wildStart, false);
- this.mouseIconCover.node.active = true;
- let collectParticleStart = 0;
- let collectParticleEnd = 0;
- for (let i = 0; i < this._gameResult.itemInfo.length; i++) {
- let iconItem = this.mouseIconCover.getIconItemByIndex(i);
- if (iconItem.iconId == MouseConst.CT_WILD) {
- this.getIconItemByIndex(i).node.active = false;
- iconItem.playWildAnim();
- // 收集粒子动画
- let particleAnimNode = this.particleAnimNodeArr.getChildByName('pos_' + i);
- particleAnimNode.position = iconItem.node.position;
- particleAnimNode.active = true;
- particleAnimNode.getComponent(cc.ParticleSystem).resetSystem();
- collectParticleStart++;
- cc.tween(particleAnimNode)
- .bezierTo(0.6, cc.v2(particleAnimNode.x - 50, particleAnimNode.y + 30), cc.v2(particleAnimNode.x - 100, particleAnimNode.y), this.mouseAvatar.getBottomPos())
- .call(() => {
- particleAnimNode.active = false;
- collectParticleEnd++;
- if (collectParticleStart == collectParticleEnd) {
- // 粒子结束音效
- AudioPlayer.playEffect(MouseConst.Sound.wildEnd, false);
- this.mouseAvatar.playWildAnim();
- this.scheduleOnce(() => {
- cb?.();
- }, 0.5);
- }
- })
- .start();
- }
- }
- }
- /**
- * shine
- */
- playShineArea() {
- // let shineCount = this._gameResult?.shineArea?.length || 0;
- // if (shineCount == 0)
- // return;
- // 后台协议有变化
- let hasShine = (this._gameResult?.awardTotalTimes || 0) > 0;
- if (!hasShine)
- return;
- // 播放shine的时候就要隐藏中间三个老鼠
- if (this.gameFrameView.isSuperSpin) {
- this.mouseSuper.onExitSuper();
- this.mouseAvatar.onExitSuper();
- }
- // 中奖音效
- AudioPlayer.playEffect(MouseConst.Sound.win, false);
- // 老鼠音效
- for (let i = 0; i < this._gameResult.shineArea.length; i++) {
- if (this._gameResult.shineArea[i] && this._gameResult.itemInfo[i] == MouseConst.CT_WILD) {
- AudioPlayer.playEffect(`sound/winLineMouse${MouseConst.getRandomInt(1, 3)}`, false);
- break;
- }
- }
- this.mouseIconCover.playShineArea(this._gameResult);
- }
- // ====================== 超级转 =======================
- isVisibleIcon(row: number) {
- return row >= 0 && row <= MouseConst.GAME_ROW - 1;
- }
- /**
- * 触发超级转动画
- */
- playSuperAnim(cb: Function) {
- // 超级转触发音效
- AudioPlayer.playEffect(MouseConst.Sound.superPre, false);
- this.mouseDecor.onEnterSuper();
- // 老鼠摇晃
- this.mouseAvatar.playSuperAnim();
- // 窗口变小
- cc.tween(this.node).to(MouseConst.SUPER_ENTER_TIME, { scale: 0.85, y: this.node.y - this.SCALE_OFFSET }, { easing: 'sineIn' })
- .call(() => { cb?.(); }).start();
- }
- /**
- * 进入超级转
- */
- onEnterSuper() {
- this.mouseAvatar.onEnterSuper();
- this.scheduleOnce(() => {
- // 超级转音效(中间3个老鼠)
- AudioPlayer.playEffect(MouseConst.Sound.superStart, false);
- this.underlayNormal.active = false;
- this.underlaySuper.active = true;
- this.mouseSuper.onEnterSuper();
- }, 1); // 1s 以同步老鼠窜天的动作
- }
- /**
- * 退出超级转
- */
- onExitSuper(cb: Function) {
- this.scheduleOnce(() => {
- this.mouseDecor.onExitSuper();
- cc.tween(this.node).to(MouseConst.SUPER_EXIT_TIME, { scale: 1, y: this.node.y + this.SCALE_OFFSET })
- .call(() => {
- this.underlayNormal.active = true;
- this.underlaySuper.active = false;
- cb?.();
- })
- .start();
- }, 1);
- }
- onClickIconView() {
- if (!this.nodeClick.active)
- return;
- cc.warn("=============>onClickIconView");
- this.nodeClick.active = false;
- if (!this.gameFrameView.isGaming || this.gameFrameView.bottomView.isTurbo || !this.isSpinReady)
- return;
- if (this.isStartSuper || this.gameFrameView.isSuperSpin) {
- return;
- }
- this.stopSpin();
- }
- resetIcons() {
- for (let i = 0; i < MouseConst.GAME_COLUMN; i++) {
- for (let j = 0; j < MouseConst.GAME_ROW + TopCount; j++) {
- this._iconItemMap[i][j].node.active = true;
- }
- }
- }
- resetAllIconItemPos() {
- for (let i = 0; i < MouseConst.GAME_COLUMN; i++) {
- for (let j = 0; j < MouseConst.GAME_ROW + TopCount; j++) {
- this._iconItemMap[i][j].node.y = MouseConst.IconSize.height * (j - 1);
- }
- }
- }
- // =====================
- showIconDetail(iconId: number, col: number, row: number, target: cc.Node) {
- this.mouseIconDetail.show(this, iconId, col, row);
- }
- resetView() {
- cc.error("========== MouseIconView ResetView==========");
- this._callback = null;
- this._gameResult = null;
- this._startRunAudioId = 0;
- this.isStartSuper = false;
- this.isSpinReady = false;
- this.unscheduleAllCallbacks();
- this.nodeClick.active = false;
- this.mouseIconCover.resetView(); // IconCover会调用IconView的resetIcons
- this.mouseIconDetail.resetView();
- }
- }
|