├── assets └── scripts │ └── core │ ├── AStar │ ├── AStarMoveType.js │ ├── AStarStep.js │ └── AStar.js │ ├── UI │ ├── Qmessage.js │ ├── AvatarItem.js │ ├── SaveItem.js │ ├── MessageBox.js │ ├── SliderBar.js │ ├── SystemWindow.js │ ├── ShopItem.js │ ├── GroupList.js │ ├── ItemMsg.js │ ├── OptionBox.js │ ├── BagItem.js │ ├── ConfirmBox.js │ ├── Slider.js │ ├── GameMenu.js │ ├── DialogueBox.js │ ├── BagSystem.js │ ├── SaveSystem.js │ └── Shop.js │ ├── system │ ├── Mainbutton.js │ ├── MapAnimation.js │ ├── MainMenu.js │ ├── Camera.js │ ├── EmotionFX.js │ ├── ActionParse.js │ ├── Global.js │ ├── Cache.js │ ├── AudioManager.js │ ├── Scene.js │ ├── Treasure.js │ ├── EventManager.js │ ├── GameEvent.js │ ├── TouchControl.js │ ├── WindowManager.js │ ├── PlayerData.js │ ├── Game.js │ ├── Map.js │ └── EventHandle.js │ └── Stealth │ └── Stealth.js ├── README.md └── .gitignore /assets/scripts/core/AStar/AStarMoveType.js: -------------------------------------------------------------------------------- 1 | var AStarMoveType = cc.Enum({ 2 | FOUR_DIRECTION: -1, 3 | EIGHT_DIRECTION: -1 4 | }); 5 | 6 | module.exports = AStarMoveType; -------------------------------------------------------------------------------- /assets/scripts/core/UI/Qmessage.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | messageLabel: cc.RichText, 6 | animation: cc.Animation 7 | }, 8 | 9 | // use this for initialization 10 | onLoad: function() { 11 | 12 | }, 13 | 14 | onEnable: function() { 15 | this.animation.play("Qmessage"); 16 | }, 17 | 18 | close: function() { 19 | this.node.destroy(); 20 | }, 21 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RPGMakerFP 2 | 3 | 使用Cocos Creator开发的类似于RPG Maker的日式RPG游戏的基础系统。 4 | 5 | 目前已完成剧情流程相关的大部分内容。如:角色移动、对话、商店、背包、地图切换、事件触发等等。 6 | 7 | 项目包含系统的核心代码,使用方法请移步[Wiki](https://github.com/neveis/RPGMakerFP/wiki) 8 | 9 | 注:代码里的A*算法根据[luckytianyiyan](https://github.com/luckytianyiyan)写的修改而来。[A-Star](https://github.com/luckytianyiyan/A-star/) 10 | 11 | 更新一下... 12 | 13 | 过去一段时间以及未来的一段时间都很多事情做,真的是很少时间来写这个了,虽然本来也就是写着来玩玩的。 14 | 15 | 不过既然写了,有时候还是想着怎么去更完善一点(虽然并没有什么用)。而且好多地方的设计好烂啊(没脸看,扶额),已经写好的部分如果没什么大问题暂时是懒得去改了。 16 | 17 | 近期大概会找点素材做个简单的例子吧(文档都没去更了ORZ)。机械城那个工程发出来不太合适,虽然现在都是在这个基础上开发。 18 | 19 | 然后也琢磨着想弄个战斗系统,尽管肯定是很简单的(复杂的也做不来啊),不过就算再简单还是想做个出来吧。 20 | 21 | 就这样吧。 -------------------------------------------------------------------------------- /assets/scripts/core/UI/AvatarItem.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | avatarSprite: cc.Sprite, 6 | _handle: null 7 | }, 8 | 9 | 10 | onLoad: function() { 11 | this.gameNode = cc.find("Game"); 12 | this.game = this.gameNode.getComponent('Game'); 13 | 14 | }, 15 | 16 | create: function(actorId, spriteFrame) { 17 | this.actorId = actorId; 18 | this.avatarSprite.spriteFrame = spriteFrame; 19 | }, 20 | 21 | switchPlayer: function() { 22 | let oldId = this.game.playerId; 23 | this.game.switchPlayer(this.actorId, null); 24 | this._handle.updateList(oldId); 25 | } 26 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Mainbutton.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | gameNode: { 6 | default: null, 7 | type: cc.Node 8 | }, 9 | }, 10 | 11 | // use this for initialization 12 | onLoad: function() { 13 | this.gameNode = this.gameNode || cc.find('Game') 14 | this.game = this.gameNode.getComponent("Game"); 15 | this.eventManager = this.gameNode.getComponent("EventManager"); 16 | this.node.on(cc.Node.EventType.TOUCH_START, function(event) { 17 | cc.log("mainbutton pressed"); 18 | //先检测事件,前方有事件则不执行攻击 19 | this.game.player.checkEventThere(); 20 | /* 21 | //攻击的地图,并且前方无事件时,执行攻击 22 | if (this.game.map.battle) { 23 | this.game.player.attack(); 24 | } 25 | */ 26 | }, this); 27 | }, 28 | 29 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/MapAnimation.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: {}, 5 | 6 | /** 7 | * 用于动画结束后的回调 8 | */ 9 | callFunc: function(func) { 10 | func(); 11 | }, 12 | 13 | //动画中需要调用的事件 14 | mechanicalBird: function() { 15 | var gameNode = cc.find("Game"); 16 | var actorManager = gameNode.getComponent("ActorManager"); 17 | var idList = [1, 12, 13, 14, 15, 22]; 18 | var target; 19 | for (var i = 0; i < idList.length; i++) { 20 | target = actorManager.getTarget(idList[i]); 21 | if (target == null) continue; 22 | target.showBalloon("surprise", false, false); 23 | } 24 | }, 25 | 26 | birdAttackedEffect: function() { 27 | var myParticle = cc.find("MechanicalBird/Bird/BirdAttackedEffect", this.node).getComponent(cc.ParticleSystem); 28 | myParticle.resetSystem(); // restart particle system 29 | } 30 | }); -------------------------------------------------------------------------------- /assets/scripts/core/AStar/AStarStep.js: -------------------------------------------------------------------------------- 1 | var AStarStep = cc.Class({ 2 | properties: () => ({ 3 | g: { 4 | default: 0, 5 | type: cc.Integer 6 | }, 7 | h: { 8 | default: 0, 9 | type: cc.Integer 10 | }, 11 | f: { 12 | get: function() { 13 | return this.g + this.h; 14 | } 15 | }, 16 | position: { 17 | default: new cc.Vec2() 18 | }, 19 | parent: { 20 | default: null, 21 | type: AStarStep, 22 | serializable: false 23 | } 24 | }), 25 | 26 | ctor: function () { 27 | if (arguments.length > 0 && arguments[0] instanceof cc.Vec2) { 28 | this.position = arguments[0]; 29 | } 30 | }, 31 | 32 | equalTo(other) { 33 | if (other instanceof AStarStep) { 34 | return this.position.equals(other.position); 35 | } 36 | return false; 37 | }, 38 | 39 | toString: function () { 40 | return '(' + 'position: ' + this.position + ' g: ' + this.g + ' h: ' + this.h + ' f: ' + this.f + ')'; 41 | } 42 | 43 | }); 44 | 45 | module.exports = AStarStep; -------------------------------------------------------------------------------- /assets/scripts/core/system/MainMenu.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | saveWin: cc.Prefab 6 | }, 7 | 8 | // use this for initialization 9 | onLoad: function() { 10 | this.gameNode = cc.find("Game"); 11 | this.game = this.gameNode.getComponent("Game"); 12 | this.windowManager = this.gameNode.getComponent("WindowManager"); 13 | }, 14 | 15 | showSaveWin: function() { 16 | this.windowManager.showSaveWindow(); 17 | }, 18 | 19 | startGame: function() { 20 | //cc.director.loadScene("Opening"); 21 | //淡出,需要自行编写事件淡入,或注释不使用 22 | //this.windowManager.fadeInOrOut(false, 1, null); 23 | this.scheduleOnce(function() { 24 | //this.game.switchScene("1", 1, cc.p(384, 256), 6, true); 25 | //this.game.switchScene("2", 1, cc.p(640, 288), 2, true); 26 | //this.game.switchScene("3", 1, cc.p(1536, 288), 4, true); 27 | //this.game.switchScene("4", 1, cc.p(736, 0), 8, true); 28 | this.game.switchScene("100", 1, cc.p(768, 0), 8, true); 29 | }, 0.5); 30 | }, 31 | 32 | exitGame: function() { 33 | //cc.sys.localStorage.clear(); 34 | } 35 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/SaveItem.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | saveSystem: null, 6 | index: 0, 7 | itemName: "", 8 | info: "", 9 | nameLabel: cc.Label, 10 | normal: cc.SpriteFrame, 11 | pressed: cc.SpriteFrame 12 | }, 13 | 14 | // use this for initialization 15 | onLoad: function() { 16 | this.nameLabel.string = this.itemName; 17 | 18 | this.node.on(cc.Node.EventType.TOUCH_START, function(event) { 19 | this.setPressed(); 20 | }, this); 21 | 22 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 23 | this.isSelected(); 24 | }, this); 25 | 26 | this.node.on(cc.Node.EventType.TOUCH_CANCEL, function(event) { 27 | this.setNormal(); 28 | }, this); 29 | }, 30 | 31 | isSelected: function() { 32 | this.setPressed(); 33 | this.saveSystem.selectSaveItem(this, this.index, this.info); 34 | }, 35 | 36 | setNormal: function() { 37 | this.getComponent(cc.Sprite).spriteFrame = this.normal; 38 | }, 39 | 40 | setPressed: function() { 41 | this.getComponent(cc.Sprite).spriteFrame = this.pressed; 42 | } 43 | 44 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Camera.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | horizontalOffset: 0, 6 | verticalOffset: 0, 7 | }, 8 | 9 | onLoad: function() { 10 | //offset补偿人物锚点与画面中心的距离 11 | 12 | this.gameNode = cc.find('Game'); 13 | this.game = this.gameNode.getComponent("Game"); 14 | this.scene = cc.find('Canvas').getComponent("Scene"); 15 | this.boundingBox = cc.rect(0, 0, this.node.windth, this.node.height); 16 | 17 | var halfWidth = cc.visibleRect.width / 2; 18 | var halfHeight = cc.visibleRect.height / 2; 19 | this.minX = -(this.node.width - halfWidth); 20 | this.maxX = -halfWidth; 21 | this.minY = -(this.node.height - halfHeight); 22 | this.maxY = -halfHeight; 23 | this.prePos = { x: 0, y: 0 }; 24 | }, 25 | 26 | lateUpdate: function(dt) { 27 | if (!this.game.cameraFollowFlag) return; 28 | var target = this.scene.getActorTarget(this.game.playerId); 29 | var pos = target.getPos(); 30 | 31 | pos.x = cc.clampf(-(pos.x + this.horizontalOffset), this.minX, this.maxX); 32 | pos.y = cc.clampf(-(pos.y + this.verticalOffset), this.minY, this.maxY); 33 | 34 | this.node.setPosition(pos); 35 | }, 36 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/MessageBox.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | cc.Class({ 5 | extends: cc.Component, 6 | 7 | properties: { 8 | gameNode: { 9 | default: null, 10 | type: cc.Node 11 | }, 12 | messageLabel: { 13 | default: null, 14 | type: cc.Label 15 | }, 16 | poolMng: null 17 | }, 18 | onEnable: function() { 19 | this.node.on('touchstart', emptyFunc, this); 20 | }, 21 | // use this for initialization 22 | onLoad: function() { 23 | this.game = this.gameNode.getComponent("Game"); 24 | 25 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 26 | this.hide(); 27 | }, this) 28 | }, 29 | 30 | showMessage: function(message, cb) { 31 | this.game.hideUI(['default'], true, false); 32 | this.messageLabel.string = message; 33 | this.cb = cb 34 | }, 35 | 36 | hide: function() { 37 | this.poolMng.put(this.node); 38 | this.game.hideUI(['default'], false, false); 39 | if (this.cb) this.cb.next(); 40 | }, 41 | 42 | onDisable: function() { 43 | this.node.off('touchstart', emptyFunc, this); 44 | }, 45 | // called every frame, uncomment this function to activate update callback 46 | // update: function (dt) { 47 | 48 | // }, 49 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/EmotionFX.js: -------------------------------------------------------------------------------- 1 | var EmotionName = ["surprised", "doubt", "joyful", "like", "angry", "ashamed", "tangle", "silent", "inspired", "sleep"]; 2 | 3 | cc.Class({ 4 | extends: cc.Component, 5 | properties: {}, 6 | 7 | createAnimationClip: function() { 8 | var gameNode = cc.find("Game"); 9 | var cache = gameNode.getComponent('Cache'); 10 | var emotionAtlas = cache.getEmotionAtlas(); 11 | if (!emotionAtlas) return; 12 | 13 | var animation = this.node.getComponent(cc.Animation); 14 | var frame; 15 | //十种表情 16 | for (var i = 0; i < 10; i++) { 17 | frame = []; 18 | //8张图组成 19 | for (var j = 0; j < 8; j++) { 20 | var index = i * 8 + j + 1; 21 | if (index < 10) { 22 | var spriteTag = "Emotion_0" + index; 23 | } else { 24 | var spriteTag = "Emotion_" + index; 25 | } 26 | frame.push(emotionAtlas.getSpriteFrame(spriteTag)); 27 | } 28 | var clip = cc.AnimationClip.createWithSpriteFrames(frame, 6); 29 | clip.events = [{ frame: clip.duration, func: 'onAnimationCompleted', params: [] }]; 30 | animation.addClip(clip, EmotionName[i]); 31 | } 32 | }, 33 | onAnimationCompleted: function() { 34 | this.node.opacity = 0; 35 | } 36 | 37 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/SliderBar.js: -------------------------------------------------------------------------------- 1 | var Direction = cc.Enum({ 2 | Horizontal: 1, 3 | Vertical: 2 4 | }) 5 | 6 | cc.Class({ 7 | extends: cc.Component, 8 | 9 | properties: () => ({ 10 | handle: null, 11 | eventTag: "c_slider", 12 | direction: { 13 | default: Direction.Horizontal, 14 | type: Direction 15 | }, 16 | slider: { 17 | default: null, 18 | type: require("Slider") 19 | }, 20 | }), 21 | 22 | // use this for initialization 23 | onLoad: function() { 24 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 25 | var newPos = this.node.convertToNodeSpaceAR(event.getLocation()); 26 | cc.log(this.node.convertToNodeSpaceAR(event.getLocation())); 27 | switch (this.direction) { 28 | case Direction.Horizontal: 29 | this.slider.node.x = newPos.x 30 | break; 31 | case Direction.Vertical: 32 | this.slider.node.y = newPos.y 33 | break; 34 | } 35 | this.sendRatio(this.slider.getRatio()); 36 | }, this); 37 | }, 38 | 39 | sendRatio: function(ratio) { 40 | if (this.handle == null) return; 41 | 42 | this.handle.emit(this.eventTag, { 43 | ratio: ratio 44 | }); 45 | }, 46 | 47 | addListener: function(handle) { 48 | this.handle = handle; 49 | }, 50 | 51 | removeListener: function() { 52 | this.handle = null; 53 | } 54 | 55 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/SystemWindow.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | 5 | cc.Class({ 6 | extends: cc.Component, 7 | 8 | properties: { 9 | BGMNode: cc.Node, 10 | SENode: cc.Node, 11 | _poolMng: null 12 | }, 13 | 14 | // use this for initialization 15 | onLoad: function() { 16 | this.gameNode = this.gameNode || cc.find('Game'); 17 | this.game = this.gameNode.getComponent("Game"); 18 | this.audioManager = this.gameNode.getComponent("AudioManager"); 19 | this.BGMSliderBar = this.BGMNode.getComponent("SliderBar"); 20 | this.SESliderBar = this.SENode.getComponent("SliderBar"); 21 | this.BGMSliderBar.addListener(this.node); 22 | this.SESliderBar.addListener(this.node); 23 | 24 | this.node.on("c_bgm_slider", function(event) { 25 | this.audioManager.setMusicVolume(event.detail.ratio); 26 | }, this); 27 | this.node.on("c_se_slider", function(event) { 28 | this.audioManager.setEffectVolume(event.detail.ratio); 29 | }, this) 30 | }, 31 | 32 | start: function() { 33 | this.BGMSliderBar.slider.setPos(this.audioManager.getMusicVolume()); 34 | this.SESliderBar.slider.setPos(this.audioManager.getEffectVolume()); 35 | }, 36 | 37 | onEnable: function() { 38 | this.node.on('touchstart', emptyFunc, this); 39 | }, 40 | 41 | close: function() { 42 | this._poolMng.put(this.node); 43 | }, 44 | 45 | onDisable: function() { 46 | this.node.off('touchstart', emptyFunc, this); 47 | }, 48 | 49 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/ShopItem.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | id: 0, 6 | icon: { 7 | default: null, 8 | type: cc.Sprite 9 | }, 10 | itemName: { 11 | default: null, 12 | type: cc.Label 13 | }, 14 | price: { 15 | default: null, 16 | type: cc.Label 17 | }, 18 | //discription: "", 19 | //模拟按钮的图片 20 | normal: { 21 | default: null, 22 | type: cc.SpriteFrame 23 | }, 24 | pressed: { 25 | default: null, 26 | type: cc.SpriteFrame 27 | }, 28 | }, 29 | 30 | // use this for initialization 31 | onLoad: function() { 32 | //this.itemInfo = {}; 33 | this.node.on(cc.Node.EventType.TOUCH_START, function(event) { 34 | this.shop.node.emit("itemEvent", { 35 | self: this, 36 | state: 1, 37 | }); 38 | }, this); 39 | 40 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 41 | this.shop.node.emit("itemEvent", { 42 | self: this, 43 | state: 2, 44 | }); 45 | 46 | }, this); 47 | 48 | this.node.on(cc.Node.EventType.TOUCH_CANCEL, function(event) { 49 | this.shop.node.emit("itemEvent", { 50 | self: this, 51 | state: 3, 52 | }); 53 | 54 | }, this); 55 | }, 56 | 57 | setPressed: function() { 58 | this.node.getComponent(cc.Sprite).spriteFrame = this.pressed; 59 | }, 60 | 61 | setNormal: function() { 62 | this.node.getComponent(cc.Sprite).spriteFrame = this.normal; 63 | }, 64 | // called every frame, uncomment this function to activate update callback 65 | // update: function (dt) { 66 | 67 | // }, 68 | }); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #///////////////////////////////////////////////////////////////////////////// 2 | # Fireball Projects 3 | #///////////////////////////////////////////////////////////////////////////// 4 | 5 | library/ 6 | temp/ 7 | local/ 8 | build/ 9 | settings/ 10 | 11 | #///////////////////////////////////////////////////////////////////////////// 12 | # Logs and databases 13 | #///////////////////////////////////////////////////////////////////////////// 14 | 15 | *.log 16 | *.sql 17 | *.sqlite 18 | 19 | #///////////////////////////////////////////////////////////////////////////// 20 | # files for debugger 21 | #///////////////////////////////////////////////////////////////////////////// 22 | 23 | *.sln 24 | *.csproj 25 | *.pidb 26 | *.unityproj 27 | *.suo 28 | 29 | #///////////////////////////////////////////////////////////////////////////// 30 | # OS generated files 31 | #///////////////////////////////////////////////////////////////////////////// 32 | 33 | .DS_Store 34 | ehthumbs.db 35 | Thumbs.db 36 | 37 | #///////////////////////////////////////////////////////////////////////////// 38 | # exvim files 39 | #///////////////////////////////////////////////////////////////////////////// 40 | 41 | *UnityVS.meta 42 | *.err 43 | *.err.meta 44 | *.exvim 45 | *.exvim.meta 46 | *.vimentry 47 | *.vimentry.meta 48 | *.vimproject 49 | *.vimproject.meta 50 | .vimfiles.*/ 51 | .exvim.*/ 52 | quick_gen_project_*_autogen.bat 53 | quick_gen_project_*_autogen.bat.meta 54 | quick_gen_project_*_autogen.sh 55 | quick_gen_project_*_autogen.sh.meta 56 | .exvim.app 57 | 58 | #///////////////////////////////////////////////////////////////////////////// 59 | # webstorm files 60 | #///////////////////////////////////////////////////////////////////////////// 61 | 62 | .idea/ 63 | 64 | #///////////////////////////////////////////////////////////////////////////// 65 | # project 66 | #///////////////////////////////////////////////////////////////////////////// 67 | assets/res/* 68 | assets/resources/* 69 | assets/scenes/* 70 | *.meta 71 | creator.d.ts 72 | jsconfig.json 73 | project.json -------------------------------------------------------------------------------- /assets/scripts/core/UI/GroupList.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | avatarItemPrefab: cc.Prefab 6 | }, 7 | 8 | 9 | onLoad: function() { 10 | 11 | }, 12 | 13 | init: function() { 14 | this.gameNode = cc.find("Game"); 15 | this.game = this.gameNode.getComponent('Game'); 16 | this.cache = this.gameNode.getComponent('Cache'); 17 | this.nodePool = new cc.NodePool(); 18 | this.avatarList = []; 19 | }, 20 | 21 | initList: function() { 22 | //清除已有角色头像 23 | for (let i = 0; i < this.avatarList.length; i++) { 24 | this.nodePool.put(this.avatarList[i].node) 25 | } 26 | this.avatarList = []; 27 | let playerList = this.game.scene.map.playerList; 28 | for (let i = 0; i < playerList.length; i++) { 29 | if (playerList[i] == this.game.playerId) continue; 30 | let node; 31 | if (this.nodePool.size()) { 32 | node = this.nodePool.get(); 33 | } else { 34 | node = cc.instantiate(this.avatarItemPrefab); 35 | } 36 | let comp = node.getComponent('AvatarItem'); 37 | comp._handle = this; 38 | let spriteFrame = this.cache.getAvatar(playerList[i]); 39 | //如果没有头像,则取右朝向站立图 40 | if (!spriteFrame) { 41 | spriteFrame = this.game.scene.getActorTarget(playerList[i]).actorAtlas.getSpriteFrame("08"); 42 | } 43 | comp.create(playerList[i], spriteFrame); 44 | this.node.addChild(node); 45 | this.avatarList.push(comp); 46 | } 47 | 48 | }, 49 | 50 | updateList: function(newId) { 51 | for (let i = 0; i < this.avatarList.length; i++) { 52 | if (this.avatarList[i].actorId != this.game.playerId) continue; 53 | let spriteFrame = this.cache.getAvatar(newId); 54 | //如果没有头像,则取右朝向站立图 55 | if (!spriteFrame) { 56 | spriteFrame = this.game.scene.getActorTarget(newId).actorAtlas.getSpriteFrame("08"); 57 | } 58 | this.avatarList[i].create(newId, spriteFrame); 59 | break; 60 | } 61 | } 62 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/ActionParse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 分析动作配置数组,返回动作 3 | * 配置数组[actionType,actionName,arg [,easeAction]]。对于容器动作,可以在arg中嵌套。 4 | * @param {Array} data 5 | * {Number} actionType 动作类型:0 容器动作,1 及时动作,2 间隔动作,3 缓动动作 6 | * {String} actionName cc中对应的动作函数名称 7 | * {Array} arg 动作所需的参数,按函数参数顺序 8 | * {Array} easeAction 缓动动作,只能用于间隔动作。 9 | * return cc.Action 10 | */ 11 | var ActionParse = function(data) { 12 | var actionType = data[0]; 13 | var actionName = data[1]; 14 | var arg = data[2]; 15 | var easeAction = data[3]; 16 | var action; 17 | switch (actionType) { 18 | //容器动作 19 | case 0: 20 | //容器动作分为3类 21 | switch (actionName) { 22 | //参数为数组 23 | case 'sequence': 24 | case 'spawn': 25 | var list = []; 26 | for (var i = 0; i < arg.length; i++) { 27 | list[i] = ActionParse(arg[i]); 28 | } 29 | action = cc[actionName](list); 30 | break; 31 | //参数为动作和次数/速率 32 | case 'repeat': 33 | case 'speed': 34 | action = cc[actionName](ActionParse(arg[0]), arg[1]); 35 | break; 36 | //参数为动作 37 | case 'repeatForever': 38 | action = cc[actionName](ActionParse(arg[0])); 39 | break; 40 | } 41 | break; 42 | //即时动作 43 | case 1: 44 | action = cc[actionName](arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); 45 | break; 46 | //间隔动作 47 | case 2: 48 | action = cc[actionName](arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); 49 | //间隔动作还需要判断是否有缓动 50 | if (easeAction != null) { 51 | var easing = ActionParse(easeAction); 52 | action = action.easing(easing); 53 | } 54 | break; 55 | //缓动动作 56 | case 3: 57 | action = cc[actionName](arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); 58 | break; 59 | } 60 | 61 | return action; 62 | }; 63 | 64 | module.exports = ActionParse; -------------------------------------------------------------------------------- /assets/scripts/core/UI/ItemMsg.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | cc.Class({ 5 | extends: cc.Component, 6 | 7 | properties: { 8 | gain: { 9 | default: null, 10 | type: cc.Label 11 | }, 12 | icon: { 13 | default: null, 14 | type: cc.Sprite 15 | }, 16 | nameLabel: { 17 | default: null, 18 | type: cc.Label 19 | }, 20 | countLabel: { 21 | default: null, 22 | type: cc.Label 23 | }, 24 | gameNode: { 25 | default: null, 26 | type: cc.Node 27 | }, 28 | poolMng: null 29 | }, 30 | onEnable: function() { 31 | this.node.on('touchstart', emptyFunc, this); 32 | }, 33 | // use this for initialization 34 | onLoad: function() { 35 | this.game = this.gameNode.getComponent("Game"); 36 | this.cache = this.game.getComponent('Cache'); 37 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 38 | this.hide(); 39 | }, this) 40 | }, 41 | onDisable: function() { 42 | this.node.off('touchstart', emptyFunc, this); 43 | }, 44 | 45 | showItemMsg: function(type, itemId, count, cb) { 46 | let itemName, 47 | itemInfo, 48 | itemIcon, 49 | countStr; 50 | this.game.hideUI(['default'], true, false); 51 | switch (type) { 52 | case 0: 53 | itemName = '金钱'; 54 | countStr = Math.abs(count) + " G"; //金钱数量 55 | break; 56 | case 1: 57 | itemInfo = this.cache.getItemInfo(itemId); 58 | itemName = itemInfo.name; 59 | itemIcon = this.cache.getItemSprite(itemId); 60 | countStr = "X " + Math.abs(count); //物品数量 61 | break; 62 | } 63 | let gainStr; 64 | if (count > 0) { 65 | gainStr = '获得:'; 66 | } else { 67 | gainStr = '失去:'; 68 | } 69 | 70 | this.icon.spriteFrame = itemIcon; 71 | this.nameLabel.string = itemName; 72 | this.gain.string = gainStr; 73 | this.countLabel.string = countStr; 74 | this.cb = cb; 75 | }, 76 | 77 | hide: function() { 78 | this.poolMng.put(this.node); 79 | this.game.hideUI(['default'], false, false); 80 | if (this.cb) this.cb.next(); 81 | 82 | }, 83 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/OptionBox.js: -------------------------------------------------------------------------------- 1 | const GameEvent = require('GameEvent'); 2 | 3 | var emptyFunc = function(event) { 4 | event.stopPropagation(); 5 | }; 6 | cc.Class({ 7 | extends: cc.Component, 8 | 9 | properties: { 10 | optionNodes: { 11 | default: [], 12 | type: cc.Node 13 | }, 14 | labels: { 15 | default: [], 16 | type: cc.Label 17 | }, 18 | 19 | gameNode: { 20 | default: null, 21 | type: cc.Node 22 | }, 23 | dialogueComp: null, 24 | poolMng: null 25 | }, 26 | 27 | // use this for initialization 28 | onLoad: function() { 29 | this.game = this.gameNode.getComponent("Game"); 30 | }, 31 | 32 | onEnable: function() { 33 | this.node.on('touchstart', emptyFunc, this); 34 | }, 35 | 36 | showOption: function(options, cb) { 37 | this.game.hideUI(['default'], true, false); 38 | this.options = options; 39 | //显示需要数量的选项 40 | for (var i = 0; i < this.optionNodes.length; i++) { 41 | if (i < options.length) { 42 | this.optionNodes[i].active = true; 43 | this.labels[i].string = options[i].label; 44 | } else 45 | this.optionNodes[i].active = false; 46 | } 47 | this.cb = cb; 48 | }, 49 | 50 | option0: function() { 51 | var index = 0; 52 | this.execute(index); 53 | }, 54 | 55 | option1: function() { 56 | var index = 1; 57 | this.execute(index); 58 | }, 59 | 60 | option2: function() { 61 | var index = 2; 62 | this.execute(index); 63 | }, 64 | 65 | option3: function() { 66 | var index = 3; 67 | this.execute(index); 68 | }, 69 | 70 | execute: function(optionIndex) { 71 | let subEvent = this.options[optionIndex].subEvent 72 | let gameEvent = new GameEvent(); 73 | gameEvent.setCallback(this.cb); 74 | if (this.cb instanceof GameEvent) { 75 | gameEvent.setTarget(this.cb.event.target); 76 | this.cb.setChild(gameEvent); 77 | } 78 | this.dialogueComp.updataDisplay(); 79 | this.options = null; 80 | this.game.hideUI(['default'], false, false); 81 | gameEvent.startBySubEvent(subEvent); 82 | this.poolMng.put(this.node); 83 | }, 84 | 85 | onDisable: function() { 86 | this.node.off('touchstart', emptyFunc, this); 87 | } 88 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/BagItem.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | // foo: { 6 | // default: null, // The default value will be used only when the component attaching 7 | // to a node for the first time 8 | // url: cc.Texture2D, // optional, default is typeof default 9 | // serializable: true, // optional, default is true 10 | // visible: true, // optional, default is true 11 | // displayName: 'Foo', // optional 12 | // readonly: false, // optional, default is false 13 | // }, 14 | // ... 15 | itemId: "", 16 | icon: { 17 | default: null, 18 | type: cc.SpriteFrame 19 | }, 20 | itemName: "", 21 | itemNum: 0, 22 | description: "", 23 | iconSprite: { 24 | default: null, 25 | type: cc.Sprite 26 | }, 27 | nameLabel: { 28 | default: null, 29 | type: cc.Label 30 | }, 31 | bag: null, 32 | numberLabel: { 33 | default: null, 34 | type: cc.Label 35 | }, 36 | normal: { 37 | default: null, 38 | type: cc.SpriteFrame 39 | }, 40 | pressed: { 41 | default: null, 42 | type: cc.SpriteFrame 43 | }, 44 | }, 45 | 46 | // use this for initialization 47 | onLoad: function () { 48 | this.nameLabel.string = this.itemName; 49 | this.numberLabel.string = this.itemNum.toString(); 50 | this.iconSprite.spriteFrame = this.icon; 51 | 52 | this.node.on(cc.Node.EventType.TOUCH_START, function (event) { 53 | this.setPressed(); 54 | }, this); 55 | 56 | this.node.on(cc.Node.EventType.TOUCH_END, function (event) { 57 | this.isSelected(); 58 | }, this); 59 | 60 | this.node.on(cc.Node.EventType.TOUCH_CANCEL, function (event) { 61 | this.setNormal(); 62 | }, this); 63 | 64 | }, 65 | 66 | isSelected: function () { 67 | this.setPressed(); 68 | this.bag.selectItem(this); 69 | }, 70 | 71 | setNormal: function () { 72 | this.getComponent(cc.Sprite).spriteFrame = this.normal; 73 | }, 74 | 75 | setPressed: function () { 76 | this.getComponent(cc.Sprite).spriteFrame = this.pressed; 77 | } 78 | // called every frame, uncomment this function to activate update callback 79 | // update: function (dt) { 80 | 81 | // }, 82 | }); 83 | -------------------------------------------------------------------------------- /assets/scripts/core/system/Global.js: -------------------------------------------------------------------------------- 1 | const MoveState = cc.Enum({ 2 | Stand: 0, 3 | Up: 8, 4 | Right: 6, 5 | Down: 2, 6 | Left: 4, 7 | LeftDown: 1, 8 | RightDown: 3, 9 | LeftUp: 7, 10 | RightUp: 9 11 | }); 12 | const Direction = cc.Enum({ 13 | None: 0, 14 | Up: 8, 15 | Right: 6, 16 | Down: 2, 17 | Left: 4, 18 | LeftDown: 1, 19 | RightDown: 3, 20 | LeftUp: 7, 21 | RightUp: 9 22 | }); 23 | const EventType = cc.Enum({ 24 | Dialogue: 1, 25 | Shop: 2, 26 | SwitchScene: 3, 27 | ScrollMap: 5, 28 | MoveActor: 6, 29 | ShowActor: 7, 30 | SetDone: 8, 31 | SetActorPos: 9, 32 | ShowActorBalloon: 10, 33 | ShowItemBox: 11, 34 | AddItem: 12, 35 | ShowMessage: 13, 36 | }); 37 | const LayerOrder = cc.Enum({ 38 | Below: 0, 39 | Same: 1, 40 | Above: 2, 41 | }); 42 | var RangeType = cc.Enum({ 43 | POINT: 1, 44 | SQUARE: 2, 45 | RHOMBUS: 3, 46 | LINE: 4, 47 | FRONTSQUARE: 5, 48 | FRONTRHOMBUS: 6, 49 | CROSS: 7, 50 | WALL: 8 51 | }); 52 | const GridPerStep = 2; 53 | const MoveStep = 32; 54 | const MoveTime = 0.25; 55 | const ActorOffset = 4; 56 | const MapList = { 57 | "1": "InnFirstFloor", 58 | "2": "InnSecondFloor", 59 | "3": "ForestOne", 60 | "4": "ForestTwo", 61 | "5": "ForestThree", 62 | "6": "ForestFour", 63 | "7": "CampNight", 64 | "8": "CampDay", 65 | "9": "Warehouse", 66 | "99": "Ending", 67 | "100": "StealthTest" 68 | }; 69 | //TileSetColumn是 门 所在的图集的列数 70 | const MapPara = { 71 | "1": { 72 | BlockTileGid: 385 73 | }, 74 | "2": { 75 | BlockTileGid: 385, 76 | TileSetColumn: 16 77 | }, 78 | "3": { 79 | BlockTileGid: 521 80 | }, 81 | "4": { 82 | BlockTileGid: 521 83 | }, 84 | "5": { 85 | BlockTileGid: 521 86 | }, 87 | "6": { 88 | BlockTileGid: 521 89 | }, 90 | "7": { 91 | BlockTileGid: 521 92 | }, 93 | "8": { 94 | BlockTileGid: 521 95 | }, 96 | "100": { 97 | BlockTileGid: 521 98 | } 99 | }; 100 | const NodeMap = { 101 | "1": "TouchPanel", 102 | "2": "MainButton", 103 | "default": ["TouchPanel", "MainButton", "GroupList", "GameMenu"] 104 | } 105 | const AudioPath = 'resources/Audio/' 106 | module.exports = { 107 | MoveState: MoveState, 108 | Direction: Direction, 109 | EventType: EventType, 110 | LayerOrder: LayerOrder, 111 | RangeType: RangeType, 112 | GridPerStep: GridPerStep, 113 | MoveStep: MoveStep, 114 | MoveTime: MoveTime, 115 | MapList: MapList, 116 | ActorOffset: ActorOffset, 117 | NodeMap: NodeMap, 118 | AudioPath: AudioPath, 119 | MapPara: MapPara 120 | }; -------------------------------------------------------------------------------- /assets/scripts/core/UI/ConfirmBox.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | cc.Class({ 5 | extends: cc.Component, 6 | 7 | properties: { 8 | icon: { 9 | default: null, 10 | type: cc.Sprite 11 | }, 12 | itemName: { 13 | default: null, 14 | type: cc.Label 15 | }, 16 | priceLabel: { 17 | default: null, 18 | type: cc.Label 19 | }, 20 | countLabel: { 21 | default: null, 22 | type: cc.Label 23 | }, 24 | shopNode: { 25 | default: null, 26 | type: cc.Node 27 | }, 28 | }, 29 | 30 | // use this for initialization 31 | onLoad: function() { 32 | this.gameNode = cc.find("Game"); 33 | this.playerData = this.gameNode.getComponent("PlayerData"); 34 | this.count = 1; 35 | }, 36 | 37 | showItem: function(id, iconSprite, name, price, isBuy) { 38 | this.node.parent.on('touchstart', emptyFunc, this); 39 | this.isBuy = isBuy; 40 | this.itemId = id; 41 | this.icon.spriteFrame = iconSprite; 42 | this.itemName.string = name; 43 | if (isBuy) 44 | this.price = price; 45 | else 46 | this.price = Math.round(price * 0.6) 47 | this.count = 1; 48 | this.totalPrice = this.price * this.count; 49 | this.priceLabel.string = this.totalPrice.toString(); 50 | this.countLabel.string = this.count.toString(); 51 | }, 52 | 53 | add: function() { 54 | if (this.isBuy) { 55 | if (this.count < 99 && 56 | (this.count + 1) * this.price <= this.playerData.getMoney()) 57 | this.count++; 58 | } else { 59 | if (this.count < 99 && 60 | this.count < this.playerData.getItemCount(this.itemId)) 61 | this.count++; 62 | } 63 | 64 | this.countLabel.string = this.count.toString(); 65 | this.totalPrice = this.price * this.count; 66 | this.priceLabel.string = this.totalPrice.toString(); 67 | }, 68 | 69 | sub: function() { 70 | if (this.count > 0) 71 | this.count--; 72 | this.countLabel.string = this.count.toString(); 73 | this.totalPrice = this.price * this.count; 74 | this.priceLabel.string = this.totalPrice.toString(); 75 | }, 76 | 77 | confirm: function() { 78 | this.shopNode.emit("buyconfirm", { 79 | num: this.count, 80 | totalPrice: this.totalPrice 81 | }); 82 | this.node.parent.off('touchstart', emptyFunc, this); 83 | this.node.parent.active = false; 84 | }, 85 | 86 | cancel: function() { 87 | this.node.parent.off('touchstart', emptyFunc, this); 88 | this.node.parent.active = false; 89 | } 90 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/Slider.js: -------------------------------------------------------------------------------- 1 | var Direction = cc.Enum({ 2 | Horizontal: 1, 3 | Vertical: 2 4 | }) 5 | 6 | cc.Class({ 7 | extends: cc.Component, 8 | 9 | properties: () => ({ 10 | sliderBar: { 11 | default: null, 12 | type: require("SliderBar") 13 | } 14 | }), 15 | 16 | // use this for initialization 17 | onLoad: function() { 18 | var self = this; 19 | this.direction = this.sliderBar.direction; 20 | switch (this.direction) { 21 | case Direction.Horizontal: 22 | this.barLength = this.sliderBar.node.width; 23 | break; 24 | case Direction.Vertical: 25 | this.barLength = this.sliderBar.node.height; 26 | break; 27 | } 28 | this.node.on(cc.Node.EventType.TOUCH_MOVE, function(event) { 29 | var delta = event.getDelta(); 30 | switch (this.direction) { 31 | case Direction.Horizontal: 32 | var newX = this.node.x + delta.x; 33 | if (newX < 0) 34 | newX = 0; 35 | else if (newX > this.barLength) 36 | newX = this.barLength; 37 | this.node.x = newX 38 | break; 39 | case Direction.Vertical: 40 | var newY = this.node.y + delta.y; 41 | if (newY < -this.barLength) 42 | newY = -this.barLength; 43 | else if (newY > 0) 44 | newY = 0; 45 | this.node.y = newY; 46 | break; 47 | } 48 | }, this); 49 | 50 | this.node.on(cc.Node.EventType.TOUCH_END, function(event) { 51 | event.stopPropagation(); 52 | this.sliderBar.sendRatio(this.getRatio()); 53 | }, this); 54 | 55 | this.node.on(cc.Node.EventType.TOUCH_CANCEL, function(event) { 56 | this.sliderBar.sendRatio(this.getRatio()); 57 | }, this); 58 | }, 59 | 60 | getRatio: function() { 61 | var ratio; 62 | switch (this.direction) { 63 | case Direction.Horizontal: 64 | ratio = this.node.x / this.barLength; 65 | break; 66 | case Direction.Vertical: 67 | ratio = Math.abs(this.node.y / this.barLength); 68 | break; 69 | } 70 | //cc.log("ratio", ratio) 71 | return ratio; 72 | }, 73 | 74 | setPos: function(ratio) { 75 | switch (this.direction) { 76 | case Direction.Horizontal: 77 | this.node.x = ratio * this.barLength; 78 | break; 79 | case Direction.Vertical: 80 | this.node.y = -(ratio * this.barLength); 81 | break; 82 | } 83 | }, 84 | 85 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Cache.js: -------------------------------------------------------------------------------- 1 | const ActionParse = require('ActionParse'); 2 | 3 | cc.Class({ 4 | extends: cc.Component, 5 | 6 | properties: { 7 | emotionAtlas: { 8 | default: null, 9 | type: cc.SpriteAtlas 10 | }, 11 | itemAtlas: { 12 | default: null, 13 | type: cc.SpriteAtlas 14 | }, 15 | avatarAtlas: cc.SpriteAtlas, 16 | sectorAtlas: cc.SpriteAtlas, 17 | itemJson: { 18 | default: null, 19 | url: cc.RawAsset 20 | }, 21 | actorActionJson: { 22 | default: null, 23 | url: cc.RawAsset 24 | } 25 | }, 26 | 27 | // use this for initialization 28 | onLoad: function() { 29 | this.releaseResList = []; 30 | this.balloonClip = []; 31 | this.itemTable = {}; 32 | this.actorAction = {}; 33 | var self = this; 34 | 35 | 36 | //读取道具列表到缓存中 37 | //因为是必须读取文件,使用预加载 38 | if (this.itemJson) { 39 | this.itemTable = cc.loader.getRes(this.itemJson); 40 | } 41 | // var fileName = "Global/Item"; 42 | // cc.loader.loadRes(fileName, function(err, jsonData) { 43 | // if (err) { 44 | // cc.log(fileName, 'read error'); 45 | // return; 46 | // } 47 | // cc.log("load item table"); 48 | // self.itemTable = jsonData; 49 | // cc.loader.releaseRes(fileName); 50 | // }); 51 | if (this.actorActionJson) { 52 | this.actorAction = cc.loader.getRes(this.actorActionJson); 53 | } 54 | }, 55 | 56 | getEmotionAtlas: function() { 57 | return this.emotionAtlas; 58 | }, 59 | 60 | getItemSprite: function(itemId) { 61 | var name = "IconSet_" + itemId; 62 | var spriteFrame = this.itemAtlas.getSpriteFrame(name); 63 | if (spriteFrame != null && spriteFrame != undefined) 64 | return spriteFrame; 65 | else 66 | return null; 67 | }, 68 | 69 | getAvatar: function(actorId) { 70 | var name = actorId.toString(); 71 | if (!this.avatarAtlas) return; 72 | var spriteFrame = this.avatarAtlas.getSpriteFrame(name); 73 | return (spriteFrame == null ? null : spriteFrame); 74 | 75 | }, 76 | 77 | getSectorRangeSprite: function(range) { 78 | if (!this.sectorAtlas) return; 79 | let spriteFrame = this.sectorAtlas.getSpriteFrame(range); 80 | return (spriteFrame == null ? null : spriteFrame); 81 | }, 82 | 83 | getItemInfo: function(itemId) { 84 | return this.itemTable[itemId]; 85 | }, 86 | 87 | getAction: function(actionTag) { 88 | var actionConfig = this.actorAction[actionTag]; 89 | var action; 90 | if (actionConfig) { 91 | action = ActionParse(actionConfig); 92 | } 93 | return action; 94 | }, 95 | 96 | releaseRes: function() { 97 | for (let i = 0; i < this.releaseResList.length; i++) { 98 | cc.loader.releaseRes(this.releaseResList[i]); 99 | } 100 | this.releaseResList = []; 101 | } 102 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/GameMenu.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | _isShown: false, 6 | animation: cc.Animation, 7 | listNode: cc.Node 8 | }, 9 | 10 | onLoad: function() { 11 | this.gameNode = cc.find("Game"); 12 | this.game = this.gameNode.getComponent("Game"); 13 | this.windowManager = this.gameNode.getComponent('WindowManager'); 14 | }, 15 | 16 | onEnable: function() { 17 | var posX; 18 | var posY; 19 | this.node.on('touchstart', function(event) { 20 | posX = event.touch.getLocationX(); 21 | posY = event.touch.getLocationY(); 22 | }, this); 23 | 24 | this.node.on('touchmove', function(event) { 25 | var px = event.touch.getLocationX(); 26 | var py = event.touch.getLocationY(); 27 | //横向 28 | if (posX - px > 75 && !this._isShown) { 29 | this.show(0); 30 | } 31 | if (px - posX > 75 && this._isShown) { 32 | this.hide(0); 33 | } 34 | //纵向 35 | if (posY - py > 75 && !this._isShown) { 36 | this.show(1); 37 | } 38 | if (py - posY > 75 && this._isShown) { 39 | this.hide(1); 40 | } 41 | }, this) 42 | }, 43 | 44 | /** 45 | * direction: 0->horizontal, 1->vertical 46 | */ 47 | show: function(direction) { 48 | //没有动画组件则直接隐藏 49 | if (this.animation) { 50 | if (direction) { 51 | this.animation.play('ShowMenuSlideV'); 52 | } else { 53 | this.animation.play('ShowMenuSlideH'); 54 | } 55 | } else { 56 | this.listNode.active = true; 57 | } 58 | this._isShown = true; 59 | }, 60 | 61 | hide: function(direction) { 62 | if (this.animation) { 63 | if (direction) { 64 | this.animation.play('HideMenuSlideV'); 65 | } else { 66 | this.animation.play('HideMenuSlideH'); 67 | } 68 | } else { 69 | this.listNode.active = false; 70 | } 71 | this._isShown = false; 72 | }, 73 | 74 | clickHandleBar: function() { 75 | if (this._isShown) { 76 | if (this.animation) { 77 | this.animation.play('HideMenu'); 78 | } else { 79 | this.listNode.active = false; 80 | } 81 | } else { 82 | if (this.animation) { 83 | this.animation.play('ShowMenu'); 84 | } else { 85 | this.listNode.active = true; 86 | } 87 | } 88 | this._isShown = !this._isShown; 89 | }, 90 | 91 | showBag: function() { 92 | this.windowManager.showBagWindow(); 93 | }, 94 | 95 | showTask: function() { 96 | this.windowManager.showTaskWindow(); 97 | }, 98 | 99 | showSaveWindow: function() { 100 | this.windowManager.showSaveWindow(); 101 | }, 102 | 103 | showSystemWindow: function() { 104 | this.windowManager.showSystemWindow(); 105 | }, 106 | 107 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/DialogueBox.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | nameLabel: { 6 | default: null, 7 | type: cc.Label 8 | }, 9 | dialogue: { 10 | default: null, 11 | type: cc.Label 12 | }, 13 | gameNode: { 14 | default: null, 15 | type: cc.Node 16 | }, 17 | poolMng: null 18 | }, 19 | 20 | // use this for initialization 21 | onLoad: function() { 22 | var self = this; 23 | this.game = cc.find("Game").getComponent("Game"); 24 | this.eventManager = this.gameNode.getComponent("EventManager"); 25 | this.script = []; 26 | this.nameLabel.string = ''; 27 | this.dialogue.string = ''; 28 | this.busy = false; 29 | this.index = 0; 30 | 31 | this.node.on(cc.Node.EventType.TOUCH_START, function(event) { 32 | self.updataDisplay(); 33 | }, this); 34 | 35 | /* 36 | this.node.on(cc.Node.EventType.TOUCH_MOVE,function(event) { 37 | 38 | },this); 39 | 40 | this.node.on(cc.Node.EventType.TOUCH_END, function (event) { 41 | }, this); 42 | 43 | this.node.on(cc.Node.EventType.TOUCH_CANCEL, function (event) { 44 | }, this); 45 | */ 46 | }, 47 | 48 | // called every frame, uncomment this function to activate update callback 49 | //update: function (dt) { 50 | 51 | //}, 52 | 53 | /** 54 | * !#zh 55 | * 显示对话 56 | * @param {Object} dialogueMsg [{name,script[]},{name,script[]},...] 57 | * @param {Object} actorTarget 58 | * @param {Function} cb 59 | */ 60 | showMessage: function(dialogueMsg, actorTarget, cb) { 61 | //this.node.active = true; 62 | this.busy = true; 63 | this.game.hideUI(['default'], true, false); 64 | //被触发的对象 65 | this.actor = actorTarget; 66 | if (this.actor != undefined) { 67 | this.actor.facePlayer(); 68 | } 69 | this.dialogueMsg = dialogueMsg; 70 | //dialogueMsg索引,一个元素之可能是一个名字 71 | this.index1 = 0; 72 | //script 索引,同一名字所说的话,一个元素为一页 73 | this.index2 = 0; 74 | this.nameLabel.string = this.dialogueMsg.actors[this.index1].name; 75 | this.script = this.dialogueMsg.actors[this.index1].dialogues; 76 | this.cb = cb; 77 | this.updataDisplay(); 78 | }, 79 | 80 | updataDisplay: function() { 81 | if (this.index2 < this.script.length) { 82 | this.dialogue.string = this.script[this.index2++]; 83 | } else { 84 | this.index1++; 85 | if (this.index1 < this.dialogueMsg.actors.length) { 86 | this.index2 = 0; 87 | this.nameLabel.string = this.dialogueMsg.actors[this.index1].name; 88 | this.script = this.dialogueMsg.actors[this.index1].dialogues; 89 | this.dialogue.string = this.script[this.index2++]; 90 | } else { 91 | this.busy = false; 92 | this.poolMng.put(this.node) 93 | this.game.hideUI(['default'], false, false); 94 | if (this.actor != undefined) 95 | this.actor.faceDefault(); 96 | if (this.cb) this.cb.next(); 97 | } 98 | } 99 | } 100 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/AudioManager.js: -------------------------------------------------------------------------------- 1 | const RPG = require('Global'); 2 | const AudioPath = RPG.AudioPath; 3 | 4 | cc.Class({ 5 | extends: cc.Component, 6 | 7 | properties: { 8 | 9 | }, 10 | 11 | // use this for initialization 12 | onLoad: function() { 13 | this.audioList = []; 14 | //默认音量大小 15 | this.musicVolume = 0.3; 16 | this.effectVolume = 0.3; 17 | this.musicList = {}; 18 | this.preMusicList = {}; 19 | 20 | var self = this; 21 | 22 | //audioEngine bug 23 | cc.game.on(cc.game.EVENT_HIDE, function() { 24 | for (var key in self.musicList) { 25 | cc.audioEngine.pause(self.musicList[key]) 26 | } 27 | 28 | }); 29 | 30 | cc.game.on(cc.game.EVENT_SHOW, function() { 31 | for (var key in self.musicList) { 32 | cc.audioEngine.resume(self.musicList[key]) 33 | } 34 | }); 35 | }, 36 | 37 | /** 38 | * 预加载场景中用到的音频,与以加载的进行对比,释放不再使用的音频 39 | */ 40 | preload: function(audioList) { 41 | 42 | //加载新音频 43 | for (let i = 0; i < audioList.length; i++) { 44 | for (let j = 0; j < this.audioList.length; j++) { 45 | if (audioList[i] === this.audioList[j]) { 46 | break; 47 | } 48 | } 49 | //如果未加载,则加载新音频 50 | if (j === this.audioList.length) { 51 | cc.audioEngine.preload(audioList[i]); 52 | } 53 | } 54 | 55 | //释放不再使用的音频 56 | for (let i = 0; i < this.audioList.length; i++) { 57 | for (let j = 0; j < audioList.length; j++) { 58 | if (this.audioList[i] === audioList[j]) { 59 | break; 60 | } 61 | } 62 | if (j === audioList.length) { 63 | cc.audioEngine.uncache(AudioPath + this.audioList[i]); 64 | } 65 | } 66 | 67 | this.audioList = audioList; 68 | }, 69 | 70 | playMusic: function(audioName, loop, cb) { 71 | let audioId = cc.audioEngine.play(cc.url.raw(AudioPath + audioName), loop, this.musicVolume); 72 | this.musicList[audioName] = audioId; 73 | if (this.musicVolume == 0) { 74 | this.setMusicVolume(0); 75 | } 76 | if (cb) cb.next(); 77 | }, 78 | 79 | pauseMusic: function(audioName, cb) { 80 | cc.audioEngine.pause(this.musicList[audioName]); 81 | if (cb) cb.next(); 82 | }, 83 | resumeMusic: function(audioName, loop, cb) { 84 | if (audioName in this.preMusicList) { 85 | this.musicList[audioName] = this.preMusicList[audioName]; 86 | cc.audioEngine.resume(this.musicList[audioName]); 87 | } else { 88 | this.playMusic(audioName, loop, null) 89 | } 90 | if (cb) cb.next(); 91 | }, 92 | stopMusic: function(audioName, cb) { 93 | cc.audioEngine.stop(this.musicList[audioName]); 94 | delete this.musicList[audioName]; 95 | if (cb) cb.next(); 96 | }, 97 | 98 | stopAll: function(cb) { 99 | cc.audioEngine.stopAll(); 100 | this.musicList = {}; 101 | if (cb) cb.next(); 102 | }, 103 | 104 | playEffect: function(audioName, cb) { 105 | cc.audioEngine.play(cc.url.raw(AudioPath + audioName), false, this.effectVolume); 106 | if (cb) cb.next(); 107 | }, 108 | 109 | getMusicVolume: function() { 110 | return this.musicVolume; 111 | }, 112 | 113 | setMusicVolume: function(volume) { 114 | this.musicVolume = volume; 115 | for (let musicName in this.musicList) { 116 | cc.audioEngine.setVolume(this.musicList[musicName], volume); 117 | } 118 | }, 119 | 120 | getEffectVolume: function() { 121 | return this.effectVolume; 122 | }, 123 | 124 | setEffectVolume: function(volume) { 125 | this.effectVolume = volume; 126 | }, 127 | 128 | clearMusicList: function() { 129 | this.preMusicList = this.musicList; 130 | this.musicList = {}; 131 | }, 132 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Scene.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | mapNode: cc.Node, 6 | actorNode: cc.Node, 7 | belowActorNode: cc.Node, 8 | aboveActorNode: cc.Node 9 | }, 10 | 11 | // use this for initialization 12 | onLoad: function() { 13 | this.stealth = this.node.getComponent('Stealth'); 14 | this.mapNode = this.mapNode || cc.find('Canvas/Map'); 15 | this.map = this.mapNode.getComponent('Map'); 16 | this.actorNode = this.actorNode || cc.find('Canvas/Map/Actor'); 17 | //this.belowActorNode = this.belowActorNode || cc.find('Canvas/Map/BelowActor'); 18 | //this.aboveActorNode = this.aboveActorNode || cc.find('Canvas/Map/AboveActor'); 19 | this.gameNode = cc.find('Game'); 20 | this.game = this.gameNode.getComponent('Game'); 21 | this.eventManager = this.gameNode.getComponent('EventManager'); 22 | this.audioManager = this.gameNode.getComponent('AudioManager'); 23 | 24 | //创建BelowActor节点和AboveActor节点。 25 | let actorNodeIndex = this.actorNode.getSiblingIndex(); 26 | // this.belowActorNode = new cc.Node('BelowActor'); 27 | this.aboveActorNode = new cc.Node('AboveActor'); 28 | // cc.log(actorNodeIndex) 29 | // this.mapNode.addChild(this.belowActorNode); 30 | this.mapNode.addChild(this.aboveActorNode); 31 | // this.belowActorNode.setSiblingIndex(actorNodeIndex); 32 | // actorNodeIndex = this.actorNode.getSiblingIndex(); 33 | // cc.log(actorNodeIndex); 34 | this.aboveActorNode.setSiblingIndex(actorNodeIndex + 1); 35 | 36 | //遍历角色并记录 37 | this.actorList = {}; 38 | this.dynamicActorList = []; 39 | let actors = this.actorNode.children; 40 | for (let i = 0; i < actors.length; i++) { 41 | let target = actors[i].getComponent('Actor'); 42 | if (target) 43 | this.actorList[target.actorId] = target; 44 | } 45 | }, 46 | 47 | start: function() { 48 | let self = this; 49 | //读取地图事件 50 | let mapEventFile = 'Scene/' + this.map.mapId + '/MapEvent'; 51 | cc.loader.loadRes(mapEventFile, function(err, mapEvents) { 52 | if (err) { 53 | cc.log(mapEventFile + ' read error'); 54 | //return; 55 | } 56 | 57 | //读取人物事件 58 | let ActorEventFile = 'Scene/' + self.map.mapId + '/ActorEvent'; 59 | cc.loader.loadRes(ActorEventFile, function(err, actorEvents) { 60 | if (err) { 61 | cc.log(ActorEventFile + ' read error'); 62 | //return; 63 | } 64 | for (let actorId in self.actorList) { 65 | let actor = self.actorList[actorId] 66 | actor._initActor(); 67 | if (actorEvents) { 68 | actor.initEvent(actorEvents[actorId]); 69 | } 70 | if (actor.node.active) { 71 | actor.registerEvent(); 72 | } 73 | if (actor.dynamic) { 74 | self.dynamicActorList.push(actor); 75 | } 76 | } 77 | 78 | //此处为初始化最后的部分 79 | self.gameNode.emit('scene-init-done', { 80 | scene: self 81 | }) 82 | }); 83 | 84 | //注册地图事件 85 | for (let eventId in mapEvents) { 86 | self.eventManager.createEvent(eventId, mapEvents[eventId]); 87 | } 88 | 89 | }); 90 | 91 | //读取预加载音频 92 | /* 93 | let audioFile = 'Scene/' + this.map.mapId + '/Audio'; 94 | cc.loader.loadRes(audioFile, function(err, audioList) { 95 | if (err) { 96 | cc.log(audioFile + ' read error'); 97 | return; 98 | } 99 | //self.audioManager.preload(audioList); 100 | }); 101 | */ 102 | }, 103 | 104 | getActorTarget: function(actorId) { 105 | return null || this.actorList[actorId]; 106 | }, 107 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Treasure.js: -------------------------------------------------------------------------------- 1 | const GameEvent = require('GameEvent'); 2 | 3 | cc.Class({ 4 | extends: cc.Component, 5 | 6 | properties: { 7 | treasureId: "", 8 | once: true, 9 | isChest: true, 10 | chestAtlas: { 11 | default: null, 12 | type: cc.SpriteAtlas 13 | }, 14 | mapNode: { 15 | default: null, 16 | type: cc.Node 17 | }, 18 | }, 19 | 20 | // use this for initialization 21 | onLoad: function() { 22 | this.mapNode = this.mapNode || cc.find('Canvas/Map'); 23 | this.map = this.mapNode.getComponent('Map'); 24 | this.gameNode = cc.find("Game"); 25 | this.game = this.gameNode.getComponent("Game"); 26 | this.eventManager = this.gameNode.getComponent("EventManager"); 27 | this.animation = this.node.getComponent(cc.Animation); 28 | 29 | //初始化开启箱子动画 30 | if (this.isChest) { 31 | var frame = []; 32 | for (let i = 1; i < 5; i++) { 33 | let spriteFrameName = "0" + i; 34 | frame.push(this.chestAtlas.getSpriteFrame(spriteFrameName)); 35 | } 36 | let clip = cc.AnimationClip.createWithSpriteFrames(frame, 8); 37 | this.animation.addClip(clip, "Treasure"); 38 | } 39 | }, 40 | 41 | start: function() { 42 | if (this.isChest) 43 | this.map.setTileBlock(this.getTilePos()); 44 | if (this.inTreasureList(this.treasureId)) { 45 | if (this.isChest) { 46 | this.node.getComponent(cc.Sprite).spriteFrame = this.chestAtlas.getSpriteFrame("04"); 47 | } else { 48 | this.animation.stop(); 49 | this.node.active = false; 50 | } 51 | return; 52 | } 53 | this.registerEvent(); 54 | }, 55 | 56 | registerEvent: function() { 57 | var self = this; 58 | var filePath = 'Scene/' + self.map.mapId + '/Treasure'; 59 | cc.loader.loadRes(filePath, function(err, jsonData) { 60 | if (err) { 61 | cc.log("Doesn't find : ", filePath); 62 | return; 63 | } 64 | 65 | let event = jsonData[self.treasureId]; 66 | if (!event) return; 67 | event.target = self; 68 | let eventId = self.eventManager.generateEventId(self.map.mapId, self.getRealTilePos()); 69 | self.eventManager.createEvent(eventId, event); 70 | }); 71 | }, 72 | 73 | removeEvent: function() { 74 | this.eventManager.removeEvent(this.eventManager.generateEventId(this.map.mapId, this.getRealTilePos())); 75 | }, 76 | 77 | getPos: function() { 78 | return cc.p(Math.round(this.node.x), Math.round(this.node.y)); 79 | }, 80 | getPosX: function() { 81 | return Math.round(this.node.x); 82 | }, 83 | getPosY: function() { 84 | return Math.round(this.node.y); 85 | }, 86 | getTilePos: function() { 87 | var x = Math.round(this.getPosX() / this.map.tileSize.width); 88 | var y = Math.round(this.getPosY() / this.map.tileSize.height); 89 | y = this.map.mapTileSize.height - y - 1; //坐标系不同,需要转换 90 | return cc.p(x, y); 91 | }, 92 | 93 | /** 94 | * 以左下角为原点的Tile坐标(遗留问题) 95 | */ 96 | getRealTilePosY: function() { 97 | var y = Math.round(this.getPosY() / this.map.tileSize.height); 98 | return y; 99 | }, 100 | 101 | getRealTilePos: function() { 102 | return cc.p(this.getTilePos().x, this.getRealTilePosY()); 103 | }, 104 | 105 | inTreasureList: function(treasureId) { 106 | for (let i = 0; i < this.game.treasureList.length; i++) { 107 | if (treasureId === this.game.treasureList[i]) 108 | return true; 109 | } 110 | return false; 111 | }, 112 | 113 | getTreasure: function(gainEvent, cb) { 114 | this.removeEvent(); 115 | if (this.once) { 116 | this.game.treasureList.push(this.treasureId); 117 | } 118 | if (this.isChest) { 119 | this.animation.play("Treasure"); 120 | } else { 121 | this.animation.stop(); 122 | this.node.active = false; 123 | } 124 | let gameEvent = new GameEvent(); 125 | gameEvent.setCallback(cb); 126 | gameEvent.startBySubEvent(gainEvent); 127 | if (cb instanceof GameEvent) { 128 | cb.setChild(gameEvent); 129 | } 130 | }, 131 | 132 | onDisable: function() { 133 | if (this.isChest) 134 | this.map.removeTileBlock(this.getTilePos()); 135 | this.removeEvent() 136 | }, 137 | 138 | onDestroy: function() { 139 | if (this.isChest) 140 | this.map.removeTileBlock(this.getTilePos()); 141 | } 142 | 143 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/EventManager.js: -------------------------------------------------------------------------------- 1 | var GameEvent = require("GameEvent"); 2 | 3 | cc.Class({ 4 | extends: cc.Component, 5 | 6 | properties: { 7 | 8 | }, 9 | 10 | // use this for initialization 11 | onLoad: function() { 12 | var self = this; 13 | this.game = this.node.getComponent('Game'); 14 | this.eventSwitcher = {}; 15 | this.eventList = {}; 16 | cc.log('event init'); 17 | 18 | this.eventDone = { 19 | '1': false 20 | } 21 | }, 22 | 23 | createEvent: function(eventId, event) { 24 | let gameEvent = new GameEvent(); 25 | if (eventId in this.eventList) return; 26 | 27 | if (typeof event === 'string') { 28 | gameEvent.setEventByStr(event); 29 | } else if (typeof event === 'object') { 30 | gameEvent.setEventByObj(event); 31 | } else { 32 | console.log('CreateEvent: error type'); 33 | return; 34 | } 35 | 36 | this.eventList[eventId] = gameEvent; 37 | }, 38 | 39 | 40 | /** 41 | * !#zh 42 | * 根据地图ID和触发位置生成事件ID 43 | * @param {String} mapId 44 | * @param {Object} triggerPos 45 | * @return {String} 46 | */ 47 | generateEventId: function(mapId, triggerPos) { 48 | return mapId.toString() + "-" + triggerPos.x.toString() + 49 | "-" + triggerPos.y.toString(); 50 | }, 51 | 52 | /** 53 | * !#zh 54 | * 根据地图ID和触发位置获取事件ID 55 | * @param {String} mapId 56 | * @param {Object} triggerPos 57 | * @return {String} 58 | */ 59 | getEventId: function(mapId, triggerPos) { 60 | return this.generateEventId(mapId, triggerPos); 61 | }, 62 | 63 | /** 64 | * 根据事件ID判断是否有该事件 65 | */ 66 | checkEventById: function(eventId, triggerType) { 67 | if (eventId in this.eventList) { 68 | if (this.eventList[eventId].event.triggerType == triggerType) { 69 | return true; 70 | } 71 | } 72 | return false; 73 | 74 | }, 75 | 76 | eventStart: function(eventId) { 77 | let event = this.eventList[eventId]; 78 | if (event) event.start(); 79 | }, 80 | 81 | eventPause: function(eventId) { 82 | let event = this.eventList[eventId]; 83 | if (event) event.stop(); 84 | }, 85 | 86 | eventResume: function(eventId) { 87 | let event = this.eventList[eventId]; 88 | if (event) event.resume(); 89 | }, 90 | 91 | eventStop: function(eventId) { 92 | let event = this.eventList[eventId]; 93 | if (event) event.stop(); 94 | }, 95 | 96 | eventControl: function(eventId, state, cb) { 97 | switch (state) { 98 | case 0: 99 | //start 100 | this.eventStart(eventId); 101 | break; 102 | case 1: 103 | //pause 104 | this.eventStop(eventId); 105 | break; 106 | case 2: 107 | //resume 108 | this.eventResume(eventId); 109 | break; 110 | case 3: 111 | //stop 112 | this.eventStop(eventId); 113 | break; 114 | } 115 | if (cb) cb(); 116 | }, 117 | 118 | /** 119 | * !#zh 120 | * 检测条件是否符合 121 | * @param {Object} condition 122 | * @return {Boolean} 123 | */ 124 | checkCondition: function(condition) { 125 | switch (condition.type) { 126 | case 1: 127 | if (this.playerData.checkItem(condition.id) >= condition.num) 128 | return true; 129 | else 130 | return false; 131 | } 132 | }, 133 | 134 | /** 135 | * !#zh 136 | * 设置事件完成标志,防止多次开始初始事件 137 | * @param {String} eventId 138 | * @param {Boolean} done 139 | * @param {Function} cb 140 | */ 141 | //setDoneFlag: function (detail, nextEvent) 142 | setDoneFlag: function(eventId, done, cb) { 143 | //var eventId = detail.eventId; 144 | //var done = detail.done; 145 | this.eventDone[eventId] = done; 146 | if (cb) cb.next(); 147 | }, 148 | /** 149 | * !#zh 150 | * 设置开关 151 | * @param {Number} switcherId 152 | * @param {Boolean} flag 153 | * @param {Function} cb 154 | */ 155 | setSwitcher: function(switcherId, flag, cb) { 156 | this.eventSwitcher[switcherId] = flag; 157 | if (cb) cb.next(); 158 | }, 159 | /** 160 | * !#zh 161 | * 移除事件 162 | * @param {String} eventId 163 | */ 164 | removeEvent: function(eventId) { 165 | //var eventId = this.generateEventId(mapId, triggerPos); 166 | //cc.log(eventId) 167 | if (eventId in this.eventList) 168 | delete this.eventList[eventId]; 169 | }, 170 | 171 | clearEvent: function() { 172 | for (var eventId in this.eventList) { 173 | this.eventList[eventId].stop(); 174 | } 175 | this.eventList = {}; 176 | } 177 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/BagSystem.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | 5 | cc.Class({ 6 | extends: cc.Component, 7 | 8 | properties: { 9 | gameNode: cc.Node, 10 | bagItemPrefab: cc.Prefab, 11 | statusPrefab: cc.Prefab, 12 | itemContent: cc.Node, 13 | actorContent: cc.Node, 14 | gold: cc.Label, 15 | descriptionLabel: cc.Label 16 | }, 17 | 18 | // use this for initialization 19 | onLoad: function() { 20 | this.gameNode = this.gameNode || cc.find('Game'); 21 | this.game = this.gameNode.getComponent("Game"); 22 | this.playerData = this.gameNode.getComponent("PlayerData"); 23 | this.actorManager = this.gameNode.getComponent("ActorManager"); 24 | this.cache = this.game.getComponent('Cache'); 25 | this.currentItem = null; 26 | this.preItem = null; 27 | this.descriptionLabel.string = ""; 28 | }, 29 | 30 | onEnable: function() { 31 | this.node.on('touchstart', emptyFunc, this); 32 | this.showBagBox(); 33 | }, 34 | 35 | showBagBox: function() { 36 | //this.node.active = true; 37 | var items = this.playerData.getItems(); 38 | var itemIdList = Object.keys(items); 39 | this.gold.string = this.playerData.getMoney().toString() + " G"; 40 | this.createItemList(itemIdList); 41 | }, 42 | 43 | createItem: function(itemId) { 44 | var itemInfo = this.cache.getItemInfo(itemId); 45 | var itemNode = cc.instantiate(this.bagItemPrefab); 46 | var item = itemNode.getComponent("BagItem"); 47 | item.bag = this; 48 | item.itemId = itemId; 49 | item.itemName = itemInfo.name; 50 | item.icon = this.cache.getItemSprite(itemId.toString()) 51 | item.itemType = itemInfo.type; 52 | item.description = itemInfo.description; 53 | item.itemNum = this.playerData.getItemCount(itemId); 54 | return item; 55 | }, 56 | 57 | createItemList: function(itemIdList) { 58 | var item; 59 | for (var i = 0; i < itemIdList.length; i++) { 60 | item = this.createItem(itemIdList[i]) 61 | this.itemContent.addChild(item.node); 62 | } 63 | }, 64 | 65 | clearItemList: function() { 66 | var list = this.itemContent.children; 67 | for (var i = 0; i < list.length; i++) { 68 | list[i].destroy(); 69 | } 70 | }, 71 | 72 | createActorList: function() { 73 | this.clearActorList(); 74 | var idList = this.game.playerList; 75 | var actorNode; 76 | var actor; 77 | for (var i = 0; i < idList.length; i++) { 78 | actorNode = cc.instantiate(this.statusPrefab); 79 | actor = actorNode.getComponent("ActorStatus"); 80 | var attributes = this.playerData.player[idList[i]].getAttributes(true); 81 | actor.handle = this; 82 | actor.actorId = idList[i]; 83 | actor.actorName = this.actorManager.getTarget(idList[i]).npcName; 84 | actor.HPBar.point = attributes.HP; 85 | actor.HPBar.maxPoint = attributes.MaxHP; 86 | actor.MPBar.point = attributes.MP; 87 | actor.MPBar.maxPoint = attributes.MaxMP; 88 | this.actorContent.addChild(actorNode); 89 | } 90 | }, 91 | 92 | clearActorList: function() { 93 | var list = this.actorContent.children; 94 | //描述标签不能删 95 | for (var i = 1; i < list.length; i++) { 96 | list[i].destroy(); 97 | } 98 | }, 99 | 100 | selectItem: function(item) { 101 | this.preItem = this.currentItem; 102 | if (this.preItem != null) 103 | if (this.preItem.itemId !== item.itemId) 104 | this.preItem.setNormal(); 105 | this.currentItem = item; 106 | this.descriptionLabel.string = item.description; 107 | 108 | // //使用道具功能 109 | // if (item.itemType == 11) { 110 | // this.createActorList(); 111 | // } else { 112 | // this.clearActorList(); 113 | // } 114 | }, 115 | 116 | selectButton: function(actor) { 117 | if (this.currentItem == null) return; 118 | var itemInfo = this.game.itemTable[this.currentItem.itemId]; 119 | var effect = itemInfo.effect; 120 | for (var key in effect) { 121 | switch (key) { 122 | case "HP": 123 | this.playerData.player[actor.actorId].loseHP(-effect[key]); 124 | break; 125 | case "MP": 126 | this.playerData.player[actor.actorId].loseMP(-effect[key]); 127 | } 128 | } 129 | 130 | //更新显示 131 | var attributes = this.playerData.player[actor.actorId].getAttributes(true); 132 | actor.HPBar.point = attributes.HP; 133 | actor.HPBar.maxPoint = attributes.MaxHP; 134 | actor.MPBar.point = attributes.MP; 135 | actor.MPBar.maxPoint = attributes.MaxMP; 136 | 137 | this.playerData.removeItem(this.currentItem.itemId, 1); 138 | var num = this.playerData.getItemCount(this.currentItem.itemId); 139 | if (num > 0) { 140 | this.currentItem.numberLabel.string = num.toString(); 141 | } else { 142 | this.currentItem.node.destroy(); 143 | this.currentItem = null; 144 | } 145 | }, 146 | 147 | close: function() { 148 | //this.node.active = false; 149 | this.node.destroy(); 150 | }, 151 | 152 | onDisable: function() { 153 | this.node.off('touchstart', emptyFunc, this); 154 | this.currentItem = null; 155 | this.preItem = null; 156 | this.descriptionLabel.string = ""; 157 | this.clearItemList(); 158 | this.clearActorList(); 159 | } 160 | 161 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/GameEvent.js: -------------------------------------------------------------------------------- 1 | var gameEvent = cc.Class({ 2 | ctor: function() { 3 | if (arguments[0]) { 4 | this.handle = arguments[0]; 5 | } else { 6 | this.handle = cc.find('Game').getComponent('EventHandle'); 7 | } 8 | 9 | this.event = {}; 10 | }, 11 | properties: { 12 | loop: false, 13 | repeatCount: 0, 14 | _repeatCount: 0, 15 | _running: false, 16 | _stop: false, 17 | _child: null 18 | }, 19 | 20 | setEventByObj: function(event) { 21 | this.event = event; 22 | this.loop = event.loop; 23 | if (event.repeatCount && event.repeatCount === 'Infinity') { 24 | this.repeatCount = Infinity; 25 | } else if (event.repeatCount) { 26 | this.repeatCount = event.repeatCount - 1; 27 | } else { 28 | this.repeatCount = 0; 29 | } 30 | this._repeatCount = this.repeatCount; 31 | }, 32 | 33 | setEventByStr: function(eventStr) { 34 | this.event = JSON.parse(eventStr); 35 | this.loop = event.loop; 36 | if (event.repeatCount && event.repeatCount === 'Infinity') { 37 | this.repeatCount = Infinity; 38 | } else if (event.repeatCount) { 39 | this.repeatCount = event.repeatCount - 1; 40 | } else { 41 | this.repeatCount = 0; 42 | } 43 | this._repeatCount = this.repeatCount; 44 | }, 45 | 46 | start: function() { 47 | if (!this._running) { 48 | this._running = true; 49 | this.init(); 50 | this.next(); 51 | } 52 | }, 53 | 54 | /** 55 | * 检测开关、条件,生成待运行的子事件序列。 56 | */ 57 | init: function() { 58 | this.subEventSeq = []; 59 | //遍历事件页,优先级从高到底。 60 | for (let i = this.event.pages.length - 1; i >= 0; i--) { 61 | let page = this.event.pages[i]; 62 | //检查开关和条件,如果不满足,检查下一页 63 | if (!this.checkSwitcher(page.switcher)) continue; 64 | if (!this.checkCondition(page.condition)) continue; 65 | let subEvents = page.subEvents; 66 | for (let j = 0; j < subEvents.length; j++) { 67 | this.subEventSeq.push(subEvents[j]); 68 | } 69 | break; 70 | } 71 | if (!this.subEventSeq.length) { 72 | console.log('event sequence is empty') 73 | } 74 | }, 75 | 76 | /** 77 | * 逐条运行子事件序列。 78 | */ 79 | next: function() { 80 | if (this._stop) { 81 | this._running = false; 82 | this._stop = false; 83 | return; 84 | } 85 | if (!this.subEventSeq.length) { 86 | //事件运行完,调用回调函数 87 | if (this.callback) { 88 | if (typeof this.callback === 'function') { 89 | this.callback(); 90 | } else { 91 | //分支事件运行结束 92 | this.callback.setChild(null); 93 | this.callback.next(); 94 | } 95 | } 96 | if (this.loop) { 97 | if (this._repeatCount) { 98 | this._repeatCount--; 99 | setTimeout(function() { 100 | this._running = false; 101 | this.start(); 102 | }.bind(this), 0); 103 | } else { 104 | this._repeatCount = this.repeatCount; 105 | this._running = false; 106 | } 107 | } else { 108 | this._running = false; 109 | } 110 | return; 111 | } 112 | let subEvent = this.subEventSeq.shift(); 113 | this.preSubEvent = subEvent; 114 | this.handle.eventInterpreter(subEvent, this); 115 | }, 116 | 117 | checkSwitcher: function(switcher) { 118 | if (switcher == null) return true; 119 | for (let i = 0; i < switcher.length; i++) { 120 | if (!this.handle.checkSwitcher(switcher[i])) { 121 | return false; 122 | } 123 | } 124 | return true; 125 | }, 126 | 127 | checkCondition: function(conditions) { 128 | if (conditions == null) return true; 129 | for (let i = 0; i < conditions.length; i++) { 130 | if (!this.handle.conditionInterpreter(conditions[i], this)) { 131 | return false 132 | } 133 | } 134 | return true; 135 | }, 136 | 137 | startBySubEvent: function(subEvents, parentEvent) { 138 | if (parentEvent) { 139 | parentEvent.setChild(this); 140 | } 141 | this._running = true; 142 | //复制 143 | this.subEventSeq = subEvents.slice(); 144 | this.next(); 145 | }, 146 | 147 | setCallback: function(cb) { 148 | this.callback = cb; 149 | }, 150 | setTarget: function(target) { 151 | this.event.target = target; 152 | }, 153 | setChild: function(branchEvent) { 154 | if (branchEvent instanceof gameEvent || branchEvent == null) { 155 | this._child = branchEvent; 156 | } 157 | }, 158 | unshiftSubEvent: function(subEvent) { 159 | this.subEventSeq.unshift(subEvent); 160 | }, 161 | 162 | resume: function() { 163 | this._running = true; 164 | if (this._child && this._child instanceof gameEvent) { 165 | this._child.resume(); 166 | } else { 167 | this.next(); 168 | } 169 | }, 170 | 171 | stop: function() { 172 | this._running = false; 173 | if (this._child && (this._child instanceof gameEvent)) { 174 | this._child.stop(); 175 | } else { 176 | this._stop = true; 177 | } 178 | } 179 | 180 | }) 181 | 182 | module.exports = gameEvent; -------------------------------------------------------------------------------- /assets/scripts/core/system/TouchControl.js: -------------------------------------------------------------------------------- 1 | const RPG = require('Global'); 2 | 3 | const MoveState = RPG.MoveState; 4 | const DirectionState = RPG.Direction; 5 | 6 | const MoveType = cc.Enum({ 7 | FOUR_DIRECTION: -1, 8 | EIGHT_DIRECTION: 1 9 | }); 10 | 11 | cc.Class({ 12 | extends: cc.Component, 13 | 14 | properties: { 15 | controlNode: { 16 | default: null, 17 | type: cc.Node 18 | }, 19 | controlPanel: { 20 | default: null, 21 | type: cc.Node 22 | }, 23 | speed: 300, 24 | moveType: { 25 | default: MoveType.FOUR_DIRECTION, 26 | type: MoveType 27 | }, 28 | _listener: [] 29 | }, 30 | 31 | // use this for initialization 32 | onLoad: function() { 33 | //this.listener = []; 34 | var self = this; 35 | //cc.game.addPersistRootNode(this.node); 36 | self.maxRadius = self.controlPanel.getContentSize().height / 2; 37 | self.originPos = this.controlNode.position; 38 | self.moveToPos = cc.p(0, 0); 39 | self.isMoving = false; 40 | this.controlPanel.on(cc.Node.EventType.TOUCH_START, function(event) { 41 | var touchLoc = event.touch.getLocation(); 42 | self.isMoving = true; 43 | self.moveToPos = self.controlNode.parent.convertToNodeSpaceAR(touchLoc); 44 | }, this); 45 | 46 | this.controlPanel.on(cc.Node.EventType.TOUCH_MOVE, function(event) { 47 | var touchLoc = event.touch.getLocation(); 48 | self.isMoving = true; 49 | self.moveToPos = self.controlNode.parent.convertToNodeSpaceAR(touchLoc); 50 | }, this); 51 | 52 | this.controlPanel.on(cc.Node.EventType.TOUCH_END, function(event) { 53 | self.isMoving = false; 54 | }, this); 55 | 56 | this.controlPanel.on(cc.Node.EventType.TOUCH_CANCEL, function(event) { 57 | self.isMoving = false; 58 | 59 | }, this); 60 | }, 61 | 62 | // called every frame, uncomment this function to activate update callback 63 | update: function(dt) { 64 | if (this.isMoving) { 65 | this.isTouching = true; 66 | var oldPos = this.controlNode.position; 67 | this.actorDirection = cc.pNormalize(cc.pSub(this.moveToPos, this.originPos)) 68 | if (!cc.pFuzzyEqual(oldPos, this.moveToPos, 5)) //防止同一位置抖动,moveDirection计算导致 69 | { 70 | var moveDirection = cc.pNormalize(cc.pSub(this.moveToPos, oldPos)); 71 | var newPos = cc.pAdd(oldPos, cc.pMult(moveDirection, this.speed * dt)); 72 | if (cc.pDistance(newPos, this.originPos) > this.maxRadius) //处理边界的情况 73 | newPos = cc.pMult(this.actorDirection, this.maxRadius); 74 | this.controlNode.setPosition(newPos); 75 | } 76 | var angle = cc.pToAngle(this.actorDirection) 77 | var pi = 3.14; 78 | if ((this.moveType === MoveType.FOUR_DIRECTION && (pi / 4 <= angle && angle < 3 * pi / 4)) || 79 | (this.moveType === MoveType.EIGHT_DIRECTION && (3 * pi / 8 <= angle && angle < 5 * pi / 8))) { 80 | this.actorDirection = DirectionState.Up; 81 | this.moveState = MoveState.Up; 82 | } else if ((this.moveType === MoveType.FOUR_DIRECTION && (3 * pi / 4 <= angle || angle < (-3) * pi / 4)) || 83 | (this.moveType === MoveType.EIGHT_DIRECTION && (7 * pi / 8 <= angle || angle < (-7) * pi / 8))) { 84 | this.actorDirection = DirectionState.Left; 85 | this.moveState = MoveState.Left; 86 | } else if ((this.moveType === MoveType.FOUR_DIRECTION && ((-3) * pi / 4 <= angle && angle < pi / (-4))) || 87 | (this.moveType === MoveType.EIGHT_DIRECTION && ((-5) * pi / 8 <= angle && angle < 3 * pi / (-8)))) { 88 | this.actorDirection = DirectionState.Down; 89 | this.moveState = MoveState.Down; 90 | } else if ((this.moveType === MoveType.FOUR_DIRECTION && (-pi / 4 <= angle && angle < pi / 4)) || 91 | (this.moveType === MoveType.EIGHT_DIRECTION && (-pi / 8 <= angle && angle < pi / 8))) { 92 | this.actorDirection = DirectionState.Right; 93 | this.moveState = MoveState.Right; 94 | } else if (this.moveType === MoveType.EIGHT_DIRECTION && (pi / 8 <= angle && angle < 3 * pi / 8)) { 95 | this.actorDirection = DirectionState.RightUp; 96 | this.moveState = MoveState.RightUp; 97 | } else if (this.moveType === MoveType.EIGHT_DIRECTION && (5 * pi / 8 <= angle && angle < 7 * pi / 8)) { 98 | this.actorDirection = DirectionState.LeftUp; 99 | this.moveState = MoveState.LeftUp; 100 | } else if (this.moveType === MoveType.EIGHT_DIRECTION && ((-7) * pi / 8 <= angle && angle < (-5) * pi / 8)) { 101 | this.actorDirection = DirectionState.LeftDown; 102 | this.moveState = MoveState.LeftDown; 103 | } else if (this.moveType === MoveType.EIGHT_DIRECTION) { 104 | this.actorDirection = DirectionState.RightDown; 105 | this.moveState = MoveState.RightDown; 106 | } 107 | this.broadcast(); 108 | } else { 109 | this.controlNode.setPosition(this.originPos); 110 | this.moveState = MoveState.Stand; 111 | if (this.isTouching) { 112 | this.broadcast(); 113 | this.isTouching = false; 114 | } 115 | } 116 | }, 117 | 118 | addListener: function(comp) { 119 | this._listener.push(comp); 120 | }, 121 | 122 | broadcast: function() { 123 | for (let i = 0; i < this._listener.length; i++) { 124 | this._listener[i].emit('touch-control', { 125 | moveDirection: this.actorDirection, 126 | moveState: this.moveState 127 | }); 128 | } 129 | }, 130 | 131 | /** 132 | * 隐藏UI后控制复位。触摸中隐藏UI会导致系统还以为在触摸 133 | * 再次显示UI时,触摸是处于MOVE状态 134 | */ 135 | onDisable: function() { 136 | this.controlNode.setPosition(this.originPos); 137 | this.moveState = MoveState.Stand; 138 | this.isMoving = false; 139 | if (this.isTouching) { 140 | cc.find('Game').emit('TouchControl', { 141 | moveDirection: this.actorDirection, 142 | moveState: this.moveState 143 | }); 144 | this.isTouching = false; 145 | } 146 | } 147 | 148 | }); -------------------------------------------------------------------------------- /assets/scripts/core/Stealth/Stealth.js: -------------------------------------------------------------------------------- 1 | const RPG = require('Global'); 2 | const Direction = RPG.Direction; 3 | const GridPerStep = RPG.GridPerStep; 4 | const MoveStep = RPG.MoveStep; 5 | cc.Class({ 6 | extends: cc.Component, 7 | 8 | properties: { 9 | detectionRange: 1, 10 | spriteParentNode: { 11 | default: null, 12 | type: cc.Node, 13 | tooltip: "范围贴图的父节点。如果父节点就为该节点,务必不要设置,否则会出错。" 14 | }, 15 | realTime: { 16 | default: false, 17 | tooltip: "是否实时监测。否则通过事件控制,会存在一定延迟。" 18 | }, 19 | triggerEventId: { 20 | default: '', 21 | tooltip: "当角色被发现时,需要触发的事件ID。实时选项开启才有效。" 22 | } 23 | }, 24 | 25 | // use this for initialization 26 | onLoad: function() { 27 | this.gameNode = cc.find('Game'); 28 | this.game = this.gameNode.getComponent('Game'); 29 | this.cache = this.gameNode.getComponent('Cache'); 30 | this.eventManager = this.gameNode.getComponent('EventManager'); 31 | this.actor = this.node.getComponent("Actor"); 32 | this.rangeNode = new cc.Node("Range"); 33 | this.rangeNode.setAnchorPoint(0.5, 0); 34 | this.rangeNode.setPosition(16, 16); 35 | this.rangeNode.opacity = 110; 36 | 37 | let circleNode = new cc.Node('circle'); 38 | this.circleSprite = circleNode.addComponent(cc.Sprite); 39 | circleNode.parent = this.rangeNode; 40 | 41 | this.rangeNode.parent = this.spriteParentNode || this.node;; 42 | this.sprite = this.rangeNode.addComponent(cc.Sprite); 43 | }, 44 | 45 | onEnable: function() { 46 | this.rangeNode.active = true; 47 | }, 48 | 49 | start: function() { 50 | this.actor.stealth = this; 51 | this.direction = this.actor.direction; 52 | this.sprite.spriteFrame = this.cache.getSectorRangeSprite(this.detectionRange.toString()); 53 | this.circleSprite.spriteFrame = this.cache.getSectorRangeSprite("0"); 54 | this.setRangeDirection(this.direction); 55 | }, 56 | // called every frame, uncomment this function to activate update callback 57 | update: function(dt) { 58 | if (!this.game.loaded) return; 59 | this.setSpritePos(); 60 | if (this.direction != this.actor.direction) { 61 | this.direction = this.actor.direction; 62 | this.setRangeDirection(this.direction); 63 | } 64 | if (this.realTime) { 65 | if (this.inDetectionRange(this.actor.actorId, this.game.playerId, this.detectionRange)) { 66 | this.eventManager.eventStart(this.triggerEventId); 67 | } 68 | } 69 | }, 70 | 71 | //扇形 72 | inDetectionRange: function(selfId, targetId, range) { 73 | let self = this.game.scene.getActorTarget(selfId); 74 | let target = this.game.scene.getActorTarget(targetId); 75 | let deltaTilePos = cc.pSub(target.getRealTilePos(), self.getRealTilePos()); 76 | deltaTilePos.x = deltaTilePos.x / GridPerStep; 77 | deltaTilePos.y = deltaTilePos.y / GridPerStep; 78 | let flag = false; 79 | switch (self.direction) { 80 | case Direction.Down: 81 | if ((-deltaTilePos.y <= range) && (Math.abs(deltaTilePos.x) < -deltaTilePos.y)) flag = true; 82 | break; 83 | case Direction.Up: 84 | if ((deltaTilePos.y <= range) && (Math.abs(deltaTilePos.x) < deltaTilePos.y)) flag = true; 85 | break; 86 | case Direction.Left: 87 | if ((-deltaTilePos.x <= range) && (Math.abs(deltaTilePos.y) < -deltaTilePos.x)) flag = true; 88 | break; 89 | case Direction.Right: 90 | if ((deltaTilePos.x <= range) && (Math.abs(deltaTilePos.y) < deltaTilePos.x)) flag = true; 91 | break; 92 | } 93 | 94 | return this.isAround(self.direction, deltaTilePos) || flag; 95 | }, 96 | 97 | isAround: function(direction, deltaTilePos) { 98 | let flag = false; 99 | switch (direction) { 100 | case Direction.Down: 101 | if (Math.abs(deltaTilePos.x) === 1 && (deltaTilePos.y === 0 || deltaTilePos.y === -1)) flag = true; 102 | break; 103 | case Direction.Up: 104 | if (Math.abs(deltaTilePos.x) === 1 && (deltaTilePos.y === 0 || deltaTilePos.y === 1)) flag = true; 105 | break; 106 | case Direction.Left: 107 | if (Math.abs(deltaTilePos.y) === 1 && (deltaTilePos.x === 0 || deltaTilePos.x === -1)) flag = true; 108 | break; 109 | case Direction.Right: 110 | if (Math.abs(deltaTilePos.y) === 1 && (deltaTilePos.x === 0 || deltaTilePos.x === 1)) flag = true; 111 | break; 112 | } 113 | return flag; 114 | }, 115 | 116 | //检测玩家是否在背后 117 | checkBehind: function() { 118 | let selfPos = this.actor.getRealTilePos(); 119 | let playerPos = this.game.scene.getActorTarget(this.game.playerId).getRealTilePos(); 120 | let deltaTilePos = cc.pSub(playerPos, selfPos); 121 | deltaTilePos.x = deltaTilePos.x / GridPerStep; 122 | deltaTilePos.y = deltaTilePos.y / GridPerStep; 123 | let flag = false; 124 | switch (this.actor.direction) { 125 | case Direction.Down: 126 | if (deltaTilePos.x === 0 && deltaTilePos.y === 1) flag = true; 127 | break; 128 | case Direction.Up: 129 | if (deltaTilePos.x === 0 && deltaTilePos.y === -1) flag = true; 130 | break; 131 | case Direction.Left: 132 | if (deltaTilePos.x === 1 && deltaTilePos.y === 0) flag = true; 133 | break; 134 | case Direction.Right: 135 | if (deltaTilePos.x === -1 && deltaTilePos.y === 0) flag = true; 136 | break; 137 | } 138 | return flag; 139 | }, 140 | 141 | setRangeDirection: function(direction) { 142 | switch (direction) { 143 | case Direction.Up: 144 | this.rangeNode.rotation = 0; 145 | break; 146 | case Direction.Down: 147 | this.rangeNode.rotation = 180; 148 | break; 149 | case Direction.Left: 150 | this.rangeNode.rotation = 270; 151 | break; 152 | case Direction.Right: 153 | this.rangeNode.rotation = 90; 154 | break; 155 | } 156 | }, 157 | 158 | setSpritePos: function() { 159 | if (this.spriteParentNode) { 160 | this.rangeNode.setPosition(cc.pAdd(this.node.getPosition(), cc.p(MoveStep / 2, MoveStep / 2))) 161 | } 162 | }, 163 | 164 | onDisable: function() { 165 | this.rangeNode.active = false; 166 | } 167 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/WindowManager.js: -------------------------------------------------------------------------------- 1 | cc.Class({ 2 | extends: cc.Component, 3 | 4 | properties: { 5 | gameNode: { 6 | default: null, 7 | type: cc.Node 8 | }, 9 | dialogueBoxPrefab: cc.Prefab, 10 | shopWindowPrefab: cc.Prefab, 11 | itemMsgPrefab: cc.Prefab, 12 | messagePrefab: cc.Prefab, 13 | optionBoxPrefab: cc.Prefab, 14 | blackScreenPrefab: cc.Prefab, 15 | loadingPrefab: cc.Prefab, 16 | SystemWinPrefab: cc.Prefab, 17 | SaveWindowPrefab: cc.Prefab, 18 | BagWindowPrefab: cc.Prefab, 19 | QmessagePrefab: cc.Prefab 20 | }, 21 | 22 | // use this for initialization 23 | onLoad: function() { 24 | this.dialogueBoxPool = new cc.NodePool(); 25 | this.shopWindowPool = new cc.NodePool(); 26 | this.itemMsgPool = new cc.NodePool(); 27 | this.messagePool = new cc.NodePool(); 28 | this.optionPool = new cc.NodePool(); 29 | this.systemWinPool = new cc.NodePool(); 30 | this.saveWinPool = new cc.NodePool(); 31 | 32 | this.loadingPool = new cc.NodePool(); 33 | this.loadingNode = null; 34 | 35 | this.blackScreenPool = new cc.NodePool(); 36 | this.blackScreenPool.put(cc.instantiate(this.blackScreenPrefab)); 37 | this.blackScreenNode = null; 38 | }, 39 | 40 | showDialogueBox: function(dialogueMsg, actorTarget, cb) { 41 | //从对象池中取出空闲对象 42 | let dialogueNode = null; 43 | if (this.dialogueBoxPool.size() > 0) { 44 | dialogueNode = this.dialogueBoxPool.get(); 45 | } else { 46 | dialogueNode = cc.instantiate(this.dialogueBoxPrefab); 47 | } 48 | let dialogueComp = dialogueNode.getComponent("DialogueBox"); 49 | dialogueComp.gameNode = this.gameNode; 50 | dialogueComp.poolMng = this.dialogueBoxPool; 51 | this.gameNode.addChild(dialogueNode); 52 | dialogueComp.showMessage(dialogueMsg, actorTarget, cb); 53 | return dialogueComp; 54 | }, 55 | 56 | showShopWindow: function(itemIdList, actorTarget, cb) { 57 | let shopNode = null; 58 | if (this.shopWindowPool.size() > 0) { 59 | shopNode = this.shopWindowPool.get(); 60 | } else { 61 | shopNode = cc.instantiate(this.shopWindowPrefab); 62 | } 63 | let shopComp = shopNode.getComponent('Shop'); 64 | shopComp.gameNode = this.gameNode; 65 | shopComp.poolMng = this.shopWindowPool; 66 | this.gameNode.addChild(shopNode); 67 | shopComp.showShop(itemIdList, actorTarget, cb); 68 | }, 69 | 70 | showItemMsg: function(type, itemId, count, cb) { 71 | let itemMsgNode = null; 72 | if (this.itemMsgPool.size() > 0) { 73 | itemMsgNode = this.itemMsgPool.get(); 74 | } else { 75 | itemMsgNode = cc.instantiate(this.itemMsgPrefab); 76 | } 77 | let itemMsgComp = itemMsgNode.getComponent('ItemMsg'); 78 | itemMsgComp.gameNode = this.gameNode; 79 | itemMsgComp.poolMng = this.itemMsgPool; 80 | this.gameNode.addChild(itemMsgNode); 81 | itemMsgComp.showItemMsg(type, itemId, count, cb); 82 | }, 83 | 84 | showMessage: function(message, cb) { 85 | let messageNode = null; 86 | if (this.messagePool.size() > 0) { 87 | messageNode = this.messagePool.get(); 88 | } else { 89 | messageNode = cc.instantiate(this.messagePrefab); 90 | } 91 | let messageComp = messageNode.getComponent('MessageBox'); 92 | messageComp.gameNode = this.gameNode; 93 | messageComp.poolMng = this.messagePool; 94 | this.gameNode.addChild(messageNode); 95 | messageComp.showMessage(message, cb); 96 | }, 97 | 98 | showOption: function(message, target, options, cb) { 99 | let dialogueComp = this.showDialogueBox(message, target, null); 100 | let optionNode = null; 101 | if (this.optionPool.size() > 0) { 102 | optionNode = this.optionPool.get(); 103 | } else { 104 | optionNode = cc.instantiate(this.optionBoxPrefab); 105 | } 106 | let optionComp = optionNode.getComponent('OptionBox'); 107 | optionComp.gameNode = this.gameNode; 108 | optionComp.poolMng = this.optionPool; 109 | optionComp.dialogueComp = dialogueComp; 110 | this.gameNode.addChild(optionNode); 111 | optionComp.showOption(options, cb); 112 | }, 113 | 114 | showSystemWindow: function() { 115 | let systemNode = null; 116 | if (this.systemWinPool.size() > 0) { 117 | systemNode = this.systemWinPool.get(); 118 | } else { 119 | systemNode = cc.instantiate(this.SystemWinPrefab); 120 | } 121 | let systemComp = systemNode.getComponent('SystemWindow'); 122 | systemComp._poolMng = this.systemWinPool; 123 | this.gameNode.addChild(systemNode); 124 | }, 125 | 126 | showSaveWindow: function() { 127 | let saveNode = null; 128 | if (this.saveWinPool.size() > 0) { 129 | saveNode = this.saveWinPool.get(); 130 | } else { 131 | saveNode = cc.instantiate(this.SaveWindowPrefab); 132 | } 133 | let saveComp = saveNode.getComponent('SaveSystem'); 134 | saveComp._poolMng = this.saveWinPool; 135 | this.gameNode.addChild(saveNode); 136 | }, 137 | 138 | showBagWindow: function() { 139 | let bagNode = cc.instantiate(this.BagWindowPrefab); 140 | this.gameNode.addChild(bagNode); 141 | }, 142 | 143 | showQmessage: function(parentNode, message, cb) { 144 | let node = cc.instantiate(this.QmessagePrefab); 145 | let comp = node.getComponent('Qmessage'); 146 | comp.messageLabel.string = message; 147 | node.parent = parentNode; 148 | 149 | if (cb) cb(); 150 | }, 151 | 152 | /** 153 | * !#zh 154 | * 淡入或淡出黑屏,搭配使用,否则黑屏时不能恢复。持续时间为0可快速恢复 155 | * fade in 指的是游戏画面 156 | * 黑幕出现时,需要记录节点,用于消失 157 | * @param {Boolean} fadeIn 158 | * @param {GameEvent} cb 159 | */ 160 | fadeInOrOut: function(fadeIn, duration, cb) { 161 | if (!this.blackScreenNode) { 162 | if (this.blackScreenPool.size() > 0) { 163 | this.blackScreenNode = this.blackScreenPool.get(); 164 | } else { 165 | this.blackScreenNode = cc.instantiate(this.blackScreenPrefab); 166 | } 167 | this.gameNode.addChild(this.blackScreenNode); 168 | } 169 | //fade in 指的是游戏画面淡入 也就是黑幕淡出 170 | if (fadeIn) { 171 | this.blackScreenNode.runAction(cc.sequence( 172 | cc.fadeOut(duration), 173 | cc.callFunc(function() { 174 | this.blackScreenPool.put(this.blackScreenNode); 175 | this.blackScreenNode = null; 176 | if (cb) cb.next(); 177 | }, this), 178 | )); 179 | } else { 180 | this.blackScreenNode.runAction(cc.sequence( 181 | cc.fadeIn(duration), 182 | cc.callFunc(function() { if (cb) cb.next() }), 183 | )); 184 | } 185 | }, 186 | 187 | showLoading: function(show, cb) { 188 | if (show) { 189 | if (!this.loadingNode) { 190 | if (this.loadingPool.size() > 0) { 191 | this.loadingNode = this.loadingPool.get(); 192 | } else { 193 | this.loadingNode = cc.instantiate(this.loadingPrefab); 194 | } 195 | this.gameNode.addChild(this.loadingNode); 196 | } 197 | } else { 198 | if (this.loadingNode) { 199 | this.loadingPool.put(this.loadingNode); 200 | this.loadingNode = null; 201 | } 202 | } 203 | if (cb) cb.next(); 204 | } 205 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/PlayerData.js: -------------------------------------------------------------------------------- 1 | var PlayerAttribute = cc.Class({ 2 | //ctor: function () { 3 | //}, 4 | properties: { 5 | Lv: 1, 6 | Exp: 0, 7 | HP: 0, 8 | MP: 0, 9 | MaxHP: 0, 10 | MaxMP: 0, 11 | ATK: 0, 12 | DEF: 0, 13 | SPI: 0, 14 | AGI: 0, 15 | equipment: [] 16 | }, 17 | 18 | init: function() { 19 | this.Lv = 1; 20 | this.Exp = 0; 21 | this.HP = 200; 22 | this.MP = 100; 23 | this.MaxHP = 200; 24 | this.MaxMP = 100; 25 | this.ATK = 20; 26 | this.DEF = 10; 27 | this.SPI = 5; 28 | this.AGI = 5 29 | this.equipment = []; 30 | }, 31 | 32 | setAttributes: function(attributes) { 33 | this.Lv = attributes.Lv; 34 | this.Exp = attributes.Exp; 35 | this.HP = attributes.HP; 36 | this.MP = attributes.MP; 37 | this.MaxHP = attributes.MaxHP; 38 | this.MaxMP = attributes.MaxMP; 39 | this.ATK = attributes.ATK; 40 | this.DEF = attributes.DEF; 41 | this.SPI = attributes.SPI; 42 | this.AGI = attributes.AGI; 43 | }, 44 | 45 | getAttributes: function(sum) { 46 | if (sum) { 47 | var attributes = { 48 | Lv: this.Lv, 49 | Exp: this.Exp, 50 | HP: this.HP, 51 | MP: this.MP, 52 | MaxHP: this.MaxHP, 53 | MaxMP: this.MaxMP, 54 | ATK: this.getATK(), 55 | DEF: this.getDEF(), 56 | SPI: this.getSPI(), 57 | AGI: this.getAGI() 58 | } 59 | } else { 60 | var attributes = { 61 | Lv: this.Lv, 62 | Exp: this.Exp, 63 | HP: this.HP, 64 | MP: this.MP, 65 | MaxHP: this.MaxHP, 66 | MaxMP: this.MaxMP, 67 | ATK: this.ATK, 68 | DEF: this.DEF, 69 | SPI: this.SPI, 70 | AGI: this.AGI 71 | } 72 | } 73 | 74 | return attributes; 75 | }, 76 | 77 | getExp: function(point) { 78 | this.Exp += point; 79 | if (this.Exp > this.totalExp[this.Lv + 1]) { 80 | this.levelUp(); 81 | } 82 | }, 83 | 84 | levelUp: function() { 85 | 86 | }, 87 | 88 | /** 89 | * 负为补血 90 | */ 91 | loseHP: function(point) { 92 | this.HP -= point; 93 | if (this.HP <= 0) { 94 | this.death(); 95 | } 96 | if (this.HP > this.MaxHP) 97 | this.HP = this.MaxHP; 98 | }, 99 | 100 | loseMP: function(point) { 101 | this.MP -= point; 102 | if (this.MP <= 0) { 103 | this.MP = 0; 104 | } 105 | if (this.MP > this.MaxMP) 106 | this.MP = this.MaxMP; 107 | }, 108 | 109 | equip: function(equipment) { 110 | this.equipment[equipment.type - 1] = equipment; 111 | }, 112 | 113 | getEquipment: function(type) { 114 | if (type == null) 115 | return this.equipment 116 | else 117 | return this.equipment[type - 1] 118 | }, 119 | removeEquipment: function(type) { 120 | this.equipment[type - 1] = null; 121 | }, 122 | getATK: function() { 123 | var ATK = 0; 124 | for (var i = 0; i < this.equipment.length; i++) { 125 | if (this.equipment[i] != null) 126 | ATK += this.equipment[i].attribute.ATK; 127 | } 128 | ATK += this.ATK; 129 | return ATK; 130 | }, 131 | getDEF: function() { 132 | var DEF = 0; 133 | for (var i = 0; i < this.equipment.length; i++) { 134 | if (this.equipment[i] != null) 135 | DEF += this.equipment[i].attribute.DEF; 136 | } 137 | DEF += this.DEF; 138 | return DEF; 139 | }, 140 | getSPI: function() { 141 | var SPI = 0; 142 | for (var i = 0; i < this.equipment.length; i++) { 143 | if (this.equipment[i] != null) 144 | SPI += this.equipment[i].attribute.SPI; 145 | } 146 | SPI += this.SPI; 147 | return SPI; 148 | }, 149 | getAGI: function() { 150 | var AGI = 0; 151 | for (var i = 0; i < this.equipment.length; i++) { 152 | if (this.equipment[i] != null) 153 | AGI += this.equipment[i].attribute.AGI; 154 | } 155 | AGI += this.AGI; 156 | return AGI; 157 | } 158 | }) 159 | 160 | cc.Class({ 161 | extends: cc.Component, 162 | 163 | properties: { 164 | 165 | }, 166 | 167 | // use this for initialization 168 | onLoad: function() { 169 | /* 170 | var elsa = new PlayerAttribute(); 171 | var noah = new PlayerAttribute(); 172 | elsa.init(); 173 | noah.init(); 174 | elsa.equip({ 175 | "id": 100, 176 | "name": "铁制弯刀", 177 | "attribute": { 178 | "ATK": 3, 179 | "DEF": 0, 180 | "SPI": 0, 181 | "AGI": 0 182 | }, 183 | "price": 80, 184 | "description": "作为艾尔莎最趁手的武器,非弯刀莫属!", 185 | "type": 1 186 | }); 187 | elsa.equip({ 188 | "id": 104, 189 | "name": "长袍", 190 | "attribute": { 191 | "ATK": 0, 192 | "DEF": 5, 193 | "SPI": 0, 194 | "AGI": 0 195 | }, 196 | "price": 90, 197 | "description": "到处都可以找到的普通长袍。", 198 | "type": 3 199 | }); 200 | this.player = { 201 | "1": elsa, 202 | "2": noah 203 | }; 204 | */ 205 | this.money = 100; 206 | /* 207 | item = { 208 | "1": { 209 | id: 1, 210 | count: 3 211 | } 212 | "3": { 213 | id:3, 214 | count:1 215 | } 216 | } 217 | */ 218 | this.items = {}; 219 | 220 | this.taskList = []; 221 | }, 222 | 223 | getMoney: function() { 224 | return this.money; 225 | }, 226 | setMoneyTo: function(money) { 227 | this.money = money; 228 | }, 229 | setMoneyBy: function(amount) { 230 | this.money = this.money + amount; 231 | }, 232 | 233 | getItems: function() { 234 | return this.items; 235 | }, 236 | getItemCount: function(itemId) { 237 | if (itemId.toString() in this.items) 238 | return this.items[itemId.toString()].count; 239 | else 240 | return 0; 241 | }, 242 | addItem: function(itemId, num) { 243 | if (itemId.toString() in this.items) 244 | this.items[itemId.toString()].count += num; 245 | else 246 | this.items[itemId.toString()] = { 247 | "id": itemId, 248 | "count": num 249 | } 250 | }, 251 | removeItem: function(itemId, num) { 252 | var itemIdS = itemId.toString(); 253 | if (itemIdS in this.items) { 254 | if (this.items[itemIdS].count > num) 255 | this.items[itemId.toString()].count -= num; 256 | else if (this.items[itemIdS].count == num) 257 | delete this.items[itemIdS]; 258 | else 259 | cc.log("item count less than num"); 260 | } else 261 | cc.log("does not have this item"); 262 | }, 263 | checkItem: function(itemId) { 264 | if (itemId.toString() in this.items) 265 | return this.items[itemId.toString()].count; 266 | else 267 | return 0; 268 | } 269 | 270 | // called every frame, uncomment this function to activate update callback 271 | // update: function (dt) { 272 | 273 | // }, 274 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/SaveSystem.js: -------------------------------------------------------------------------------- 1 | var emptyFunc = function(event) { 2 | event.stopPropagation(); 3 | }; 4 | 5 | cc.Class({ 6 | extends: cc.Component, 7 | 8 | properties: { 9 | gameNode: cc.Node, 10 | newSaveNode: cc.Node, 11 | saveListContent: cc.Node, 12 | saveItemPrefab: cc.Prefab, 13 | infoLabel: cc.Label, 14 | _poolMng: null 15 | }, 16 | 17 | // use this for initialization 18 | onLoad: function() { 19 | this.gameNode = this.gameNode || cc.find('Game'); 20 | this.game = this.gameNode.getComponent("Game"); 21 | this.eventManager = this.gameNode.getComponent("EventManager"); 22 | this.playerData = this.gameNode.getComponent("PlayerData"); 23 | this.audioManager = this.gameNode.getComponent("AudioManager"); 24 | this.preSelect = { target: null, index: null }; 25 | this.currentSelect = { target: null, index: null }; 26 | this.targetList = []; 27 | this.saveList = []; 28 | this.infoLabel.string = ""; 29 | //this.createSaveList(this.saveList); 30 | }, 31 | 32 | onEnable: function() { 33 | this.node.on('touchstart', emptyFunc, this); 34 | this.showSaveBox(); 35 | }, 36 | 37 | showSaveBox: function() { 38 | //this.node.active = true; 39 | var saveList = this.readSaveList(); 40 | this.createSaveList(saveList); 41 | this.saveList = saveList; 42 | }, 43 | 44 | readSaveList: function() { 45 | /* 46 | var saveList = []; 47 | for (var i = 0; i < this.saveList.length; i++) { 48 | saveList[i] = this.saveList[i]; 49 | } 50 | return saveList; 51 | */ 52 | var saveList = cc.sys.localStorage.getItem("SaveList"); 53 | if (saveList == null) { 54 | cc.log("no save"); 55 | return []; 56 | } 57 | return JSON.parse(saveList) 58 | }, 59 | 60 | createSaveList: function(saveList) { 61 | var saveItem; 62 | //新的在上面 63 | for (var i = saveList.length - 1; i >= 0; i--) { 64 | saveItem = this.createSaveItem(i, saveList[i]); 65 | this.targetList.unshift(saveItem); 66 | this.saveListContent.addChild(saveItem.node, -i); 67 | } 68 | //新存档选项在最顶上。 69 | this.newSaveNode.setLocalZOrder(-saveList.length); 70 | }, 71 | 72 | createSaveItem: function(index, info) { 73 | var saveItemNode; 74 | var saveItem; 75 | saveItemNode = cc.instantiate(this.saveItemPrefab); 76 | saveItem = saveItemNode.getComponent("SaveItem"); 77 | saveItem.saveSystem = this; 78 | saveItem.index = index; 79 | saveItem.itemName = "存档 " + ((index + 1 < 10) ? "0" + (index + 1) : index + 1); 80 | 81 | //显示存档信息 82 | var saveDate = new Date(info); 83 | var timeLabel = saveDate.getFullYear() + '年' + (saveDate.getMonth() + 1) + '月' + saveDate.getDate() + ' ' + saveDate.getHours() + ":" + saveDate.getMinutes() + ":" + saveDate.getSeconds(); 84 | saveItem.info = timeLabel; 85 | return saveItem; 86 | }, 87 | 88 | updateSaveList: function(saveList) { 89 | //添加新的 90 | for (var i = this.targetList.length; i < saveList.length; i++) { 91 | var saveItem = this.createSaveItem(i, saveList[i]); 92 | this.targetList.push(saveItem); 93 | this.saveListContent.addChild(saveItem.node, -i); 94 | } 95 | this.newSaveNode.setLocalZOrder(-saveList.length); 96 | }, 97 | 98 | clearSaveList: function() { 99 | var listChildren = this.saveListContent.children; 100 | //新建存档的按钮不能删除 101 | for (var i = 1; i < listChildren.length; i++) { 102 | listChildren[i].destroy(); 103 | } 104 | }, 105 | 106 | selectSaveItem: function(target, index, info) { 107 | this.preSelect = this.currentSelect; 108 | if (this.preSelect.target != null) 109 | if (this.preSelect.index != index) 110 | this.preSelect.target.setNormal(); 111 | this.currentSelect.target = target; 112 | this.currentSelect.index = index; 113 | this.infoLabel.string = info; 114 | }, 115 | 116 | newSave: function() { 117 | if (this.game.currentMapId === "0") return; 118 | var nowDate = new Date(); 119 | //var time = nowDate.getHours() + ":" + nowDate.getMinutes() + ":" + nowDate.getSeconds() + "." + nowDate.getMilliseconds(); 120 | //time 相当于存档信息。可以为object。 121 | var time = nowDate.getTime(); 122 | this.saveList.push(time) 123 | this.updateSaveList(this.saveList); 124 | var saveData = this.game.saveGame(); 125 | cc.log("Save" + (this.saveList.length - 1)); 126 | cc.sys.localStorage.setItem("Save" + (this.saveList.length - 1), JSON.stringify(saveData)); 127 | }, 128 | 129 | quickSave: function() { 130 | this.game = this.gameNode.getComponent("Game"); 131 | if (this.game.currentMapId === "0") return; 132 | var nowDate = new Date(); 133 | //var time = nowDate.getHours() + ":" + nowDate.getMinutes() + ":" + nowDate.getSeconds() + "." + nowDate.getMilliseconds(); 134 | var time = nowDate.getTime(); 135 | var saveList = this.readSaveList(); 136 | var saveData = this.game.saveGame(); 137 | saveList.push(time); 138 | cc.sys.localStorage.setItem("Save" + (saveList.length - 1), JSON.stringify(saveData)); 139 | cc.sys.localStorage.setItem('SaveList', JSON.stringify(saveList)); 140 | }, 141 | 142 | loadSave: function() { 143 | cc.log("Save" + this.currentSelect.index) 144 | var saveData = cc.sys.localStorage.getItem("Save" + this.currentSelect.index); 145 | if (saveData == null) { 146 | cc.log("load save error"); 147 | return; 148 | } 149 | this.node.active = false; 150 | this.loadGame(JSON.parse(saveData)); 151 | }, 152 | 153 | close: function() { 154 | this._poolMng.put(this.node); 155 | }, 156 | 157 | deleteSave: function() { 158 | if (this.currentSelect.index == null) return; 159 | cc.sys.localStorage.removeItem("Save" + this.currentSelect.index) 160 | this.saveList[this.currentSelect.index] = "None"; 161 | this.targetList[this.currentSelect.index].info = "None"; 162 | this.infoLabel.string = "None"; 163 | }, 164 | 165 | override: function() { 166 | //开始界面没有覆盖 167 | if (this.game.currentMapId === "0") return; 168 | var saveData = this.game.saveGame(); 169 | cc.sys.localStorage.setItem("Save" + this.currentSelect.index, JSON.stringify(saveData)); 170 | var nowDate = new Date(); 171 | var timeLabel = nowDate.getFullYear() + '年' + (nowDate.getMonth() + 1) + '月' + nowDate.getDate() + ' ' + nowDate.getHours() + ":" + nowDate.getMinutes() + ":" + nowDate.getSeconds(); 172 | this.saveList[this.currentSelect.index] = nowDate.getTime(); 173 | this.targetList[this.currentSelect.index].info = timeLabel; 174 | this.infoLabel.string = timeLabel; 175 | }, 176 | 177 | loadGame: function(saveData) { 178 | this.game.loadGame(saveData); 179 | }, 180 | 181 | onDisable: function() { 182 | this.node.off('touchstart', emptyFunc, this); 183 | this.preSelect = { target: null, index: null }; 184 | this.currentSelect = { target: null, index: null }; 185 | this.targetList = []; 186 | this.infoLabel.string = ""; 187 | for (var i = this.saveList.length - 1; i >= 0; i--) { 188 | if (this.saveList[i] !== "None") { 189 | break; 190 | } 191 | this.saveList.pop(); 192 | cc.sys.localStorage.removeItem("Save" + i) 193 | } 194 | //保存存档列表 195 | cc.sys.localStorage.setItem('SaveList', JSON.stringify(this.saveList)); 196 | this.clearSaveList(); 197 | } 198 | 199 | }); -------------------------------------------------------------------------------- /assets/scripts/core/UI/Shop.js: -------------------------------------------------------------------------------- 1 | var isEmptyObject = function(obj) { 2 | for (var key in obj) { 3 | return false; 4 | } 5 | return true; 6 | }; 7 | 8 | var emptyFunc = function(event) { 9 | event.stopPropagation(); 10 | }; 11 | 12 | cc.Class({ 13 | extends: cc.Component, 14 | 15 | properties: { 16 | description: { 17 | default: null, 18 | type: cc.Label 19 | }, 20 | 21 | money: { 22 | default: null, 23 | type: cc.Label 24 | }, 25 | itemPrefab: { 26 | default: null, 27 | type: cc.Prefab 28 | }, 29 | itemContent: { 30 | default: null, 31 | type: cc.Node 32 | }, 33 | buyButton: { 34 | default: null, 35 | type: cc.Node 36 | }, 37 | saleButton: { 38 | default: null, 39 | type: cc.Node 40 | }, 41 | countNode: { 42 | default: null, 43 | type: cc.Node 44 | }, 45 | countLabel: { 46 | default: null, 47 | type: cc.Label 48 | }, 49 | mask: { 50 | default: null, 51 | type: cc.Node 52 | }, 53 | confirmBox: { 54 | default: null, 55 | type: cc.Node 56 | }, 57 | gameNode: { 58 | default: null, 59 | type: cc.Node 60 | }, 61 | poolMng: null 62 | }, 63 | 64 | // use this for initialization 65 | onLoad: function() { 66 | var self = this; 67 | this.gameNode = this.gameNode || cc.find('Game'); 68 | this.game = this.gameNode.getComponent("Game"); 69 | this.playerData = this.gameNode.getComponent("PlayerData"); 70 | this.eventManager = this.gameNode.getComponent("EventManager"); 71 | this.cache = this.gameNode.getComponent("Cache"); 72 | 73 | this.preItem = null; 74 | this.currentItem = null; 75 | //点击次数 76 | this.touchTimes = 0; 77 | //所有的物品列表 78 | this.itemTable = {}; 79 | //可买物品列表 80 | this.itemList = []; 81 | 82 | this.node.on("itemEvent", function(event) { 83 | 84 | switch (event.detail.state) { 85 | case 1: 86 | event.detail.self.setPressed(); 87 | break; 88 | case 2: 89 | this.preItem = this.currentItem; 90 | this.currentItem = event.detail.self; 91 | this.description.string = this.currentItem.itemInfo.description; 92 | this.countLabel.string = this.playerData.checkItem(this.currentItem.id); 93 | if (this.preItem != null) { 94 | if (this.currentItem.id == this.preItem.id) { 95 | this.touchTimes++; 96 | } else { 97 | this.preItem.setNormal(); 98 | this.touchTimes = 1; 99 | } 100 | } else 101 | this.touchTimes = 1; 102 | if (this.touchTimes == 2) { 103 | this.mask.active = true; 104 | //cc.find("debug").getComponent(cc.Label).string = "confirm box"; 105 | this.confirmBox.getComponent("ConfirmBox").showItem( 106 | this.currentItem.id, 107 | this.currentItem.icon.spriteFrame, 108 | this.currentItem.itemInfo.name, 109 | this.currentItem.itemInfo.price, 110 | this.isBuy); 111 | this.touchTimes = 0; 112 | } 113 | //cc.log(this.touchTimes); 114 | //this.currentItem.setNormal(); 115 | break; 116 | case 3: 117 | if (this.touchTimes == 0 || 118 | (this.touchTimes == 1 && event.detail.self.id != this.currentItem.id)) 119 | event.detail.self.setNormal(); 120 | //this.touchTimes = 0; 121 | break; 122 | } 123 | }, this) 124 | 125 | this.node.on("buyconfirm", function(event) { 126 | //cc.find("debug").getComponent(cc.Label).string = "confirm"; 127 | if (this.isBuy) { 128 | if (this.playerData.getMoney() >= event.detail.totalPrice) { 129 | this.playerData.addItem(this.currentItem.id, event.detail.num); 130 | this.playerData.setMoneyBy(-(event.detail.totalPrice)) 131 | } 132 | } else { 133 | if (this.playerData.getItemCount(this.currentItem.id) >= event.detail.num) { 134 | this.playerData.removeItem(this.currentItem.id, event.detail.num); 135 | this.playerData.setMoneyBy(event.detail.totalPrice); 136 | 137 | } 138 | } 139 | this.money.string = this.playerData.getMoney() + " G"; 140 | this.countLabel.string = this.playerData.getItemCount(this.currentItem.id); 141 | //cc.log(this.playerData.getMoney()); 142 | //cc.log(this.playerData.items); 143 | //cc.find("debug").getComponent(cc.Label).string = "confirm over"; 144 | }, this) 145 | }, 146 | 147 | showShop: function(itemIdList, actorTarget, cb) { 148 | var self = this; 149 | 150 | this.game.hideUI(['default'], true, false); 151 | this.actor = actorTarget; 152 | if (this.actor != undefined) { 153 | this.actor.facePlayer(); 154 | } 155 | this.itemIdList = itemIdList; 156 | this.money.string = this.playerData.getMoney() + " G"; 157 | //读取道具列表 158 | if (isEmptyObject(this.itemTable)) { 159 | var fileName = "Global/Item"; 160 | cc.loader.loadRes(fileName, function(err, jsonData) { 161 | if (err) { 162 | cc.log(fileName, 'read error'); 163 | return; 164 | } 165 | cc.log("load item table"); 166 | self.itemTable = jsonData; 167 | self.itemList = []; //清空列表 168 | for (var i = 0; i < self.itemIdList.length; i++) { 169 | self.itemList[i] = jsonData[self.itemIdList[i].toString()]; 170 | } 171 | cc.loader.releaseRes(fileName); 172 | }); 173 | } else { 174 | self.itemList = []; //清空列表 175 | for (var i = 0; i < self.itemIdList.length; i++) { 176 | self.itemList[i] = self.itemTable[self.itemIdList[i].toString()]; 177 | } 178 | } 179 | 180 | this.cb = cb; 181 | }, 182 | 183 | buy: function() { 184 | this.isBuy = true; 185 | this.description.string = ""; 186 | this.preItem = null; 187 | this.currentItem = null; 188 | if (this.itemContent.children.length) { 189 | this.cleanItemList() 190 | } 191 | for (var i = 0; i < this.itemList.length; i++) { 192 | this.createItem(this.itemList[i]); 193 | } 194 | if (!this.saleButton.getComponent(cc.Button).interactable) 195 | this.saleButton.getComponent(cc.Button).interactable = true; 196 | this.buyButton.getComponent(cc.Button).interactable = false; 197 | this.countNode.active = true; 198 | this.countLabel.string = ""; 199 | }, 200 | 201 | sale: function() { 202 | this.isBuy = false; 203 | this.description.string = ""; 204 | this.preItem = null; 205 | this.currentItem = null; 206 | var items = this.playerData.getItems(); 207 | var itemList = []; 208 | var i = 0; 209 | for (var key in items) { 210 | itemList[i] = this.itemTable[items[key].id]; 211 | i++; 212 | } 213 | if (this.itemContent.children.length) { 214 | this.cleanItemList() 215 | } 216 | for (var i = 0; i < itemList.length; i++) { 217 | this.createItem(itemList[i]); 218 | } 219 | if (!this.buyButton.getComponent(cc.Button).interactable) 220 | this.buyButton.getComponent(cc.Button).interactable = true; 221 | this.saleButton.getComponent(cc.Button).interactable = false; 222 | this.countNode.active = true; 223 | this.countLabel.string = ""; 224 | }, 225 | 226 | cancel: function() { 227 | this.cleanItemList(); 228 | this.description.string = ""; 229 | this.buyButton.getComponent(cc.Button).interactable = true; 230 | this.saleButton.getComponent(cc.Button).interactable = true; 231 | 232 | this.countNode.active = false; 233 | this.game.hideUI(['default'], false, false); 234 | this.poolMng.put(this.node); 235 | if (this.actor != undefined) 236 | this.actor.faceDefault(); 237 | if (this.cb) this.cb.next(); 238 | }, 239 | 240 | createItem: function(itemObj) { 241 | var itemNode = cc.instantiate(this.itemPrefab); 242 | var item = itemNode.getComponent('ShopItem'); 243 | 244 | item.id = itemObj.id; 245 | item.itemName.string = itemObj.name; 246 | 247 | item.icon.spriteFrame = this.cache.getItemSprite(item.id.toString()) 248 | if (this.isBuy) 249 | item.price.string = itemObj.price + "G"; 250 | else 251 | item.price.string = (Math.round(itemObj.price * 0.6)) + "G"; 252 | //itemComp.description = itemObj.description; 253 | //itemComp.descriptionLabel = this.description; 254 | item.shop = this; 255 | this.itemContent.addChild(itemNode); //加了Layout 256 | item.itemInfo = itemObj; 257 | }, 258 | 259 | cleanItemList: function() { 260 | var itemListChildren = this.itemContent.children; 261 | for (var i = 0; i < itemListChildren.lenght; i++) { 262 | itemListChildren[i].destroy(); 263 | } 264 | this.itemContent.removeAllChildren(true); 265 | //this.information.active = false; 266 | //this.description.string = ""; 267 | }, 268 | 269 | // called every frame, uncomment this function to activate update callback 270 | // update: function (dt) { 271 | 272 | // }, 273 | }); -------------------------------------------------------------------------------- /assets/scripts/core/AStar/AStar.js: -------------------------------------------------------------------------------- 1 | var AStarStep = require('AStarStep'); 2 | var AStarMoveType = require('AStarMoveType'); 3 | 4 | cc.Class({ 5 | extends: cc.Component, 6 | 7 | properties: { 8 | barrierLayerName: 'block', 9 | moveType: { 10 | default: AStarMoveType.FOUR_DIRECTION, 11 | type: AStarMoveType 12 | } 13 | }, 14 | 15 | editor: { 16 | requireComponent: cc.TiledMap 17 | }, 18 | 19 | onLoad: function () { 20 | this._open = []; 21 | this._closed = []; 22 | }, 23 | 24 | start: function () { 25 | this._tiledMap = this.node.getComponent("cc.TiledMap"); 26 | this._layerBarrier = this._tiledMap.getLayer(this.barrierLayerName); 27 | this.layerSize = this._layerBarrier.getLayerSize(); 28 | }, 29 | 30 | /** 31 | * !#zh 32 | * 返回检测点在列表中的位置,不存在返回-1 33 | * @returns {Number} 34 | */ 35 | _indexOfStepArray: function (checkPoint, stepArray) { 36 | for (let i = 0; i < stepArray.length; ++i) { 37 | if (checkPoint.equals(stepArray[i].position)) { 38 | return i; 39 | } 40 | } 41 | return -1; 42 | }, 43 | 44 | /** 45 | * !#zh 46 | * 方格数据加入到open list,F从小到大排序 47 | * @param {Object} nextStep 48 | */ 49 | _insertToOpen: function (nextStep) { 50 | let stepF = nextStep.f; 51 | let length = this._open.length; 52 | let i = 0; 53 | for (; i < length; ++i) { 54 | if (stepF <= this._open[i].f) { 55 | break; 56 | } 57 | } 58 | // insert to index i 59 | //open中,F从小往大排 60 | this._open.splice(i, 0, nextStep); 61 | }, 62 | 63 | /** 64 | * !#zh 65 | * 搜索路径 66 | * @param {Object} start Tile坐标 67 | * @param {Object} finish Tile坐标 68 | * @param {Boolean} ignoreBarrier 忽略终点的障碍,用于敌人向玩家寻路使用 69 | * @returns {Array} paths 从起到到终点的路径 70 | */ 71 | moveToward: function (start, finish) { 72 | this._closed = []; 73 | this._open = []; 74 | let paths = []; 75 | //如果目的地为不可行走区域,直接结束 76 | 77 | let tileGid = this._layerBarrier.getTileGIDAt(finish); 78 | if (tileGid) { 79 | let tileProperties = this._tiledMap.getPropertiesForGID(tileGid); 80 | if (tileProperties['isBlock']) { 81 | return paths; 82 | } 83 | } 84 | // cc.log('find start: ' + start + ' to: ' + finish); 85 | this._open.push(new AStarStep(start)); 86 | let pathFound = false; 87 | do { 88 | // cc.log('=============================================================='); 89 | let currentStep = this._open.shift(); 90 | // cc.log('currentStep: ' + currentStep); 91 | 92 | this._closed.push(currentStep); 93 | 94 | if (currentStep.position.equals(finish)) { 95 | // cc.log('finish :P'); 96 | pathFound = true; 97 | let tmpStep = currentStep; 98 | do { 99 | paths.unshift(tmpStep.position); 100 | tmpStep = tmpStep.parent; 101 | } while (tmpStep !== null); 102 | 103 | this._open = []; 104 | this._closed = []; 105 | break; 106 | } 107 | 108 | let borderPositions = this._borderMovablePoints(currentStep.position); 109 | 110 | for (let i = 0; i < borderPositions.length; ++i) { 111 | let borderPosition = borderPositions[i]; 112 | //cc.log('check: ' + borderPosition); 113 | // Check if the nextStep isn't already in the closed set 114 | if (this._indexOfStepArray(borderPosition, this._closed) != -1) { 115 | // cc.log('had in closed: ' + borderPosition); 116 | // cc.log('remove check position: ' + borderPosition); 117 | borderPositions.splice(i, 1); 118 | i--; 119 | continue; 120 | } 121 | 122 | let nextStep = new AStarStep(borderPosition); 123 | let moveCost = this._costToMove(borderPosition, finish) 124 | let index = this._indexOfStepArray(borderPosition, this._open); 125 | 126 | if (index == -1) { 127 | //当前check点不在open中,添加父节点,计算g,h,添加到open中 128 | nextStep.parent = currentStep; 129 | nextStep.g = currentStep.g + moveCost; 130 | let distancePoint = borderPosition.sub(finish); 131 | nextStep.h = Math.abs(distancePoint.x) + Math.abs(distancePoint.y); 132 | this._insertToOpen(nextStep); 133 | } else { 134 | //检测点在open中 135 | //cc.log('had in open: ' + nextStep.toString()); 136 | nextStep = this._open[index]; 137 | if (currentStep.g + moveCost < nextStep.g) { 138 | //cc.log('re insert into open: ' + nextStep.toString()); 139 | nextStep.g = currentStep.g + moveCost; 140 | nextStep.parent = currentStep; 141 | // re insert 142 | this._open.splice(index, 1); 143 | this._insertToOpen(nextStep); 144 | } 145 | } 146 | } 147 | } while (this._open.length > 0); 148 | 149 | cc.log("paths:", paths); 150 | return paths; 151 | }, 152 | 153 | _costToMove(positionLeft, positionRight) { 154 | //用于8方向,暂时没用 155 | //if (this.moveType == AStarMoveType.EIGHT_DIRECTION) { 156 | /** 157 | * diagonal length: 1.41 ≈ Math.sqrt(x * x + y * y) 158 | * line length: 1 159 | * 160 | * cost = length * 10 161 | * diagonal cost = 14 ≈ 14.1 162 | * cost line = 10 = 1 * 10 163 | */ 164 | // return (positionLeft.x != positionRight.x) && (positionLeft.y != positionRight.y) ? 14 : 10; 165 | //} else { 166 | return 1; 167 | // } 168 | }, 169 | 170 | _borderMovablePoints: function (position) { 171 | var results = []; 172 | let hasTop = false; 173 | let hasBottom = false; 174 | let hasLeft = false; 175 | let hasRight = false; 176 | let tileGid; 177 | // top 178 | let top = cc.p(position.x, position.y - 2); 179 | if (top.y >= 0) { 180 | tileGid = this._layerBarrier.getTileGIDAt(top); 181 | if (tileGid === 0) { 182 | // cc.log('top: ' + top); 183 | results.push(top); 184 | hasTop = true; 185 | } 186 | else { 187 | if (!this._tiledMap.getPropertiesForGID(tileGid).isBlock) { 188 | // cc.log('top: ' + top); 189 | results.push(top); 190 | hasTop = true; 191 | } 192 | } 193 | } 194 | // bottom 195 | let bottom = cc.p(position.x, position.y + 2); 196 | if (bottom.y < this.layerSize.height) { 197 | tileGid = this._layerBarrier.getTileGIDAt(bottom); 198 | if (tileGid === 0) { 199 | // cc.log('bottom: ' + bottom); 200 | results.push(bottom); 201 | hasBottom = true; 202 | } 203 | else { 204 | if (!this._tiledMap.getPropertiesForGID(tileGid).isBlock) { 205 | // cc.log('bottom: ' + bottom); 206 | results.push(bottom); 207 | hasBottom = true; 208 | } 209 | } 210 | } 211 | // left 212 | let left = cc.p(position.x - 2, position.y); 213 | if (left.x >= 0) { 214 | tileGid = this._layerBarrier.getTileGIDAt(left); 215 | if (tileGid === 0) { 216 | // cc.log('left: ' + left); 217 | results.push(left); 218 | hasLeft = true; 219 | } 220 | else { 221 | if (!this._tiledMap.getPropertiesForGID(tileGid).isBlock) { 222 | // cc.log('left: ' + left); 223 | results.push(left); 224 | hasLeft = true; 225 | } 226 | } 227 | } 228 | // right 229 | let right = cc.p(position.x + 2, position.y); 230 | if (right.x < this.layerSize.width) { 231 | tileGid = this._layerBarrier.getTileGIDAt(right); 232 | if (tileGid === 0) { 233 | // cc.log('right: ' + right); 234 | results.push(right); 235 | hasRight = true; 236 | } 237 | else { 238 | if (!this._tiledMap.getPropertiesForGID(tileGid).isBlock) { 239 | // cc.log('right: ' + right); 240 | results.push(right); 241 | hasRight = true; 242 | } 243 | } 244 | } 245 | /* //8方向 246 | if (this.moveType == AStarMoveType.EIGHT_DIRECTION) { 247 | // Top Left 248 | let topLeft = cc.p(position.x - 2, position.y - 2); 249 | if (hasTop && hasLeft) { 250 | if (this._layerBarrier.getTileGIDAt(topLeft) === 0) { 251 | // cc.log('top left: ' + topLeft); 252 | results.push(topLeft); 253 | } 254 | } 255 | // Top Right 256 | let topRight = cc.p(position.x + 2, position.y - 2); 257 | if (hasTop && hasRight) { 258 | if (this._layerBarrier.getTileGIDAt(topRight) === 0) { 259 | // cc.log('top right: ' + topRight); 260 | results.push(topRight); 261 | } 262 | } 263 | // Bottom Left 264 | let bottomLeft = cc.p(position.x - 2, position.y + 2); 265 | if (hasBottom && hasLeft) { 266 | if (this._layerBarrier.getTileGIDAt(bottomLeft) === 0) { 267 | // cc.log('bttom left: ' + bottomLeft); 268 | results.push(bottomLeft); 269 | } 270 | } 271 | // Bottom Right 272 | let bottomRight = cc.p(position.x + 2, position.y + 2); 273 | if (hasBottom && hasRight) { 274 | if (this._layerBarrier.getTileGIDAt(bottomRight) === 0) { 275 | // cc.log('top right: ' + bottomRight); 276 | results.push(bottomRight); 277 | } 278 | } 279 | }*/ 280 | return results; 281 | } 282 | }); 283 | -------------------------------------------------------------------------------- /assets/scripts/core/system/Game.js: -------------------------------------------------------------------------------- 1 | var RPG = require("Global"); 2 | var MoveState = RPG.MoveState; 3 | var Direction = RPG.Direction; 4 | var MoveStep = RPG.MoveStep; 5 | var MoveTime = RPG.MoveTime; 6 | var MapList = RPG.MapList; 7 | const TouchControl = RPG.TouchControl; 8 | cc.Class({ 9 | extends: cc.Component, 10 | 11 | properties: { 12 | 13 | gameMenuNode: cc.Node, 14 | 15 | }, 16 | 17 | // use this for initialization 18 | onLoad: function() { 19 | var self = this; 20 | //Game节点设置为常驻节点 21 | cc.game.addPersistRootNode(this.node); 22 | 23 | //锁定UI标志 24 | this.lockUIFlag = false; 25 | this.loadingFlag = false; 26 | 27 | //镜头自动跟随开关,事件中移动镜头需要先关闭。 28 | this.cameraFollowFlag = true; 29 | 30 | this.loaded = false; 31 | //当前正在控制的角色ID,默认为ID = 1 32 | this.playerId = 1; 33 | this.prePlayerId = 1; 34 | //可控角色列表 35 | this.playerList = []; 36 | //移动方向 37 | this.moveState = MoveState.Stand; 38 | 39 | //玩家朝向 40 | this.playerDirection = Direction.Down; 41 | 42 | //上一个地图和当前地图ID 43 | this.previousMapId = this.currentMapId = "0"; 44 | //当然控制角色的ID,通过ActorManager来获取实例 45 | this.currentActorId = 1; 46 | 47 | this.eventManager = this.node.getComponent('EventManager'); 48 | this.audioManager = this.node.getComponent('AudioManager'); 49 | this.playerData = this.node.getComponent('PlayerData'); 50 | this.cache = this.node.getComponent('Cache'); 51 | this.windowManager = this.getComponent('WindowManager'); 52 | this.groupList = this.node.getComponentInChildren('GroupList'); 53 | this.groupList.init(); 54 | this.gameMenu = this.gameMenuNode.getComponent("GameMenu"); 55 | //this.hud = cc.find("Game/Hud").getComponent("Hud"); 56 | 57 | //与地图相关的信息 58 | this.mapInfo = {}; 59 | //动态角色 60 | this.dynamicActorList = []; 61 | 62 | this.treasureList = []; 63 | 64 | //cc.audioEngine.play(cc.url.raw('/resources/Audio/LuoRiYuGe.mp3'), false, 1); 65 | //注册键盘事件,方便电脑调试 66 | cc.eventManager.addListener({ 67 | event: cc.EventListener.KEYBOARD, 68 | onKeyPressed: function(keyCode, event) { 69 | switch (keyCode) { 70 | case cc.KEY.a: 71 | self.moveState = MoveState.Left; 72 | self.playerDirection = Direction.Left; 73 | self.keyA = true; 74 | break; 75 | case cc.KEY.d: 76 | self.moveState = MoveState.Right; 77 | self.playerDirection = Direction.Right; 78 | self.keyD = true; 79 | break; 80 | case cc.KEY.w: 81 | self.moveState = MoveState.Up; 82 | self.playerDirection = Direction.Up; 83 | self.keyW = true; 84 | break; 85 | case cc.KEY.s: 86 | self.moveState = MoveState.Down; 87 | self.playerDirection = Direction.Down; 88 | self.keyS = true; 89 | break; 90 | case cc.KEY.shift: 91 | self.acc = true; 92 | break; 93 | default: 94 | self.moveState = MoveState.Stand; 95 | break; 96 | } 97 | self.player.playerMove(self.moveState); 98 | //cc.log(self.moveState); 99 | }, 100 | onKeyReleased: function(keyCode, event) { 101 | switch (keyCode) { 102 | case cc.KEY.a: 103 | self.keyA = false; 104 | break; 105 | case cc.KEY.d: 106 | self.keyD = false; 107 | break; 108 | case cc.KEY.w: 109 | self.keyW = false; 110 | break; 111 | case cc.KEY.s: 112 | self.keyS = false; 113 | break; 114 | case cc.KEY.shift: 115 | self.acc = false; 116 | break; 117 | } 118 | if (!(self.keyA || self.keyD || self.keyW || self.keyS)) { 119 | //self.moveStop(); 120 | //this.isKeyBoard = false; 121 | self.moveState = MoveState.Stand; 122 | } 123 | //cc.log(self.moveState); 124 | } 125 | }, self.node) 126 | 127 | //监控触摸事件,与键盘同时控制 128 | this.node.on('TouchControl', function(event) { 129 | this.moveState = event.detail.moveState; 130 | this.playerDirection = event.detail.moveDirection; 131 | }, this) 132 | 133 | //初始化与地图相关的属性,并运行初始事件 134 | //所有脚本的start()结束后会被触发 135 | this.node.on('scene-init-done', function(event) { 136 | this.scene = event.detail.scene; 137 | 138 | //获取控制角色对象 139 | this.player = this.scene.getActorTarget(this.playerId); 140 | this.player.setPlayerPos(this.loadPos, this.loadDirection); 141 | 142 | //优先使用上一个地图正在控制的角色。如果必要,可以通过事件控制切换为其他角色。 143 | if (this.prePlayerId != this.playerId) { 144 | let i; 145 | for (i = 0; i < this.scene.map.playerList.length; i++) { 146 | if (this.prePlayerId == this.scene.map.playerList[i]) { 147 | break; 148 | } 149 | } 150 | if (i != this.scene.map.playerList.length) { 151 | this.switchPlayer(this.prePlayerId, null); 152 | } 153 | } 154 | 155 | this.currentMapId = this.scene.map.mapId; 156 | //设置动态角色状态 *在scene中设置 157 | for (let i = 0; i < this.dynamicActorList.length; i++) { 158 | let actorTarget = this.scene.getActorTarget(this.dynamicActorList[i].actorId); 159 | actorTarget.setPos(this.dynamicActorList[i].pos, this.dynamicActorList[i].direction); 160 | actorTarget.node.active = this.dynamicActorList[i].active; 161 | } 162 | //保证阻挡区域不会被误移除 163 | for (let i = 0; i < this.dynamicActorList.length; i++) { 164 | let actorTarget = this.scene.getActorTarget(this.dynamicActorList[i].actorId); 165 | actorTarget.setPos(actorTarget.getPos()); 166 | } 167 | this.hideUI(['default'], false, false); 168 | 169 | this.groupList.initList(); 170 | 171 | //读存档才会发生 172 | if (this.loadingFlag) { 173 | this.windowManager.showLoading(false, null); 174 | this.loadingFlag = false; 175 | } 176 | //检测是否有初始事件 177 | if (this.eventManager.checkEventById(this.currentMapId, 0)) { 178 | this.eventManager.eventStart(this.currentMapId); 179 | } 180 | this.loaded = true; 181 | }, this) 182 | }, 183 | 184 | start: function() { 185 | let TouchControl = cc.find('Game/TouchPanel').getComponent('TouchControl') 186 | TouchControl.addListener(this.node); 187 | 188 | this.node.on('touch-control', function(event) { 189 | this.moveState = event.detail.moveState; 190 | this.playerDirection = event.detail.moveDirection; 191 | this.player.playerMove(this.moveState); 192 | }, this) 193 | }, 194 | 195 | switchPlayer: function(actorId, cb) { 196 | if (this.player.isMoving()) return; 197 | //当前控制角色 198 | this.playerId = actorId; 199 | let prePlayer = this.player; 200 | this.player = this.scene.getActorTarget(actorId); 201 | let pos = prePlayer.getPos(); 202 | 203 | this.player.setPos(pos, prePlayer.direction); 204 | prePlayer.node.active = false; 205 | this.player.node.active = true; 206 | if (cb) cb.next(); 207 | }, 208 | /** 209 | * 添加/删除任务。只用于显示,与系统无任何交互 210 | * @param {Number} index 211 | * @param {Object} info 212 | * @param {Boolean} add 213 | */ 214 | addTask: function(index, info, add) { 215 | if (add) { 216 | this.playerData.taskList.splice(index, 0, info); 217 | } else 218 | this.playerData.taskList.splice(index, 1); 219 | this.eventManager.nextEventStart(); 220 | }, 221 | 222 | /** 223 | * !#zh 224 | * 隐藏UI 225 | * @param {[String]} nodeName 226 | * @param {Boolean} hide 227 | * @param {Boolean} nextEvent 228 | */ 229 | hideUI: function(nodeList, hide, cb) { 230 | //如果UI被锁定,那么该函数不生效 231 | if (this.lockUIFlag) return; 232 | 233 | let NodeMap = RPG.NodeMap; 234 | let node; 235 | for (let i = 0; i < nodeList.length; i++) { 236 | let nodeName = NodeMap[nodeList[i].toString()]; 237 | if (nodeName instanceof Array) { 238 | for (let j = 0; j < nodeName.length; j++) { 239 | node = this.node.getChildByName(nodeName[j]); 240 | node && (node.active = !hide); 241 | } 242 | } else { 243 | node = this.node.getChildByName(NodeMap[nodeList[i].toString()]); 244 | node && (node.active = !hide); 245 | } 246 | } 247 | if (cb) cb.next(); 248 | }, 249 | 250 | /** 251 | * 用于锁定UI,启用时,不能改变UI显示或隐藏状态 252 | */ 253 | lockUI: function(lock, cb) { 254 | this.lockUIFlag = lock; 255 | if (cb) cb.next(); 256 | }, 257 | 258 | /** 259 | * !#zh 260 | * 播放动画 261 | * @param {String} clipName 262 | * @param {Boolean} wait 263 | * @param {GameEvent} cb 264 | */ 265 | playMapAnimation: function(clipName, wait, cb) { 266 | var mapAnimation = this.scene.map.node.getComponent(cc.Animation); 267 | if (mapAnimation == null) return; 268 | var clip; 269 | var clips = mapAnimation.getClips(); 270 | for (let i = 0; i < clips.length; i++) { 271 | if (clips[i].name === clipName) { 272 | clip = clips[i]; 273 | break; 274 | } 275 | } 276 | if (clip == null) return; 277 | if (wait) { 278 | clip.events.push({ frame: clip.duration, func: "callFunc", params: [function() { if (cb) cb.next() }] }); 279 | mapAnimation.play(clipName); 280 | } else { 281 | mapAnimation.play(clipName); 282 | if (cb) cb.next(); 283 | } 284 | }, 285 | 286 | /** 287 | * !#zh 288 | * 播放音效 289 | * @param {String} effectName 音效名 290 | * @param {Number} type 291 | * @param {Boolean} nextEvent 292 | */ 293 | playAudioEffect: function(effectName, type, nextEvent) { 294 | this.audioManager.playEffect(effectName, type, nextEvent); 295 | }, 296 | 297 | /** 298 | * !#zh 299 | * 开门动画,含音效 300 | * @param {Object} doorPos 门的坐标 301 | * @param {Number} firstGid 门左下角的GID 302 | * @param (Boolean) nextEvent 303 | */ 304 | openDoor: function(doorPos, firstGid, nextEvent) { 305 | this.scene.map.openDoor(doorPos, firstGid, nextEvent); 306 | }, 307 | 308 | /** 309 | * !#zh 310 | * 延迟,以秒为单位 311 | * @param {Number} second 312 | * @param {GameEvent} cb 313 | */ 314 | delaySecond: function(second, cb) { 315 | this.node.runAction(cc.sequence( 316 | cc.delayTime(second), 317 | cc.callFunc(function() { if (cb) cb.next() }) 318 | )); 319 | }, 320 | 321 | /** 322 | * !#zh 323 | * 存档 324 | */ 325 | saveGame: function() { 326 | //角色数据 327 | var player = {}; 328 | /* 329 | for (var key in this.playerData.player) { 330 | player[key] = {}; 331 | player[key].attributes = this.playerData.player[key].getAttributes(); 332 | player[key].equipment = this.playerData.player[key].getEquipment(); 333 | }; 334 | */ 335 | //更新地图信息 336 | this.saveMapInfo(); 337 | var mapData = { 338 | currentMapId: this.currentMapId, 339 | mapInfo: this.mapInfo 340 | }; 341 | var eventData = { 342 | eventSwitcher: this.eventManager.eventSwitcher, 343 | //eventDone: this.eventManager.eventDone 344 | }; 345 | var playerData = { 346 | money: this.playerData.money, 347 | items: this.playerData.items, 348 | currentPlayerId: this.playerId, 349 | player: player, 350 | playerPos: this.player.getPos(), 351 | playerDirection: this.player.direction, 352 | //taskList: this.playerData.taskList 353 | }; 354 | 355 | var systemData = { 356 | musicVolume: this.audioManager.getMusicVolume(), 357 | effectVolume: this.audioManager.getEffectVolume() 358 | }; 359 | 360 | var saveData = { 361 | mapData: mapData, 362 | eventData: eventData, 363 | playerData: playerData, 364 | systemData: systemData 365 | }; 366 | cc.log("saveData:", saveData); 367 | //cc.sys.localStorage.setItem('save', JSON.stringify(saveData)); 368 | return saveData; 369 | }, 370 | 371 | loadGame: function(saveData) { 372 | var mapData = saveData.mapData; 373 | var eventData = saveData.eventData; 374 | var playerData = saveData.playerData; 375 | var systemData = saveData.systemData; 376 | 377 | this.eventManager.eventSwitcher = eventData.eventSwitcher; 378 | //this.eventManager.eventDone = eventData.eventDone; 379 | this.playerData.money = playerData.money; 380 | this.playerData.items = playerData.items; 381 | 382 | this.audioManager.setMusicVolume(systemData.musicVolume); 383 | this.audioManager.setEffectVolume(systemData.effectVolume); 384 | 385 | this.mapInfo = mapData.mapInfo; 386 | 387 | var mapId = mapData.currentMapId; 388 | var currentPlayerId = playerData.currentPlayerId; 389 | this.playerId = currentPlayerId; 390 | var playerPos = playerData.playerPos; 391 | var playerDirection = playerData.playerDirection; 392 | 393 | //停止播放当前音乐 394 | this.audioManager.stopAll(); 395 | //显示loading过渡 396 | this.windowManager.showLoading(true, null); 397 | this.loadingFlag = true; 398 | if (this.gameMenu._isShown) { 399 | this.gameMenu.hide(); 400 | } 401 | 402 | setTimeout( 403 | () => { this.switchScene(mapId, "1", playerPos, playerDirection, true) }, 404 | 2000); 405 | }, 406 | 407 | /** 408 | * !#zh 409 | * 切换地图 410 | * @param {String} destMapId 411 | * @param {Number} playerId 412 | * @param {Object} destPos 413 | * @param {Number} direction 414 | */ 415 | switchScene: function(destMapId, playerId, destPos, direction, load) { 416 | this.loaded = false; 417 | 418 | //如果不是读档,则存储当前地图信息 419 | if (!load) { 420 | this.saveMapInfo(); 421 | } 422 | 423 | this.loadMapInfo(destMapId); 424 | 425 | this.prePlayerId = this.playerId; 426 | this.playerId = playerId; 427 | this.loadPos = destPos; 428 | this.loadDirection = direction; 429 | 430 | //释放动态加载的资源 431 | //this.cache.releaseRes(); 432 | this.eventManager.clearEvent(); 433 | //清除音乐列表 434 | this.audioManager.clearMusicList(); 435 | 436 | //hideUI; 437 | this.hideUI(['default'], true, false); 438 | if (this.gameMenu._isShown) { 439 | this.gameMenu.hide(); 440 | } 441 | cc.director.loadScene(MapList[destMapId]); 442 | }, 443 | 444 | saveMapInfo: function() { 445 | let dynamicActorList = []; 446 | //存储角色状态,位置 447 | for (let i = 0; i < this.scene.dynamicActorList.length; i++) { 448 | dynamicActorList[i] = { 449 | actorId: this.scene.dynamicActorList[i].actorId, 450 | active: this.scene.dynamicActorList[i].node.active, 451 | pos: this.scene.dynamicActorList[i].getPos(), 452 | direction: this.scene.dynamicActorList[i].direction 453 | } 454 | } 455 | this.mapInfo[this.currentMapId] = { 456 | mapId: this.currentMapId, 457 | dynamicActorList: dynamicActorList, 458 | } 459 | 460 | }, 461 | loadMapInfo: function(mapId) { 462 | //用于初始化 463 | if (this.mapInfo[mapId]) { 464 | this.dynamicActorList = this.mapInfo[mapId].dynamicActorList; 465 | } else { 466 | this.dynamicActorList = [] 467 | } 468 | } 469 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/Map.js: -------------------------------------------------------------------------------- 1 | const RPG = require('Global'); 2 | const MoveStep = RPG.MoveStep; 3 | const Direction = RPG.Direction; 4 | const MoveTime = RPG.MoveTime; 5 | const MapPara = RPG.MapPara; 6 | cc.Class({ 7 | extends: cc.Component, 8 | 9 | properties: { 10 | mapId: '', 11 | battle: false, 12 | playerList: { 13 | default: [], 14 | type: cc.String 15 | } 16 | }, 17 | 18 | // use this for initialization 19 | onLoad: function() { 20 | this._aStar = this.node.getComponent("AStar") 21 | this.gameNode = cc.find("Game"); 22 | this.game = this.gameNode.getComponent("Game"); 23 | this.eventManager = this.gameNode.getComponent("EventManager"); 24 | this.actorManager = this.gameNode.getComponent("ActorManager"); 25 | 26 | this._tiledMap = this.node.getComponent('cc.TiledMap'); 27 | //地图尺寸 单位为tile 28 | this.mapTileSize = this._tiledMap.getMapSize(); 29 | //每个tile的尺寸 30 | this.tileSize = this._tiledMap.getTileSize(); 31 | //地图尺寸 单位为像素 32 | this.mapSize = cc.size(this.mapTileSize.width * this.tileSize.width, this.mapTileSize.height * this.tileSize.height); 33 | 34 | //暂时取巧做法,为了动态生成不可行走区域 35 | this._blockLayer = this._tiledMap.getLayer('block'); 36 | //手机获取不了gid 37 | //依然有问题 38 | //this.blockTileGid = this._blockLayer.getTileSet().firstGid; 39 | this.blockTileGid = MapPara[this.mapId].BlockTileGid; 40 | 41 | this.initMap(); 42 | 43 | /* 44 | let floor = this._tiledMap.getLayer('floor'); 45 | console.log(floor) 46 | let texture = floor.getTexture(); 47 | console.log(texture); 48 | texture.setAliasTexParameters(); 49 | */ 50 | }, 51 | /** 52 | * 计算地图移动的边界量 53 | */ 54 | initMap: function() { 55 | var halfWidth = cc.visibleRect.width / 2; 56 | var halfHeight = cc.visibleRect.height / 2; 57 | var mapInitPos = new cc.Vec2(); 58 | 59 | //如果地图大小小于窗口大小,地图居中显示 60 | //如果地图大小大于窗口大小,显示地图左下角(需要通过设定玩家位置调整) 61 | //地图锚点在左下角,窗口锚点在中心 62 | if (this.mapSize.width < cc.visibleRect.width) 63 | mapInitPos.x = -this.mapSize.width / 2 64 | else 65 | mapInitPos.x = -cc.visibleRect.width / 2; 66 | 67 | if (this.mapSize.height < cc.visibleRect.height) 68 | mapInitPos.y = -this.mapSize.height / 2 69 | else 70 | mapInitPos.y = -cc.visibleRect.height / 2; 71 | 72 | this.node.setPosition(mapInitPos); 73 | 74 | //地图大小与窗口大小不相等,但非常接近(<32pixel),会导致limit相等 75 | //不处理的话,有黑边时画面会左右移动(移动地图中已判断处理) 76 | //将相对于窗口锚点的数据转换为相对于地图锚点的数据 77 | this.leftLimit = Math.floor(halfWidth / MoveStep) * MoveStep; 78 | this.rightLimit = Math.floor((this.mapSize.width - halfWidth) / MoveStep) * MoveStep; 79 | this.bottomLimit = Math.floor(halfHeight / MoveStep) * MoveStep; 80 | this.topLimit = Math.floor((this.mapSize.height - halfHeight) / MoveStep) * MoveStep; 81 | 82 | //地图只能在以下范围内移动,不能超出这个范围,否者会有黑边出现 83 | this.boundary = {}; 84 | this.boundary.horizontalMax = 0 - cc.visibleRect.width / 2; 85 | this.boundary.horizontalMin = -(this.mapSize.width - cc.visibleRect.width / 2); 86 | this.boundary.verticalMax = 0 - cc.visibleRect.height / 2; 87 | this.boundary.verticalMin = -(this.mapSize.height - cc.visibleRect.height / 2); 88 | 89 | //this.loading.active = false; 90 | cc.log('map initial successfully'); 91 | }, 92 | 93 | /** 94 | * 根据玩家位置设定地图位置,尽量保证玩家在画面中央 95 | */ 96 | setMapPos: function(destPos) { 97 | //如果地图大小小于窗口大小,地图居中显示 98 | if (this.mapSize.width < cc.visibleRect.width) { 99 | this.node.x = -this.mapSize.width / 2 100 | } else { 101 | this.node.x = -cc.visibleRect.width / 2 - (destPos.x - this.leftLimit); 102 | if (this.node.x < -(this.mapSize.width - cc.visibleRect.width / 2)) 103 | this.node.x = -(this.mapSize.width - cc.visibleRect.width / 2); 104 | else if (this.node.x > -cc.visibleRect.width / 2) 105 | this.node.x = -cc.visibleRect.width / 2; 106 | } 107 | if (this.mapSize.height < cc.visibleRect.height) { 108 | this.node.y = -this.mapSize.height / 2 109 | } else { 110 | this.node.y = -cc.visibleRect.height / 2 - (destPos.y - this.bottomLimit); 111 | if (this.node.y < -(this.mapSize.height - cc.visibleRect.height / 2)) 112 | this.node.y = -(this.mapSize.height - cc.visibleRect.height / 2); 113 | else if (this.node.y > -cc.visibleRect.height / 2) 114 | this.node.y = -cc.visibleRect.height / 2; 115 | } 116 | }, 117 | 118 | moveMap: function(direction, destPos, speed) { 119 | speed = speed || 1; 120 | //direction指的是玩家移动的方向,地图移动方向与其相反 121 | switch (direction) { 122 | case Direction.Down: 123 | if ((destPos.y >= this.bottomLimit - MoveStep) && 124 | (destPos.y < this.topLimit) &&   125 | (this.bottomLimit != this.topLimit)) { 126 | if (Math.round(this.node.y + MoveStep) > this.boundary.verticalMax) { 127 | var delta = Math.round(this.boundary.verticalMax - this.node.y); 128 | //未完成的动作不会停止?导致之前地图移动未完成又叠加新的偏移,导致会出现黑边,所以先停止之前的动作 129 | this.node.stopAllActions(); 130 | this.node.runAction(cc.moveBy(MoveTime / speed * delta / MoveStep, 0, delta)); 131 | } else 132 | this.node.runAction(cc.moveBy(MoveTime / speed, 0, MoveStep)); 133 | } 134 | break; 135 | case Direction.Up: 136 | if ((destPos.y > this.bottomLimit) && 137 | (destPos.y <= this.topLimit + MoveStep) &&   138 | (this.bottomLimit != this.topLimit)) { 139 | if (Math.round(this.node.y - MoveStep) < this.boundary.verticalMin) { 140 | var delta = Math.round(this.node.y - this.boundary.verticalMin); 141 | //未完成的动作不会停止?导致之前地图移动未完成又叠加新的偏移,导致会出现黑边,所以先停止之前的动作 142 | this.node.stopAllActions(); 143 | this.node.runAction(cc.moveBy(MoveTime / speed * delta / MoveStep, 0, -delta)); 144 | } else 145 | this.node.runAction(cc.moveBy(MoveTime / speed, 0, -MoveStep)); 146 | } 147 | break; 148 | case Direction.Left: 149 | if ((destPos.x >= this.leftLimit - MoveStep) && 150 | (destPos.x < this.rightLimit) && 151 | (this.leftLimit != this.rightLimit)) { 152 | if (Math.round(this.node.x + MoveStep) > this.boundary.horizontalMax) { 153 | var delta = Math.round(this.boundary.horizontalMax - this.node.x); 154 | this.node.stopAllActions(); 155 | this.node.runAction(cc.moveBy(MoveTime / speed * delta / MoveStep, delta, 0)); 156 | } else 157 | this.node.runAction(cc.moveBy(MoveTime / speed, MoveStep, 0)); 158 | } 159 | break; 160 | case Direction.Right: 161 | if ((destPos.x > this.leftLimit) && 162 | (destPos.x <= this.rightLimit + MoveStep) && 163 | (this.leftLimit != this.rightLimit)) { 164 | if (Math.round(this.node.x - MoveStep) < this.boundary.horizontalMin) { 165 | var delta = Math.round(this.node.x - this.boundary.horizontalMin); 166 | this.node.stopAllActions(); 167 | this.node.runAction(cc.moveBy(MoveTime / speed * delta / MoveStep, -delta, 0)); 168 | } else 169 | this.node.runAction(cc.moveBy(MoveTime / speed, -MoveStep, 0)); 170 | } 171 | break; 172 | case Direction.RightUp: 173 | if ((destPos.y > this.bottomLimit) && 174 | (destPos.y <= this.topLimit + MoveStep) &&   175 | (this.bottomLimit != this.topLimit)) { 176 | if (Math.round(this.node.y - MoveStep) < this.boundary.verticalMin) { 177 | var deltaY = Math.round(this.node.y - this.boundary.verticalMin); 178 | } else { 179 | var deltaY = MoveStep; 180 | } 181 | } else { 182 | var deltaY = 0; 183 | } 184 | if ((destPos.x > this.leftLimit) && 185 | (destPos.x <= this.rightLimit + MoveStep) && 186 | (this.leftLimit != this.rightLimit)) { 187 | if (Math.round(this.node.x - MoveStep) < this.boundary.horizontalMin) { 188 | var deltaX = Math.round(this.node.x - this.boundary.horizontalMin); 189 | } else { 190 | var deltaX = MoveStep; 191 | } 192 | } else { 193 | var deltaX = 0; 194 | } 195 | if (deltaX || deltaY) { 196 | this.node.stopAllActions(); 197 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaX / MoveStep, -deltaX, 0)); 198 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaY / MoveStep, 0, -deltaY)); 199 | } 200 | break; 201 | case Direction.LeftUp: 202 | if ((destPos.y > this.bottomLimit) && 203 | (destPos.y <= this.topLimit + MoveStep) &&   204 | (this.bottomLimit != this.topLimit)) { 205 | if (Math.round(this.node.y - MoveStep) < this.boundary.verticalMin) { 206 | var deltaY = Math.round(this.node.y - this.boundary.verticalMin); 207 | } else { 208 | var deltaY = MoveStep; 209 | } 210 | } else { 211 | var deltaY = 0; 212 | } 213 | if ((destPos.x >= this.leftLimit - MoveStep) && 214 | (destPos.x < this.rightLimit) && 215 | (this.leftLimit != this.rightLimit)) { 216 | if (Math.round(this.node.x + MoveStep) > this.boundary.horizontalMax) { 217 | var deltaX = Math.round(this.boundary.horizontalMax - this.node.x); 218 | } else { 219 | var deltaX = MoveStep; 220 | } 221 | } else { 222 | var deltaX = 0; 223 | } 224 | if (deltaX || deltaY) { 225 | this.node.stopAllActions(); 226 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaX / MoveStep, deltaX, 0)); 227 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaY / MoveStep, 0, -deltaY)); 228 | } 229 | break; 230 | case Direction.RightDown: 231 | if ((destPos.x > this.leftLimit) && 232 | (destPos.x <= this.rightLimit + MoveStep) && 233 | (this.leftLimit != this.rightLimit)) { 234 | if (Math.round(this.node.x - MoveStep) < this.boundary.horizontalMin) { 235 | var deltaX = Math.round(this.node.x - this.boundary.horizontalMin); 236 | } else { 237 | var deltaX = MoveStep; 238 | } 239 | } else { 240 | var deltaX = 0; 241 | } 242 | if ((destPos.y >= this.bottomLimit - MoveStep) && 243 | (destPos.y < this.topLimit) &&   244 | (this.bottomLimit != this.topLimit)) { 245 | if (Math.round(this.node.y + MoveStep) > this.boundary.verticalMax) { 246 | var deltaY = Math.round(this.boundary.verticalMax - this.node.y); 247 | } else { 248 | var deltaY = MoveStep; 249 | } 250 | } else { 251 | var deltaY = 0; 252 | } 253 | if (deltaX || deltaY) { 254 | this.node.stopAllActions(); 255 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaX / MoveStep, -deltaX, 0)); 256 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaY / MoveStep, 0, deltaY)); 257 | } 258 | break; 259 | case Direction.LeftDown: 260 | if ((destPos.x >= this.leftLimit - MoveStep) && 261 | (destPos.x < this.rightLimit) && 262 | (this.leftLimit != this.rightLimit)) { 263 | if (Math.round(this.node.x + MoveStep) > this.boundary.horizontalMax) { 264 | var deltaX = Math.round(this.boundary.horizontalMax - this.node.x); 265 | } else { 266 | var deltaX = MoveStep; 267 | } 268 | } else { 269 | var deltaX = 0; 270 | } 271 | if ((destPos.y >= this.bottomLimit - MoveStep) && 272 | (destPos.y < this.topLimit) &&   273 | (this.bottomLimit != this.topLimit)) { 274 | if (Math.round(this.node.y + MoveStep) > this.boundary.verticalMax) { 275 | var deltaY = Math.round(this.boundary.verticalMax - this.node.y); 276 | } else { 277 | var deltaY = MoveStep; 278 | } 279 | } else { 280 | var deltaY = 0; 281 | } 282 | if (deltaX || deltaY) { 283 | this.node.stopAllActions(); 284 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaX / MoveStep, deltaX, 0)); 285 | this.node.runAction(cc.moveBy(MoveTime / speed * deltaY / MoveStep, 0, deltaY)); 286 | } 287 | break; 288 | } 289 | }, 290 | 291 | /** 292 | * !#zh 293 | * 移动镜头,可以滚动或瞬时 294 | * @method mapCamera 295 | * @param {cc.p} centerPos 296 | * @param {Boolean} scroll 297 | * @param {Number} speed 298 | * @param {Boolean} cb 299 | */ 300 | mapCamera: function(centerPos, scroll, speed, cb) { 301 | if (speed == null) 302 | speed = 1; 303 | cc.log("mapcamera center", centerPos.x, centerPos.y); 304 | 305 | //因为不能出现黑边,实际的目的坐标与设定坐标不一定一致 306 | 307 | //计算实际目的坐标 308 | var newPos = new cc.p(); 309 | newPos.x = -cc.visibleRect.width / 2 - (centerPos.x - this.leftLimit); 310 | if (newPos.x < -(this.mapSize.width - cc.visibleRect.width / 2)) 311 | newPos.x = -(this.mapSize.width - cc.visibleRect.width / 2); 312 | else if (newPos.x > -cc.visibleRect.width / 2) 313 | newPos.x = -cc.visibleRect.width / 2; 314 | 315 | 316 | newPos.y = -cc.visibleRect.height / 2 - (centerPos.y - this.bottomLimit); 317 | if (newPos.y < -(this.mapSize.height - cc.visibleRect.height / 2)) 318 | newPos.y = -(this.mapSize.height - cc.visibleRect.height / 2); 319 | else if (newPos.y > -cc.visibleRect.height / 2) 320 | newPos.y = -cc.visibleRect.height / 2; 321 | 322 | cc.log("mapcamera", newPos.x, newPos.y); 323 | //step用于计算移动时间,取X、Y之中最长的时间,最小是一格 324 | var mapCurrentPos = this.node.getPosition(); 325 | var stepX = Math.round(Math.abs(newPos.x - mapCurrentPos.x) / MoveStep); 326 | var stepY = Math.round(Math.abs(newPos.y - mapCurrentPos.y) / MoveStep); 327 | if (stepX > stepY) 328 | var step = stepX; 329 | else 330 | var step = stepY; 331 | 332 | cc.log("map step", step); 333 | step = (step == 0) ? 1 : step; 334 | 335 | if (scroll) { 336 | this.node.runAction(cc.sequence(cc.moveTo(MoveTime * step / speed, newPos.x, newPos.y), 337 | cc.delayTime(0.2), 338 | cc.callFunc(function() { if (cb) cb.next() }))) 339 | } else { 340 | this.node.setPosition(newPos); 341 | if (cb) cb.next(); 342 | } 343 | }, 344 | 345 | /** 346 | * !#zh 347 | * 将像素坐标转换为Tile坐标。注意像素坐标原点在左下角,而Tile坐标在左上角 348 | * @param {Object} posInPixel 349 | * @return {Object} Tile坐标 350 | */ 351 | _getTilePos: function(posInPixel) { 352 | //var mapSize = this.node.getContentSize(); 353 | var x = Math.round(posInPixel.x / this.tileSize.width); 354 | var y = Math.round(posInPixel.y / this.tileSize.height); 355 | y = this.mapTileSize.height - y - 1; //坐标系不同,需要转换 356 | return cc.p(x, y); 357 | }, 358 | 359 | 360 | /** 361 | * !#zh 362 | * 检测是否可移动至坐标位置 363 | * @param {Object} posInPixel 364 | * @return {Boolean} 365 | */ 366 | tryToMove: function(posInPixel) { 367 | var posInTile = this._getTilePos(posInPixel); 368 | if (posInTile.x >= 0 && posInTile.x < this.mapTileSize.width && posInTile.y >= 0 && posInTile.y < this.mapTileSize.height) { 369 | var tileGid = this._blockLayer.getTileGIDAt(posInTile); 370 | //cc.log(tileGid); 371 | if (tileGid) { 372 | var tileProperties = this._tiledMap.getPropertiesForGID(tileGid); 373 | if (tileProperties['isBlock']) { 374 | cc.log('This way is blocked!'); 375 | return false; 376 | } 377 | } else { 378 | return true; 379 | } 380 | } else 381 | return false; 382 | }, 383 | 384 | tryToMoveInTile: function(posInTile) { 385 | if (posInTile.x >= 0 && posInTile.x < this.mapTileSize.width && posInTile.y >= 0 && posInTile.y < this.mapTileSize.height) { 386 | var tileGid = this._blockLayer.getTileGIDAt(posInTile); 387 | //cc.log(tileGid); 388 | if (tileGid) { 389 | var tileProperties = this._tiledMap.getPropertiesForGID(tileGid); 390 | if (tileProperties['isBlock']) { 391 | cc.log('This way is blocked!'); 392 | return false; 393 | } 394 | } else { 395 | return true; 396 | } 397 | } else 398 | return false; 399 | }, 400 | 401 | inMapRange: function(posInTile) { 402 | if (posInTile.x >= 0 && posInTile.x < this.mapTileSize.width && posInTile.y >= 0 && posInTile.y < this.mapTileSize.height) { 403 | return true; 404 | } else { 405 | return false; 406 | } 407 | }, 408 | /** 409 | * !#zh 410 | * 动态设定不能行走区域,主要用于添加NPC时自动设定 411 | * @param {Object} posInTile 412 | */ 413 | setTileBlock: function(posInTile) { 414 | //偷懒只设置判定点 415 | this._blockLayer.setTileGID(this.blockTileGid, posInTile); 416 | }, 417 | 418 | /** 419 | * !#zh 420 | * 移除不可行走属性,当NPC移动或移除时都需要调用 421 | * @param {Object} posInTile 422 | */ 423 | removeTileBlock: function(posInTile) { 424 | this._blockLayer.removeTileAt(posInTile); 425 | }, 426 | 427 | /** 428 | * !#zh 429 | * 开门/关门动画(包含人物移动) 430 | * @param {Object} doorPos 门左下角坐标 431 | * @param {Number} doorFirstGid 门左下角Gid,门按固定顺序摆放 432 | * @param {GameEvent} cb 433 | */ 434 | openDoor: function(doorPos, doorFirstGid, cb) { 435 | //门由两个图层组成,人物处于中间 436 | var layer = []; 437 | layer[0] = this._tiledMap.getLayer("object"); 438 | layer[1] = this._tiledMap.getLayer("object2"); 439 | //列数 getTileSet还是有问题 440 | //var columnNum = layer[0].getTileSet().imageSize.width / this.tileSize.width; 441 | var columnNum = MapPara[this.mapId].TileSetColumn; 442 | var doorGid = [doorFirstGid, doorFirstGid + 1, 443 | doorFirstGid - columnNum, doorFirstGid - columnNum + 1, 444 | doorFirstGid - 2 * columnNum, doorFirstGid - 2 * columnNum + 1, 445 | doorFirstGid - 3 * columnNum, doorFirstGid - 3 * columnNum + 1 446 | ]; 447 | var player = this.game.player; 448 | 449 | var doorAnimation = function(target, offset) { 450 | //好像可以不用传参 451 | var posInTile = this._getTilePos(doorPos); 452 | if (offset < 0) { 453 | for (let i = 0; i < doorGid.length; i += 2) { 454 | layer[Math.floor(i / 4)].setTileGID(0, cc.p(posInTile.x, posInTile.y - i / 2)); 455 | layer[Math.floor(i / 4)].setTileGID(0, cc.p(posInTile.x + 1, posInTile.y - i / 2)); 456 | } 457 | } else { 458 | for (let i = 0; i < doorGid.length; i += 2) { 459 | layer[Math.floor(i / 4)].setTileGID(doorGid[i] + offset, cc.p(posInTile.x, posInTile.y - i / 2)); 460 | layer[Math.floor(i / 4)].setTileGID(doorGid[i + 1] + offset, cc.p(posInTile.x + 1, posInTile.y - i / 2)); 461 | } 462 | } 463 | }; 464 | var movePlayer = function(target) { 465 | var direction = player.direction; 466 | player.move(2, direction, 1, false, false); 467 | }; 468 | var playEffect = function(target, open) { 469 | var audioManager = this.gameNode.getComponent('AudioManager'); 470 | if (open) { 471 | //this.game.playAudioEffect("DoorOpen1", 0, false); 472 | audioManager.playEffect('DoorOpen1.mp3'); 473 | } else { 474 | //this.game.playAudioEffect("DoorClose1", 0, false); 475 | audioManager.playEffect('DoorClose1.mp3'); 476 | } 477 | }; 478 | var showUI = function(target) { 479 | this.game.hideUI(['default'], false, false); 480 | } 481 | 482 | var action = cc.sequence( 483 | cc.delayTime(0.07), 484 | cc.spawn( 485 | cc.callFunc(doorAnimation, this, 2), 486 | cc.callFunc(playEffect, this, true) 487 | ), 488 | cc.delayTime(0.07), 489 | cc.callFunc(doorAnimation, this, 4), 490 | cc.delayTime(0.07), 491 | cc.callFunc(doorAnimation, this, -1), 492 | cc.spawn( 493 | cc.delayTime(0.5), 494 | cc.callFunc(movePlayer, this) 495 | ), 496 | cc.delayTime(0.07), 497 | cc.spawn( 498 | cc.callFunc(doorAnimation, this, 0), 499 | cc.callFunc(playEffect, this, false) 500 | ), 501 | cc.callFunc(showUI, this), 502 | cc.callFunc(function() { if (cb) cb.next() }) 503 | ); 504 | 505 | this.game.hideUI(["default"], true, false); 506 | this.node.runAction(action); 507 | }, 508 | 509 | }); -------------------------------------------------------------------------------- /assets/scripts/core/system/EventHandle.js: -------------------------------------------------------------------------------- 1 | const Game = require('Game'); 2 | const GameEvent = require("GameEvent"); 3 | const EventManager = require('EventManager'); 4 | const WindowManager = require('WindowManager'); 5 | const PlayerData = require('PlayerData'); 6 | const AudioManager = require("AudioManager"); 7 | 8 | const EventType = cc.Enum({ 9 | Dialogue: 1, 10 | Shop: 2, 11 | SwitchScene: 3, 12 | ExecuteEvent: 4, 13 | ScrollMap: 5, 14 | MoveActor: 6, 15 | ShowActor: 7, 16 | SetEventDone: 8, 17 | SetActorPos: 9, 18 | ShowEmotion: 10, 19 | ShowItemMsg: 11, 20 | AddItem: 12, 21 | ShowMessage: 13, 22 | HideUI: 14, 23 | SetSwitcher: 15, 24 | MapAnimation: 16, 25 | DoorAnimation: 17, 26 | MoveByAStar: 18, 27 | GetTreasure: 19, 28 | LockUI: 20, 29 | Option: 21, 30 | Delay: 22, 31 | FadeIn: 23, 32 | Task: 24, 33 | AudioMusic: 25, 34 | AudioEffect: 26, 35 | ChangeAtlas: 27, 36 | ChangeSprite: 28, 37 | MoveAnimation: 29, 38 | SetLayerOrder: 30, 39 | ShowLoading: 31, 40 | Branch: 32, 41 | MoveRandomly: 33, 42 | MaintainEvent: 34, 43 | EventControl: 35, 44 | Qmessage: 36, 45 | CameraAutoFollow: 37, 46 | ActorAction: 38 47 | }); 48 | 49 | const ConditionType = cc.Enum({ 50 | CheckItem: 1, 51 | Random: 2, 52 | Variable: 3, 53 | CheckDistance: 4, 54 | ForwardPassable: 5, 55 | 56 | DetectionRange: 101, 57 | CheckBehind: 102 58 | }); 59 | 60 | cc.Class({ 61 | extends: cc.Component, 62 | 63 | properties: { 64 | game: { 65 | default: null, 66 | type: Game 67 | }, 68 | eventManager: { 69 | default: null, 70 | type: EventManager 71 | }, 72 | playerData: { 73 | default: null, 74 | type: PlayerData 75 | }, 76 | windowManager: { 77 | default: null, 78 | type: WindowManager 79 | }, 80 | audioManager: { 81 | default: null, 82 | type: AudioManager 83 | } 84 | }, 85 | 86 | // use this for initialization 87 | onLoad: function() { 88 | //自定义变量,值必须为函数 key:function 89 | this.CustomVariable = {}; 90 | }, 91 | 92 | /** 93 | * checkSwitcher 94 | */ 95 | checkSwitcher: function(switcher) { 96 | return this.eventManager.eventSwitcher[switcher]; 97 | }, 98 | 99 | /** 100 | * Type 1 101 | */ 102 | showDialogueBox: function(detail, target, gameEvent) { 103 | let dialogues = detail; 104 | this.windowManager.showDialogueBox(dialogues, target, gameEvent); 105 | }, 106 | 107 | /** 108 | * Type 2 109 | */ 110 | showShop: function(detail, target, gameEvent) { 111 | let itemIdList = detail.itemIdList; 112 | this.windowManager.showShopWindow(itemIdList, target, gameEvent); 113 | }, 114 | 115 | /** 116 | * Type 3 117 | */ 118 | switchScene: function(detail) { 119 | let destMapId = detail.destMapId; 120 | let playerId = detail.playerId; 121 | let destPos = detail.destPos; 122 | let direction = detail.direction; 123 | this.game.switchScene(destMapId, playerId, destPos, direction, false); 124 | }, 125 | 126 | /** 127 | * Type 4 128 | */ 129 | executeEvent: function(detail, gameEvent) { 130 | let eventId = detail.eventId; 131 | this.eventManager.eventStart(eventId); 132 | gameEvent.next(); 133 | }, 134 | 135 | /** 136 | * Type 5 137 | */ 138 | scrollMap: function(detail, gameEvent) { 139 | let centerPos = detail.centerPos; 140 | let scroll = detail.scroll; 141 | let speed = detail.speed || 1; 142 | this.game.scene.map.mapCamera(centerPos, scroll, speed, gameEvent); 143 | }, 144 | 145 | /** 146 | * Type 6 147 | */ 148 | moveActor: function(detail, gameEvent) { 149 | let actorId = detail.actorId.toString(); 150 | let step = detail.step; 151 | let direction = detail.direction; 152 | let speed = detail.speed; 153 | let wait = detail.wait; 154 | let actorTarget = this.game.scene.getActorTarget(actorId); 155 | actorTarget.move(step, direction, speed, wait, gameEvent); 156 | }, 157 | 158 | /** 159 | * Type 7 160 | */ 161 | showActor: function(detail, gameEvent) { 162 | let actorId = detail.actorId.toString(); 163 | let active = detail.active; 164 | let actorTarget = this.game.scene.getActorTarget(actorId); 165 | actorTarget.node.active = active; 166 | gameEvent.next(); 167 | }, 168 | 169 | /** 170 | * Type 8 171 | */ 172 | setEventDone: function(detail, gameEvent) { 173 | let eventId = detail.eventId; 174 | let done = detail.done; 175 | this.eventManager.setDoneFlag(eventId, done, gameEvent); 176 | }, 177 | 178 | /** 179 | * Type 9 180 | */ 181 | setActorPos: function(detail, gameEvent) { 182 | let actorId = detail.actorId.toString(); 183 | let pos = detail.pos; 184 | let direction = detail.direction; 185 | if (actorId == '0') actorId = this.game.playerId; 186 | let actorTarget = this.game.scene.getActorTarget(actorId); 187 | actorTarget.setPos(pos, direction); 188 | gameEvent.next(); 189 | }, 190 | 191 | /** 192 | * Type 10 193 | */ 194 | showEmotion: function(detail, gameEvent) { 195 | let actorId = detail.actorId.toString(); 196 | let emotionName = detail.emotionName; 197 | let wait = detail.wait; 198 | let target = this.game.scene.getActorTarget(actorId); 199 | target.showEmotion(emotionName, wait, gameEvent); 200 | }, 201 | 202 | /** 203 | * Type 11 204 | */ 205 | showItemMsg: function(detail, gameEvent) { 206 | let type = detail.type; 207 | let itemId = detail.itemId; 208 | let count = detail.count; 209 | this.windowManager.showItemMsg(type, itemId, count, gameEvent); 210 | }, 211 | 212 | /** 213 | * Type 12 214 | */ 215 | addItem: function(detail, gameEvent) { 216 | let type = detail.type; 217 | let itemId = detail.itemId; 218 | let num = detail.num; 219 | switch (type) { 220 | case 0: 221 | this.playerData.setMoneyBy(num); 222 | break; 223 | case 1: 224 | if (num > 0) { 225 | this.playerData.addItem(itemId, num); 226 | } else { 227 | this.playerData.removeItem(itemId, -num); 228 | } 229 | break; 230 | } 231 | gameEvent.next(); 232 | }, 233 | 234 | /** 235 | * Type 13 236 | */ 237 | showMessage: function(detail, gameEvent) { 238 | let message = detail.message; 239 | this.windowManager.showMessage(message, gameEvent); 240 | }, 241 | 242 | /** 243 | * Type 14 244 | */ 245 | hideUI: function(detail, gameEvent) { 246 | let nodeList = detail.nodeList; 247 | let hide = detail.hide; 248 | this.game.hideUI(nodeList, hide, gameEvent); 249 | }, 250 | 251 | /** 252 | * Type 15 untested 253 | */ 254 | setSwitcher: function(detail, gameEvent) { 255 | let switcherId = detail.switcherId; 256 | let flag = detail.flag; 257 | this.eventManager.setSwitcher(switcherId, flag, gameEvent); 258 | }, 259 | 260 | /** 261 | * Type 16 untested 262 | */ 263 | mapAnimation: function(detail, gameEvent) { 264 | let clipName = detail.clipName; 265 | let wait = detail.wait; 266 | this.game.playMapAnimation(clipName, wait, gameEvent); 267 | }, 268 | 269 | /** 270 | * Type 17 untested 271 | */ 272 | doorAnimation: function(detail, gameEvent) { 273 | let doorPos = detail.pos; 274 | let firstGid = detail.firstGid; 275 | this.game.scene.map.openDoor(doorPos, firstGid, gameEvent); 276 | }, 277 | 278 | /** 279 | * Type 18 280 | */ 281 | moveActorByAStar: function(detail, gameEvent) { 282 | let actorId = detail.actorId.toString(); 283 | let destPos = detail.destPos; 284 | let direction = detail.direction; 285 | let speed = detail.speed; 286 | let wait = detail.wait; 287 | let actorTarget = this.game.scene.getActorTarget(actorId); 288 | actorTarget.moveByAStar(destPos, direction, speed, wait, gameEvent); 289 | }, 290 | 291 | /** 292 | * Type 19 293 | */ 294 | getTreasure: function(detail, target, gameEvent) { 295 | let gainEvent = detail.gainEvent; 296 | target.getTreasure(gainEvent, gameEvent); 297 | }, 298 | 299 | /** 300 | * Type 20 301 | */ 302 | lockUI: function(detail, gameEvent) { 303 | let lock = detail.lock; 304 | this.game.lockUI(lock, gameEvent); 305 | }, 306 | 307 | /** 308 | * Type 21 309 | */ 310 | showOption: function(detail, target, gameEvent) { 311 | let message = detail.message; 312 | let options = detail.options; 313 | this.windowManager.showOption(message, target, options, gameEvent); 314 | }, 315 | 316 | /** 317 | * Type 22 318 | */ 319 | delaySecond: function(detail, gameEvent) { 320 | let second = detail.second; 321 | this.game.delaySecond(second, gameEvent); 322 | }, 323 | 324 | /** 325 | * Type 23 326 | */ 327 | fadeInOrOut: function(detail, gameEvent) { 328 | let fadeIn = detail.fadeIn; 329 | let duration = detail.duration; 330 | this.windowManager.fadeInOrOut(fadeIn, duration, gameEvent); 331 | }, 332 | 333 | /** 334 | * Type 25 335 | */ 336 | audioMusic: function(detail, gameEvent) { 337 | let audioName = detail.audioName; 338 | let loop = detail.loop; 339 | let state = detail.state; 340 | 341 | switch (state) { 342 | //播放 343 | case 0: 344 | this.audioManager.playMusic(audioName, loop, gameEvent); 345 | break; 346 | //暂停 347 | case 1: 348 | this.audioManager.pauseMusic(audioName, gameEvent); 349 | break; 350 | //恢复 351 | case 2: 352 | this.audioManager.resumeMusic(audioName, loop, gameEvent); 353 | break; 354 | //停止 355 | case 3: 356 | this.audioManager.stopMusic(audioName, gameEvent); 357 | break; 358 | } 359 | }, 360 | 361 | /** 362 | * Type 26 363 | */ 364 | audioEffect: function(detail, gameEvent) { 365 | let audioName = detail.audioName; 366 | this.audioManager.playEffect(audioName, gameEvent); 367 | }, 368 | 369 | /** 370 | * Type 27 371 | */ 372 | changeAtlas: function(detail, gameEvent) { 373 | let actorId = detail.actorId.toString(); 374 | let atlasPath = detail.atlasPath; 375 | let target = this.game.scene.getActorTarget(actorId); 376 | target.changeAtlas(atlasPath, gameEvent); 377 | }, 378 | 379 | /** 380 | * Type 28 381 | */ 382 | changeSprite: function(detail, gameEvent) { 383 | let actorId = detail.actorId.toString(); 384 | let spriteName = detail.spriteName; 385 | let target = this.game.scene.getActorTarget(actorId); 386 | target.changeSprite(spriteName, gameEvent); 387 | }, 388 | 389 | /** 390 | * Type 29 391 | */ 392 | moveAnimation: function(detail, gameEvent) { 393 | let actorId = detail.actorId.toString(); 394 | let direction = detail.direction; 395 | let speed = detail.speed; 396 | let state = detail.state; 397 | let target = this.game.scene.getActorTarget(actorId); 398 | if (state == 1) { 399 | target.moveAnimation(null, { direction: direction, speed: speed }); 400 | } else { 401 | target.stopAnim(null, direction); 402 | } 403 | gameEvent.next(); 404 | }, 405 | 406 | /** 407 | * Type 30 408 | */ 409 | setLayerOrder: function(detail, gameEvent) { 410 | let order = detail.order; 411 | let actorId = detail.actorId; 412 | let target = this.game.scene.getActorTarget(actorId); 413 | target.setLayerOrder(order, gameEvent); 414 | }, 415 | 416 | /** 417 | * Type 31 418 | */ 419 | showLoading: function(detail, gameEvent) { 420 | let show = detail.show; 421 | this.windowManager.showLoading(show, gameEvent); 422 | }, 423 | 424 | /** 425 | * Type 32 426 | */ 427 | branch: function(detail, gameEvent) { 428 | let conditions = detail.conditions; 429 | //事件分支列表[[],[]] 430 | let branch = detail.branch; 431 | //概率参考值。0~1,表示触发概率。1为100%触发。 432 | let randomRef = detail.randomRef; 433 | let flag = true; 434 | let subEvents = branch[0]; 435 | for (let i = 0; i < conditions.length; i++) { 436 | if (!this.conditionInterpreter(conditions[i])) { 437 | flag = false; 438 | break; 439 | } 440 | } 441 | //如果满足条件,并满足随机概率则触发。 442 | if (flag) { 443 | let random = cc.random0To1(); 444 | if (random < randomRef) { 445 | subEvents = branch[1]; 446 | } 447 | } 448 | 449 | let newEvent = new GameEvent(); 450 | newEvent.setCallback(gameEvent); 451 | newEvent.startBySubEvent(subEvents, gameEvent); 452 | }, 453 | 454 | /** 455 | * Type 33 456 | */ 457 | moveRandomly: function(detail, gameEvent) { 458 | let actorId = detail.actorId; 459 | let speed = detail.speed; 460 | let target = this.game.scene.getActorTarget(actorId); 461 | if (target) { 462 | target.moveRandomly(speed, gameEvent); 463 | } else { 464 | cc.log("cannot find actorID: ", actorId); 465 | gameEvent.next(); 466 | } 467 | }, 468 | 469 | /** 470 | * Type 34 471 | * 只能在Branch中的事件序列使用。在主事件序列中没有用。 472 | */ 473 | maintainEvent: function(detail, gameEvent) { 474 | let parentEvent = gameEvent.callback; 475 | if (parentEvent instanceof GameEvent) { 476 | parentEvent.unshiftSubEvent(parentEvent.preSubEvent); 477 | } 478 | gameEvent.next(); 479 | }, 480 | 481 | /** 482 | * Type 35 483 | * 控制事件的运行停止 484 | */ 485 | eventControl: function(detail, gameEvent) { 486 | let state = detail.state; 487 | let eventId = detail.eventId; 488 | this.eventManager.eventControl(eventId, state, gameEvent.next.bind(gameEvent)) 489 | }, 490 | 491 | /** 492 | * Type 36 493 | */ 494 | showQmessage: function(detail, gameEvent) { 495 | let actorId = detail.actorId; 496 | let message = detail.message; 497 | 498 | let target = (actorId == '0') ? this.game.scene.getActorTarget(this.game.playerId) : this.game.scene.getActorTarget(actorId); 499 | 500 | if (target) { 501 | this.windowManager.showQmessage(target.node, message, gameEvent.next.bind(gameEvent)); 502 | } else { 503 | cc.log('can not find node'); 504 | gameEvent.next(); 505 | } 506 | }, 507 | 508 | /** 509 | * Type 37 510 | * 设置镜头跟随 511 | */ 512 | setCameraAutoFollow: function(detail, gameEvent) { 513 | this.game.cameraFollowFlag = detail.flag; 514 | gameEvent.next(); 515 | }, 516 | 517 | /** 518 | * Type 38 519 | * 运行自定义角色动作 520 | */ 521 | playActionAction: function(detail, gameEvent) { 522 | var actionTag = detail.tag; 523 | var wait = detail.wait; 524 | var actorId = detail.actorId; 525 | 526 | var target = this.game.scene.getActorTarget(actorId); 527 | var action = this.game.cache.getAction(actionTag); 528 | if (!action) { 529 | console.log("没有定义动作: ", actionTag); 530 | gameEvent.next(); 531 | return; 532 | } 533 | target.runAction(action, wait, gameEvent.next.bind(gameEvent)) 534 | 535 | }, 536 | 537 | eventInterpreter: function(subEvent, gameEvent) { 538 | let detail = subEvent.detail; 539 | switch (subEvent.eventType) { 540 | case EventType.Dialogue: 541 | this.showDialogueBox(detail, gameEvent.event.target, gameEvent); 542 | break; 543 | case EventType.Shop: 544 | this.showShop(detail, gameEvent.event.target, gameEvent); 545 | break; 546 | case EventType.SwitchScene: 547 | this.switchScene(detail); 548 | break; 549 | case EventType.ExecuteEvent: 550 | this.executeEvent(detail, gameEvent); 551 | break; 552 | case EventType.ScrollMap: 553 | this.scrollMap(detail, gameEvent); 554 | break; 555 | case EventType.MoveActor: 556 | this.moveActor(detail, gameEvent); 557 | break; 558 | case EventType.ShowActor: 559 | this.showActor(detail, gameEvent); 560 | break; 561 | case EventType.SetEventDone: 562 | this.setEventDone(detail, gameEvent); 563 | break; 564 | case EventType.SetActorPos: 565 | this.setActorPos(detail, gameEvent); 566 | break; 567 | case EventType.ShowEmotion: 568 | this.showEmotion(detail, gameEvent) 569 | break; 570 | case EventType.ShowItemMsg: 571 | this.showItemMsg(detail, gameEvent); 572 | break; 573 | case EventType.AddItem: 574 | this.addItem(detail, gameEvent); 575 | break; 576 | case EventType.ShowMessage: 577 | this.showMessage(detail, gameEvent); 578 | break; 579 | case EventType.HideUI: 580 | this.hideUI(detail, gameEvent); 581 | break; 582 | case EventType.SetSwitcher: 583 | this.setSwitcher(detail, gameEvent); 584 | break; 585 | case EventType.MapAnimation: 586 | this.mapAnimation(detail, gameEvent); 587 | break; 588 | case EventType.DoorAnimation: 589 | this.doorAnimation(detail, gameEvent); 590 | break; 591 | case EventType.MoveByAStar: 592 | this.moveActorByAStar(detail, gameEvent); 593 | break; 594 | case EventType.GetTreasure: 595 | this.getTreasure(detail, gameEvent.event.target) 596 | break; 597 | case EventType.LockUI: 598 | this.lockUI(detail, gameEvent); 599 | break; 600 | case EventType.Option: 601 | this.showOption(detail, gameEvent.event.target, gameEvent); 602 | break; 603 | case EventType.Delay: 604 | this.delaySecond(detail, gameEvent); 605 | break; 606 | case EventType.FadeIn: 607 | this.fadeInOrOut(detail, gameEvent); 608 | break; 609 | case EventType.AudioMusic: 610 | this.audioMusic(detail, gameEvent); 611 | break; 612 | case EventType.AudioEffect: 613 | this.audioEffect(detail, gameEvent); 614 | break; 615 | case EventType.ChangeAtlas: 616 | this.changeAtlas(detail, gameEvent); 617 | break; 618 | case EventType.ChangeSprite: 619 | this.changeSprite(detail, gameEvent); 620 | break; 621 | case EventType.MoveAnimation: 622 | this.moveAnimation(detail, gameEvent); 623 | break; 624 | case EventType.SetLayerOrder: 625 | this.setLayerOrder(detail, gameEvent); 626 | break; 627 | case EventType.ShowLoading: 628 | this.showLoading(detail, gameEvent); 629 | break; 630 | case EventType.Branch: 631 | this.branch(detail, gameEvent); 632 | break; 633 | case EventType.MoveRandomly: 634 | this.moveRandomly(detail, gameEvent); 635 | break; 636 | case EventType.MaintainEvent: 637 | this.maintainEvent(detail, gameEvent); 638 | break; 639 | case EventType.EventControl: 640 | this.eventControl(detail, gameEvent); 641 | break; 642 | case EventType.Qmessage: 643 | this.showQmessage(detail, gameEvent); 644 | break; 645 | case EventType.CameraAutoFollow: 646 | this.setCameraAutoFollow(detail, gameEvent); 647 | break; 648 | case EventType.ActorAction: 649 | this.playActionAction(detail, gameEvent); 650 | break; 651 | default: 652 | console.log("no event type") 653 | gameEvent.next(); 654 | break; 655 | } 656 | }, 657 | 658 | /** 659 | * 检测条件 660 | */ 661 | /** 662 | * 1 663 | */ 664 | checkItem: function(detail) { 665 | let type = detail.type; 666 | let itemId = detail.itemId; 667 | let num = detail.num; 668 | let compare = detail.compare; 669 | 670 | let realNum; 671 | if (type == 0) { 672 | realNum = this.playerData.getMoney() 673 | } else { 674 | realNum = this.playerData.checkItem(itemId) 675 | } 676 | 677 | return this.compare(realNum, num, compare); 678 | }, 679 | 680 | /** 681 | * 2 682 | */ 683 | random: function(detail) { 684 | let ref = detail.ref; 685 | let operator = detail.operator; 686 | let result = cc.random0To1(); 687 | 688 | return this.compare(result, ref, operator); 689 | }, 690 | 691 | /** 692 | * 3 693 | */ 694 | variable: function(detail) { 695 | let variable = detail.variable; 696 | let ref = detail.ref; 697 | let operator = detail.operator; 698 | 699 | if (this.CustomVariable[variable]) { 700 | let result = this.CustomVariable[variable](); 701 | return this.compare(result, ref, operator); 702 | } else { 703 | cc.log('cannot find variable'); 704 | return false; 705 | } 706 | }, 707 | 708 | /** 709 | * actor1=0是代表自身 710 | * actor2=0代表玩家 711 | * 4 712 | */ 713 | checkDistance: function(detail, target) { 714 | let actorId1 = detail.actorId1; 715 | let actorId2 = detail.actorId2; 716 | let ref = detail.ref; 717 | let operator = detail.operator; 718 | 719 | //id 0 表示事件拥有者 720 | let target1 = (actorId1 == '0') ? target : this.game.scene.getActorTarget(actorId1); 721 | let target2 = (actorId2 == '0') ? this.game.scene.getActorTarget(this.game.playerId) : this.game.scene.getActorTarget(actorId2); 722 | 723 | let tilePos1 = target1.getRealTilePos(); 724 | let tilePos2 = target2.getRealTilePos(); 725 | 726 | let deltaX = Math.abs(tilePos1.x - tilePos2.x); 727 | let deltaY = Math.abs(tilePos1.y - tilePos2.y); 728 | 729 | //怎么算距离合适?x+y or max(x,y) 730 | let distance = detailX + detailY; 731 | return this.compare(distance, ref, operator); 732 | }, 733 | 734 | /** 735 | * 5 736 | */ 737 | checkForwardPassable: function(detail) { 738 | let direction = detail.direction; 739 | let actorId = detail.actorId.toString(); 740 | let target = this.game.scene.getActorTarget(actorId); 741 | return this.game.scene.map.tryToMove(target.getForwardPos(direction)); 742 | }, 743 | 744 | /** 745 | * 6 746 | */ 747 | 748 | /** 749 | * 用于潜行系统,判断玩家是否在侦察范围内 750 | * 101 751 | */ 752 | detectionRange: function(detail) { 753 | let selfId = detail.selfId; 754 | let range = detail.range; 755 | let target = this.game.scene.getActorTarget(selfId); 756 | 757 | return target.stealth.inDetectionRange(selfId, this.game.playerId, range); 758 | }, 759 | 760 | /** 761 | * 用于潜行系统,判断玩家是否在背后 762 | * Type 102 763 | */ 764 | checkBehind: function(detail, self) { 765 | let actorId = detail.actorId; 766 | let target = (actorId == '0') ? self : this.game.scene.getActorTarget(actorId); 767 | return target.stealth.checkBehind(); 768 | }, 769 | 770 | conditionInterpreter: function(condition, gameEvent) { 771 | let detail = condition.detail; 772 | let result = false; 773 | switch (condition.conditionType) { 774 | case ConditionType.CheckItem: 775 | result = this.checkItem(detail); 776 | break; 777 | case ConditionType.Random: 778 | result = this.random(detail); 779 | break; 780 | case ConditionType.Variable: 781 | result = this.variable(detail); 782 | break; 783 | case ConditionType.CheckDistance: 784 | result = this.checkDistance(detail, gameEvent.event.target); 785 | break; 786 | case ConditionType.ForwardPassable: 787 | result = this.checkForwardPassable(detail); 788 | break; 789 | case ConditionType.DetectionRange: 790 | result = this.detectionRange(detail); 791 | break; 792 | case ConditionType.CheckBehind: 793 | result = this.checkBehind(detail, gameEvent.event.target); 794 | break; 795 | } 796 | return result; 797 | }, 798 | 799 | compare: function(a, b, operator) { 800 | switch (operator) { 801 | case 0: 802 | //= 803 | if (a == b) return true 804 | break; 805 | case 1: 806 | //> 807 | if (a > b) return true 808 | break; 809 | case 2: 810 | //< 811 | if (a < b) return true 812 | break; 813 | case 3: 814 | //>= 815 | if (a >= b) return true 816 | break; 817 | case 4: 818 | //<= 819 | if (a <= b) return true 820 | break; 821 | default: 822 | return false; 823 | } 824 | return false; 825 | } 826 | }); --------------------------------------------------------------------------------