import { default as gameCfg, default as Gamecfg } from "../../../common/gameCfg"; import { gameMethod } from "../../../common/gameMethod"; import { xlsGuideInfo } from "../../../common/xlsConfig"; import auto_guideView from "../../../data/autoui/guide/auto_guideView"; import { GameEvent, GuideEvent, HomeEvent, MapEvent } from "../../../data/const/EventConst"; import { AudioConst, GuideType, HdBanBenFuLiCard, OpenType, TaskKind } from "../../../data/const/TypeConst"; import { ViewZOrder } from "../../../data/const/ViewZOrder"; import GameDataCenter from "../../../data/GameDataCenter"; import ResSpine from "../../../frameWork/compment/ResSpine"; import FguiMgr from "../../../frameWork/fgui/FguiMgr"; import EventMng from "../../../manager/EventMng"; import { I18n } from "../../../utils/I18nUtil"; import Load from "../../../utils/Load"; import { uiCommon } from "../../../utils/UICommon"; const { ccclass, property } = cc._decorator; @ccclass export default class UIGuideView extends cc.Component { @property(cc.SpriteFrame) taskzhezhao: cc.SpriteFrame = null @property(cc.SpriteFrame) btnzhezhao: cc.SpriteFrame = null @property(cc.SpriteFrame) fudi: cc.SpriteFrame = null @property(cc.SpriteFrame) jianghu: cc.SpriteFrame = null @property(cc.SpriteFrame) shilian: cc.SpriteFrame = null @property(cc.SpriteFrame) tongyong: cc.SpriteFrame = null @property(cc.SpriteFrame) tupo: cc.SpriteFrame = null @property(cc.SpriteFrame) xiuxing: cc.SpriteFrame = null @property(cc.SpriteFrame) zhaomu: cc.SpriteFrame = null @property(cc.SpriteFrame) zhenfa: cc.SpriteFrame = null @property(cc.SpriteFrame) guanbi: cc.SpriteFrame = null @property(cc.SpriteFrame) imgMask: cc.SpriteFrame = null @property(cc.SpriteFrame) shouling: cc.SpriteFrame = null @property(cc.Node) SkipPanel: cc.Node = null @property(cc.Node) SkipBtn: cc.Node = null; @property(cc.Node) SkipGuideAllBtn: cc.Node = null; ui: auto_guideView = null; private needUiName: string = "" //需要此UI才能继续引导 private guideUiName: string = "" //当前引导的UI private delayTime: number = -1 //guide延迟时间 private handTime: number = -1 //手势延迟时间 private fixTime: number = -1 //修正延迟时间 private fixCount: number = 0 //修正次数 private msgOffsetY: number = 0 //对话框偏移量 private targetNodeScale: number = 1 //目标节点真实sacle private finishTyping = false //打字完成 private event: GuideType = null //当前引导事件 private type: number = 1 //引导类型 callBack: Function; yType: number; startMoveHand: boolean = false; handWolrdPos: cc.Vec2; plotResSpine: ResSpine; isSkipPlot: boolean = false;//是否已经跳过剧情漫画 private canSkipPlot: boolean = false;//是否可以跳过漫画 skipCheckCount: number = 0;//检测点击次数跳过 protected onEnable() { this.ui = this.node.addComponent(auto_guideView); cc.game.addPersistRootNode(this.node) this.node.zIndex = ViewZOrder.Guide uiCommon.onRegisterEvent(this.ui.dialog, this.onClickDialog, this) uiCommon.onRegisterEvent(this.SkipBtn, this.onClickSkipPlot, this) uiCommon.onRegisterEvent(this.ui.plot, this.onClickPlot, this) uiCommon.onRegisterEvent(this.SkipGuideAllBtn, this.onClickSkipGuideAllBtn, this) EventMng.on(GuideEvent.GUIDE_EVENT, this.onGuideEvent, this) EventMng.on(GuideEvent.CLOSE_GUIDE, this.onClose, this) EventMng.on(GameEvent.ON_CLICK, this.checkOpen, this) EventMng.on(GuideEvent.UPDATE_TXTMSG, this.updateTxtMsg, this) EventMng.on(GuideEvent.HIDE_HAND, this.hideHand, this) this.ui.mask2.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); cc.tween(this.ui.imgQuan).repeatForever(cc.tween(this.ui.imgQuan).to(0.45, { scale: 1.2 }).to(0.45, { scale: 1 })).start() } protected onDisable() { uiCommon.unRegisterEvent(this.ui.dialog) uiCommon.unRegisterEvent(this.SkipBtn) EventMng.off(GuideEvent.GUIDE_EVENT, this.onGuideEvent, this) EventMng.off(GuideEvent.CLOSE_GUIDE, this.onClose, this) EventMng.off(GameEvent.ON_CLICK, this.checkOpen, this) EventMng.off(GuideEvent.UPDATE_TXTMSG, this.updateTxtMsg, this) EventMng.off(GuideEvent.HIDE_HAND, this.hideHand, this) this.ui.mask2.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); } private onTouchEnd(event: cc.Event.EventTouch) { if (!this.ui.imgHand.active || this.startMoveHand || gameMethod.isEmpty(this.handWolrdPos)) { return } this.skipCheckCount++; let lastPos: cc.Vec2 = cc.v2() lastPos.x = this.ui.imgHand.x lastPos.y = this.ui.imgHand.y let touchPos = event.getLocation(); cc.tween(this.ui.imgHand).stop() uiCommon.setWorldPos(this.ui.imgHand, touchPos) this.startMoveHand = true cc.tween(this.ui.imgHand).to(0.5, { x: lastPos.x, y: lastPos.y }).call(() => { uiCommon.setWorldPos(this.ui.imgHand, this.handWolrdPos) this.startMoveHand = false }).start() if (this.skipCheckCount >= 3 && GameDataCenter.guide.isFinishGuide() && this.event != GuideType.evt_guide_150) { this.SkipGuideAllBtn.active = true; } } checkOpen() { if (GameDataCenter.guide.isShowing) { let conf = Gamecfg.guideInfo.getItem(GameDataCenter.guide.guideId) if (conf?.ytype == 2) { GameDataCenter.guide.saveGuide(() => { EventMng.emit(GuideEvent.CLOSE_GUIDE) EventMng.emit(GuideEvent.GUIDE_EVENT, conf.event) }) } } } //监听剧情触发事件 onGuideEvent(event: GuideType, callBack?: Function) { //暂时先关闭所有引导 if (!GameDataCenter.guide.isOpenGuide) { return } this.event = event this.callBack = callBack let confDramaList = gameCfg.guideInfoList.getItemList(event) let isfinish: boolean = false for (const key in confDramaList) { const element = confDramaList[key]; //新手引导如果保存了步骤要过滤 if (!GameDataCenter.guide.checkIsSave(element.id) && GameDataCenter.guide.checkCanDrama(element.id)) { this.showGuide(element.id) EventMng.emit(HomeEvent.UP_HD_FLYBIRD); isfinish = true this.fixCount = 0;//重置修正次数 this.skipCheckCount = 0; this.SkipGuideAllBtn.active = false; break } } } onClickPlot() { if (!this.canSkipPlot) return; if (this.SkipPanel.active) { this.ShowPlotSkip(false); } else { this.ShowPlotSkip(true); } } onClickSkipPlot() { if (this.isSkipPlot) return; this.isSkipPlot = true; this.SkipPanel.active = false; if (!GameDataCenter.guide.isFinishGuide()) { GameDataCenter.guide.nextGuide(this.event) } cc.tween(this.ui.plot) .to(1, { opacity: 0 }) .delay(0.5) .call(() => { this.ui.plot.active = false this.plotResSpine.resetRes(); GameDataCenter.audio.playMusic(AudioConst.bgm_base) }).start(); } ShowPlotSkip(isShow: boolean) { cc.Tween.stopAllByTarget(this.SkipPanel); if (isShow) { this.SkipPanel.active = true; cc.tween(this.SkipPanel) .to(0.25, { y: this.SkipPanel.height }) .start(); } else { cc.tween(this.SkipPanel) .to(0.25, { y: 0 }) .call(() => { this.SkipPanel.active = false; }) .start(); } } showGuide(id: string) { if (GameDataCenter.guide.isShowing) { return } console.log("showGuide:" + id) GameDataCenter.guide.isShowing = true GameDataCenter.guide.guideId = id GameDataCenter.guide.guideIndex = 0 this.ui.gGuide.active = true let conf = gameCfg.guideInfo.getItem(GameDataCenter.guide.guideId) if (GameDataCenter.guide.isFinishGuide() && conf.event == GuideType.new) {//如果已完成了新手引导,但是仍然触发了新手引导的步骤,直接跳过 GameDataCenter.guide.saveGuideArray(GuideType.new, [GameDataCenter.guide.guideId], () => { }); return; } this.type = conf.type this.yType = conf.ytype if (this.type == 1) { if (!GameDataCenter.guide.isFinishGuide()) { GameDataCenter.guide.nextGuide(this.event) } } else if (this.type == 3) { //单纯对话框引导 this.ui.btnMask.active = false this.ui.dialog.active = true this.showDialog() } else if (this.type == 5) { //正常下一步引导 if (conf.way == "5") { GameDataCenter.guide.isShowing = true this.ui.gGuide.active = true this.ui.btnMask.active = true EventMng.emit(GuideEvent.GUIDE_SLOT, conf.pram[0]); } else { this.playGuide() } } else { //正常下一步引导 this.guideUiName = conf.pram[0][0]; this.playGuide() } } showDialog() { let conf = gameCfg.guideInfo.getItem(GameDataCenter.guide.guideId) let roleImgName = conf.pram[2] Load.loadTexture(this.ui.imgRole1, `guide/res/${roleImgName}`); uiCommon.setLabel(this.ui.txtName, I18n.getI18nLang(conf.pram[3])) if (conf.pram[0][GameDataCenter.guide.guideIndex] == null) { GameDataCenter.guide.saveGuide(() => { this.onClose() if (this.callBack) { //当前引导组结束回调 GameDataCenter.guide.isShowing = true this.ui.gGuide.active = true this.ui.btnMask.active = true this.callBack() this.callBack = null } else { this.onGuideEvent(this.event) } }) return } //播放配音 GameDataCenter.audio.stopAllEffects() //GameDataCenter.audio.playEffect(conf.pram?.[0]?.[GameDataCenter.guide.guideIndex]) uiCommon.typingAni(this.ui.txtDialog.getComponent(cc.RichText), I18n.getI18nLang(conf.pram?.[0]?.[GameDataCenter.guide.guideIndex]), 1 / 45, () => { this.finishTyping = true }) } onClickDialog() { if (this.finishTyping) { this.finishTyping = false GameDataCenter.guide.guideIndex++ this.showDialog() } else { this.finishTyping = true this.ui.txtDialog.getComponent(cc.RichText).unscheduleAllCallbacks() let conf = gameCfg.guideInfo.getItem(GameDataCenter.guide.guideId) uiCommon.setLabel(this.ui.txtDialog, I18n.getI18nLang(conf.pram?.[0]?.[GameDataCenter.guide.guideIndex])) GameDataCenter.audio.stopAllEffects() } } onClickSkipGuideAllBtn() { let confDramaList = gameCfg.guideInfoList.getItemList(this.event) let guideIds = []; confDramaList.forEach(element => { guideIds.push(element.id); }); GameDataCenter.guide.saveGuideArray(this.event, guideIds, () => { this.SkipGuideAllBtn.active = false; this.skipCheckCount = 0; this.onClose(); }) } playGuide() { if (this.delayTime >= 0) { return } let conf = gameCfg.guideInfo.getItem(GameDataCenter.guide.guideId) let guideInfo = conf.pram[GameDataCenter.guide.guideIndex] // console.log("guideInfo===", guideInfo) if (guideInfo != null) { switch (guideInfo[0]) { case "name": this.ui.btnMask.active = this.yType != 2 //弱引导,不开启遮罩 this.handTime = guideInfo[1] < 0 ? 0 : guideInfo[1] this.msgOffsetY = guideInfo[6] != null ? guideInfo[6] : 140 break default: this.ui.btnMask.active = this.yType != 2 //弱引导,不开启遮罩 this.needUiName = this.changeUiName(guideInfo[0], conf); this.delayTime = guideInfo[1] break } } else { GameDataCenter.guide.nextGuide(this.event) } } handCall(isFix: boolean = false) { if (isFix) { return } let conf = Gamecfg.guideInfo.getItem(GameDataCenter.guide.guideId) let guideInfo = conf.pram[GameDataCenter.guide.guideIndex] if (guideInfo == null || gameMethod.isEmpty(guideInfo[2])) { return } this.fixTime = 0.5 //每0.5s修正一次位置 this.ui.btnMask.active = false this.ui.mask.active = this.yType != 2 //弱引导,不开启遮罩 //这里需要查找节点的话,conf.pram[0][0]必须配置uiview let uiViewName = this.changeUiName(conf.pram[0][0], conf); let targetNode: cc.Node = FguiMgr.Instance.findNodeByName(uiViewName, guideInfo[2]); if (targetNode == null) { console.error(`找不到目标节点: ${guideInfo[2]}`) this.onClose(); return } let targetWolrdPos = uiCommon.getWorldPosCenter(targetNode) this.targetNodeScale = targetNode.scale let maskScale = 1 if (!gameMethod.isEmpty(guideInfo[7])) { maskScale = guideInfo[7] } this.getRealScale(targetNode) this.ui.mask.width = targetNode.width * this.targetNodeScale * maskScale this.ui.mask.height = targetNode.height * this.targetNodeScale * maskScale this.ui.mask.angle = targetNode.angle uiCommon.setWorldPos(this.ui.mask, targetWolrdPos) cc.Tween.stopAllByTarget(this.ui.imgHand) this.ui.imgHand.active = true//guideInfo[2] != "MaskBgBtn" //点击空白处关闭的,无需显示手指跟光圈 if (!gameMethod.isEmpty(guideInfo[3])) { targetWolrdPos.y -= parseInt(guideInfo[3]) } this.handWolrdPos = targetWolrdPos if (conf.type == 15 && !gameMethod.isEmpty(conf.pram?.[2]?.[2])) {//拖动类型的引导 let targetNode2: cc.Node = FguiMgr.Instance.findNodeByName(uiViewName, conf.pram[2][2]); if (targetNode2 == null) { console.error(`找不到目标节点: ${conf.pram[2][2]}`) this.onClose(); return } uiCommon.setWorldPos(this.ui.imgQuan, cc.v2(targetWolrdPos.x, targetWolrdPos.y)) uiCommon.setWorldPos(this.ui.imgHand, targetWolrdPos) this.ui.msgBg.active = !gameMethod.isEmpty(guideInfo[5]) this.ui.imgQuan.active = false; if (!gameMethod.isEmpty(conf.pram?.[GameDataCenter.guide.guideIndex]?.[5])) { uiCommon.setLabel(this.ui.txtMsg, I18n.getI18nLang(conf.pram?.[GameDataCenter.guide.guideIndex]?.[5])) } this.ui.msgBg.y = this.ui.imgQuan.y + this.msgOffsetY let msgBgX = this.ui.imgQuan.x if (this.ui.imgQuan.x < -155) { msgBgX = -155 } else if (this.ui.imgQuan.x > 155) { msgBgX = 155 } this.ui.msgBg.x = msgBgX let targetPos = uiCommon.transPos(targetNode2, this.ui.gGuide); cc.tween(this.ui.imgHand).repeatForever(cc.tween(this.ui.imgHand).to(0.5, { position: targetPos }).delay(0.3).call(() => { uiCommon.setWorldPos(this.ui.imgHand, targetWolrdPos) })).start() } else { uiCommon.setWorldPos(this.ui.imgHand, targetWolrdPos) this.guideHandEnd(guideInfo, conf, targetWolrdPos) } } guideHandEnd(guideInfo: any[], conf: xlsGuideInfo, targetWolrdPos: cc.Vec2) { this.ui.msgBg.active = !gameMethod.isEmpty(guideInfo[5]) this.ui.imgQuan.active = true//guideInfo[2] != "MaskBgBtn" //点击空白处关闭的,无需显示光圈 //播放配音 if (!gameMethod.isEmpty(conf.pram?.[GameDataCenter.guide.guideIndex]?.[5])) { uiCommon.setLabel(this.ui.txtMsg, I18n.getI18nLang(conf.pram?.[GameDataCenter.guide.guideIndex]?.[5])) GameDataCenter.audio.stopAllEffects() //GameDataCenter.audio.playEffect(conf.pram?.[GameDataCenter.guide.guideIndex]?.[5]) } uiCommon.setWorldPos(this.ui.imgQuan, cc.v2(targetWolrdPos.x, targetWolrdPos.y)) uiCommon.setWorldPos(this.ui.imgHand, cc.v2(targetWolrdPos.x, targetWolrdPos.y)) this.ui.msgBg.y = this.ui.imgQuan.y + this.msgOffsetY let msgBgX = this.ui.imgQuan.x if (this.ui.imgQuan.x < -155) { msgBgX = -155 } else if (this.ui.imgQuan.x > 155) { msgBgX = 155 } this.ui.msgBg.x = msgBgX } updateTxtMsg(txt: string) { uiCommon.setLabel(this.ui.txtMsg, txt) } //获取目标节点真实sacle getRealScale(root: cc.Node) { if (root.parent != null) { this.targetNodeScale *= root.parent.scale this.getRealScale(root.parent) } } update(dt: number) { if (this.delayTime >= 0) { this.ui.btnMask.active = this.yType != 2 //弱引导,不开启遮罩 if (this.needUiName.length > 0) { if (FguiMgr.Instance.isShowingByName(this.needUiName) && FguiMgr.Instance.getShowingViewByName(this.needUiName)?.isFinishOpenAni) { this.delayTime -= dt if (this.delayTime < 0) { this.ui.btnMask.active = false this.needUiName = "" if (this.type == 1) { this.ui.dialog.active = true this.showDialog() } else { GameDataCenter.guide.guideIndex++ this.playGuide() } } } } else { this.delayTime -= dt if (this.delayTime < 0) { this.ui.btnMask.active = false if (this.type == 1) { this.ui.dialog.active = true this.showDialog() } else { this.playGuide() } } } } //手势引导延迟 if (this.handTime >= 0) { if (FguiMgr.Instance.isShowingByName(this.guideUiName)) { this.handTime -= dt if (this.handTime < 0) { this.handCall() } } } //修正位置 if (this.fixTime >= 0) { if (FguiMgr.Instance.isShowingByName(this.guideUiName)) { this.fixTime -= dt if (this.fixTime < 0) { this.handCall(true) } } } } changeUiName(uiName: string, conf: xlsGuideInfo) { return uiName; } hideHand() { this.ui.imgQuan.active = false this.ui.imgHand.active = false } onClose() { GameDataCenter.guide.init() this.ui.gGuide.active = false this.ui.dialog.active = false this.ui.mask.active = false this.ui.msgBg.active = false this.ui.imgQuan.active = false this.ui.imgHand.active = false this.needUiName = "" this.guideUiName = "" this.delayTime = -1 this.handTime = -1 this.fixTime = -1 this.targetNodeScale = 1 } }