import { GlobalEvent, ResType, SoundName, tMgr, WindowName } from "../Global"; import { getGlobalNode } from "../kernel/battle/BattleConst"; import GlobalNode from "../kernel/GlobalNode"; import { GameSceneObjTable, TableName } from "../kernel/table/TableDefine"; import { UIManager } from "../ui/UIManager"; import { SoundManager } from "./SoundManager"; export class SaveDataManager { private static _ins: SaveDataManager = null; static get ins(): SaveDataManager { if (this._ins == null) { this._ins = new SaveDataManager(); } return this._ins; } static DATA_VERSION = "1.0.1"; static PKG_NAME = 'com.BaiYing.Marbles'; runtimeData: RuntimeData_All = null; /**回到主场景后待添加的星星 */ mainSceneAddStar: number = 0; // private _saveTimeFrq: number = 5; // private _saveTimeCount: number = 0; // private _coinDirty: number = 0; devDay: number = 0; getNowTime(): number { if (CC_DEV) { return this.devDay * 3600000 * 24 + Date.now(); } else { return Date.now(); } } init(): void { this.resetData(); let userDataText = cc.sys.localStorage.getItem('USERDATA_PLAYERDATA' + '_' + SaveDataManager.PKG_NAME); if (userDataText == null || userDataText.length == 0) { console.log('[Data][本地没有数据,使用初始数据]'); this.saveData(); } else { let userData = JSON.parse(userDataText); if (userData.curDataVersion == SaveDataManager.DATA_VERSION) { this.runtimeData = this.getDataObj(this.runtimeData, userData); } else { console.log('[Data][数据版本不同,使用初始数据]'); this.saveData(); } // this.runtimeData = JSON.parse(userDataText); // console.log('[Data][读取结束]结果为:') // console.log(this.runtimeData); } // 重新计算每日任务 // this.Action_RefreshDailyMission(); // 保存数据 // this.saveData(); // DataManager.inited = true; // if (_finishCallback != null) { // _finishCallback(); // } // this._coinDirty = this.runtimeData.curCoin; cc.game.on(cc.game.EVENT_HIDE, this.onGameHideOrClose, this); } private onGameHideOrClose() { cc.log('game hide'); this.saveData(); } getDataObj(originalObj, newObj) { if (typeof (originalObj) == 'string') { return newObj; } let keys_runtimeData = Object.keys(originalObj) let keys_loaded = Object.keys(newObj); for (let i = 0; i < keys_runtimeData.length; i++) { let key = keys_runtimeData[i]; // if (key == 'unlockSkinList') { // log(); // } // 找到储存的数据一致的key,赋值给本地 for (let j = 0; j < keys_loaded.length; j++) { if (keys_loaded[j] == key) { if (originalObj[key] instanceof Array) { originalObj[key] = newObj[key]; } else { let tempKeys = Object.keys(originalObj[key]); if (tempKeys.length > 0) { originalObj[key] = this.getDataObj(originalObj[key], newObj[key]); } else { originalObj[key] = newObj[key]; } } break; } } } return originalObj; } resetData() { this.runtimeData = { curDataVersion: SaveDataManager.DATA_VERSION, star: 0, diamond: 0, curGameScene: 1, unlockObj: [], userSkillNum: { 1: 0, 2: 0, 3: 0, 4: 0 }, curLevel: 0, gender: -1, freeWheelNum: 3, loginRewardData: { step: 0, freshTime: 0, }, musicMute: false, SEMute: false, vibration: true, goldenAimEndTime: 0, goldenAimTry: false, ballSkinUnlocked: [4], ballSkinCurrent: 4, shopDailyPackRefreshTime: 0, ballSkinTry: 0, guideStep: 0, levelScoreMap: {} } } saveData() { // console.log("[Data][保存数据成功]") // console.log(DataManager.RuntimeData) cc.sys.localStorage.setItem('USERDATA_PLAYERDATA' + '_' + SaveDataManager.PKG_NAME, JSON.stringify(this.runtimeData)); // this._coinDirty = this.runtimeData.curCoin; } /** * * @param delta * @param useAni * @param wPos 星星动画的目标点,世界坐标,当useAni为true时且delta小于0时需要传入 * @returns 是否成功,当delta小于0时,会检测当前钱是否足够 */ adjustStar(delta: number, useAni: boolean = false, wPos?: cc.Vec3): boolean { if (delta < 0 && this.runtimeData.star < Math.abs(delta)) { return false; } if (useAni) { if (delta < 0) { UIManager.ins.widgetLayer.convertToNodeSpaceAR(wPos, wPos); //扣钱时使用传入的位置 } else { let widgetNode = UIManager.ins.getWidgetNode(ResType.STAR); wPos = cc.v3(widgetNode.position.x - widgetNode.width / 2, widgetNode.y, widgetNode.z); //加钱时使用widget位置 } getGlobalNode().getComponent(GlobalNode).schedule((dt) => { this.makeStar(wPos, delta / Math.abs(delta)); }, 0.1, Math.abs(delta) - 1, 0); } else { this.runtimeData.star += delta; this.saveData(); getGlobalNode().emit(GlobalEvent.CHANGE_EVENT_STAR, delta); } return true; } /** * * @param delta * @returns 是否成功,当delta小于0时,会检测当前钱是否足够 */ adjustDiamond(delta: number, useAni: boolean = false, wPos?: cc.Vec3): boolean { if (delta < 0 && this.runtimeData.diamond < Math.abs(delta)) { UIManager.ins.openWindow(WindowName.FREE_DIAMOND); return false; } if (useAni) { if (delta < 0) { UIManager.ins.widgetLayer.convertToNodeSpaceAR(wPos, wPos); //扣钱时使用传入的位置 } else { let widgetNode = UIManager.ins.getWidgetNode(ResType.DIAMOND); wPos = cc.v3(widgetNode.position.x - widgetNode.width / 2, widgetNode.y, widgetNode.z); //加钱时使用widget位置 } if (Math.abs(delta) < 5) { this.makeDiamond(wPos, delta); //小于5只播一次 } else { let step = Math.ceil(delta / 5); let lastStep = delta - step * 4; //console.log('step', step, 'last step', lastStep); getGlobalNode().getComponent(GlobalNode).schedule(() => { this.makeDiamond(wPos, step); }, 0.1, 3, 0); if (lastStep != 0) { getGlobalNode().getComponent(GlobalNode).scheduleOnce(() => { this.makeDiamond(wPos, lastStep); }, 0.5) } } // getGlobalNode().getComponent(GlobalNode).schedule((dt) => { // this.makeDiamond(wPos, delta / Math.abs(delta)); // }, 0.1, Math.abs(delta) - 1, 0); } else { this.runtimeData.diamond += delta; this.saveData(); getGlobalNode().emit(GlobalEvent.CHANGE_EVENT_DIAMOND, delta); } return true; } unlockGameSceneObj(ID: number) { if (!this.runtimeData.unlockObj.includes(ID)) { let config = tMgr.getConfig(TableName.GAME_SCENE_OBJ, ID) as GameSceneObjTable; if (config) { this.runtimeData.unlockObj.push(ID); getGlobalNode().emit(GlobalEvent.OBJ_UNLOCK, ID); SoundManager.ins.playEffect(SoundName.BUILD); } } } setUserSkillNumDelta(skillId: number, delta: number) { if (!this.runtimeData.userSkillNum[skillId]) { this.runtimeData.userSkillNum[skillId] = delta; } else { this.runtimeData.userSkillNum[skillId] += delta; } if (this.runtimeData.userSkillNum[skillId] < 0) { this.runtimeData.userSkillNum[skillId] = 0; } getGlobalNode().emit(GlobalEvent.SKILL_NUM_CHANGE, skillId); } getUserSkillNum(skillId: number): number { if (!this.runtimeData.userSkillNum[skillId]) { return 0; } else { return this.runtimeData.userSkillNum[skillId]; } } setMusicMute(value: boolean) { this.runtimeData.musicMute = value; this.saveData(); getGlobalNode().emit(GlobalEvent.SOUND_MUSIC_CONFIG_CHANGE, this.runtimeData.musicMute); } setSoundEffectMute(value: boolean) { this.runtimeData.SEMute = value; this.saveData(); getGlobalNode().emit(GlobalEvent.SOUND_EFFECT_CONFIG_CHANGE, this.runtimeData.SEMute); } unlockBallSkin(id: number) { if (!this.runtimeData.ballSkinUnlocked.includes(id)) { this.runtimeData.ballSkinUnlocked.push(id); this.saveData(); getGlobalNode().emit(GlobalEvent.BALL_SKIN_UNLOCK); } } useBallSkin(id: number) { if (id != SaveDataManager.ins.runtimeData.ballSkinCurrent) { SaveDataManager.ins.runtimeData.ballSkinCurrent = id; this.saveData(); getGlobalNode().emit(GlobalEvent.BALL_SKIN_USE); } } update(dt: number): void { // if (this._addStarNum > 0) { // this._addStarCount += dt; // if (this._addStarCount > 0.1) { // this._addStarCount = 0; // this.makeStar(); // } // } // this._saveTimeCount += dt; // if (this._saveTimeCount >= this._saveTimeFrq) { // this._saveTimeCount = 0; // if (this.runtimeData.curCoin != this._coinDirty) { //有脏数据时才保存 // // this._coinDirty = this.runtimeData.curCoin; // this.saveData(); // } // } } private makeStar(wPos: cc.Vec3, delta: number) { let node = new cc.Node(); let sp = node.addComponent(cc.Sprite); sp.spriteFrame = cc.resources.get('ui/general/UI_Title_star', cc.SpriteFrame); UIManager.ins.widgetLayer.addChild(node); if (delta < 0) { //如果扣钱,起点设在widget上 let widgetNode = UIManager.ins.getWidgetNode(ResType.STAR); node.setPosition(widgetNode.position.x - widgetNode.width / 2, widgetNode.y, widgetNode.z); } cc.tween(node).to(0.2, { position: wPos }, { easing: 'sineOut' }).call(() => { node.destroy(); this.adjustStar(delta, false); }).start(); SoundManager.ins.playEffect(SoundName.USE_STAR); } private makeDiamond(wPos: cc.Vec3, delta: number) { let node = new cc.Node(); let sp = node.addComponent(cc.Sprite); sp.spriteFrame = cc.resources.get('ui/general/UI_Title_diamond', cc.SpriteFrame); UIManager.ins.widgetLayer.addChild(node); if (delta < 0) { //如果扣钱,起点设在widget上 let widgetNode = UIManager.ins.getWidgetNode(ResType.DIAMOND); node.setPosition(widgetNode.position.x - widgetNode.width / 2, widgetNode.y, widgetNode.z); } else { SoundManager.ins.playEffect(SoundName.DIAMOND); } cc.tween(node).to(0.2, { position: wPos }, { easing: 'sineOut' }).call(() => { node.destroy(); this.adjustDiamond(delta, false); }).start(); } /**设置某一关的过关成绩(星星数) */ setLevelStarNum(level: number, star: number) { if (star < 0 || star > 3) { return; } if (this.runtimeData.levelScoreMap[level]) { //已有数据,只有在取得更好成绩时才更改 if (star > this.runtimeData.levelScoreMap[level]) { this.runtimeData.levelScoreMap[level] = star; getGlobalNode().emit(GlobalEvent.LEVEL_STAR_CHANGE, level); this.saveData(); } } else { this.runtimeData.levelScoreMap[level] = star; getGlobalNode().emit(GlobalEvent.LEVEL_STAR_CHANGE, level); this.saveData(); } } getLevelStarNum(levelId: number): number { if (this.runtimeData.levelScoreMap[levelId]) { return this.runtimeData.levelScoreMap[levelId]; } return 0; } } export interface RuntimeData_All { curDataVersion: string, star: number, diamond: number, curGameScene: number, /**已解锁物件ID */ unlockObj: number[], userSkillNum: object, /**当前已通关的关卡ID */ curLevel: number, gender: number, /**每日免费转盘次数 */ freeWheelNum: number, loginRewardData: { step: number, freshTime: number, }, /**音乐静音 */ musicMute: boolean, /**音效静音 */ SEMute: boolean, /**震动开关 */ vibration: boolean, goldenAimEndTime: number; goldenAimTry: boolean, ballSkinUnlocked: number[], ballSkinCurrent: number, /**试用皮肤 */ ballSkinTry: number, /**每日礼包刷新时间 */ shopDailyPackRefreshTime: number, /**新手引导进度 */ guideStep: number, levelScoreMap: object }