cocos UI、地图和关卡文本制作(一)

给宝宝做一个cocos免费游戏

第一章 背景和开发框架介绍
第二章 Node树和场景制作
第三章 UI、地图和关卡文本制作
第四章 摇杆、按键和角色动画制作

第五章 敌人和AI制作
第六章 角色和敌人行为互动脚本制作
第七章 游戏打包、发布和调试


请下载上一章代码:https://download.csdn.net/download/sinat_29014637/17854872?spm=1001.2014.3001.5503。本章节上上一章代码基础上开发

一、UI-设置、equipment和item栏

1.设置tab

原理:通过cc.sys.localstorage来设定参数作为设定值(HTML平台清空缓存会被清理),jsb操作json在h5平台不受支持,所以我们项目暂时使用前者。

1.1在Canva节点右击创建节点-创建UI节点-layout,然后在layout上添加一个botton三个editBox

在这里插入图片描述

1.2 添加加载、写入和显示layout的代码

既然是全局的代码,我们放到canvasjs.js上

//1.显示和隐藏setting
  showOrHideSetting:function(e){
    var setl = cc.find('Canvas').getChildByName('settingLayout');
    if(setl){
      setl.active = setl.active? false:true;
    }
  },
//2.显示配置内容
  loadSetting:function(e){
    var setl = cc.find('Canvas').getChildByName('settingLayout');
    var pname = cc.sys.localStorage.getItem('pname');
    if(setl && pname){
      setl.getChildByName('EditBox1').getComponent(cc.EditBox).string = pname;
      setl.getChildByName('EditBox1').getChildByName('LABEL').string = 'pname';
      //voice
      //graphic
      //action
  }
  var uinode = cc.find('Canvas').getChildByName('UI');
  var userinfo = uinode.getChildByName('playerinfo');
  if(userinfo){
    userinfo.getChildByName('pname').getComponent(cc.Label).string = pname? pname:'notnamed';},
//3.修改配置内容  
  setSetting:function(e){
    var setl = cc.find('Canvas').getChildByName('settingLayout');
    var value =  setl.getChildByName('EditBox1').getComponent(cc.EditBox).string ;
    var keys = setl.getChildByName('EditBox1').getChildByName('LABEL').string;
    cc.sys.localStorage.setItem(keys,value);
  },
1.3 在场景加载时候加载这个配置内容
onLoad(){
      this.loadSetting();//加载setting,显示在右上角头像和三围
      }

2.item栏和equipment tab

现在开始做物品和装备栏,上一章我们建立了equipment节点:头身体和四肢+3个技能栏组成和scrollview,因为我们日常都是拖动物品到装备栏,故建议把equipment节点放到scrollview子节点下,方便在同一个js上写触摸拖动、碰撞、碰撞后填入栏位的功能。

2.1加载ITEMS

LOAD和set读写items的代码公用性较强,可以写到canvasjs.js
(1)考虑scrollview导致node层级较多,这里把itemSrollView修改一下,把view节点改为grid,添加layout组件:
在这里插入图片描述
(2)添加后在grid节点添加子节点发现都会自动按照网格排列。所以清空grid的子对象,使用代码读取json和localstorage来添加相应的物品。
这里遇到一个问题,cc.sys.loalstorage是异步读取的,所以读取json时候重复读spriteframe图片,会发现读完spriteframe后,前面已经读取完,故只有最后一个json记录才有spritefram,这里先记录下来后面找找原因,知道解决方法的朋友也请留言告诉我一声
虽然json遇到问题,项目还是要进行,那就替代方案走起:

1)js直接定义一个array变量记录初始的item

const TOOLS = [
    {
        id:'W1',//唯一值:type+序号
        sname:'mainMap',//场景
        type:'W',//类型 W-weapon  I-ITEMS  E-EQUIPMENT   S-SKILL技能
        name: '工具套装',                        // 名称
        desc: '这是一个工具盒,撬门破解无所不能',     // 点击显示介绍
        owner:'player',//所在位置(拥有者)
        eff:'at',//效果 at=attact  hp=+-hp mp=+-mp lp=+-lp值 
        value:'10',//配合eff,eff的值,支持+-号
        rotation:'0',//方向
        icon: 'icons/png-0007'                 // 动态加载路径
    },
    {
        id:'I1',//唯一值:type+序号
        sname:'mainMap',//场景
        type:'I',//类型 W-weapon  I-ITEMS  E-EQUIPMENT 
        name: '放大镜',                        
        desc: '就是个放大镜,啥东西放上去都能变大',     
        owner:'player',//所在位置(拥有者)
        eff:'at',//效果 at=attact  hp=+-hp mp=+-mp lp=+-lp值 
        value:'10',//配合eff,eff的值,支持+-号   
        rotation:'0',//方向      
        icon: 'icons/png-0017'                 
    },
    {
        id:'W2',//唯一值:type+序号
        sname:'mainMap',//场景
        type:'W',//类型 W-weapon  I-ITEMS  E-EQUIPMENT 
        name: '剪刀',                        
        desc: '这是剪刀,当做武器不知道行不行',      
        owner:'player',//所在位置(拥有者)
        eff:'at',//效果 at=attact  hp=+-hp mp=+-mp lp=+-lp值 
        value:'20',//配合eff,eff的值,支持+-号     
        rotation:'0',//方向  
        icon: 'icons/png-0031'               
    },
    {
        id:'W3',//唯一值:type+序号
        sname:'mainMap',//场景
        type:'W',//类型 W-weapon  I-ITEMS  E-EQUIPMENT 
        name: '卷轴',                        
        desc: '这是卷轴',      
        owner:'player',//所在位置(拥有者)
        eff:'at',//效果 at=attact  hp=+-hp mp=+-mp lp=+-lp值 
        value:'20',//配合eff,eff的值,支持+-号     
        rotation:'0',//方向  
        icon: 'icons/卷轴'               
    },
];

export {TOOLS};  // import {TOOLS} from './array'; //通过这个函数调用js

2)新建一个itemstab.js来编写加载spriteframe动态icon的代码

    // update (dt) {},
    setSpriteFrame:function(iconurl){
        var self = this;
        cc.loader.loadRes(iconurl,cc.SpriteFrame,function(err,res){
            self.node.getComponent(cc.Sprite).spriteFrame = res; 
        });
    },

3)定义一个物品的prefab方便实例化复制然后切换不同的icon来代码不同物品
a.在grid节点——新建节点——sprite,然后添加一个label
在这里插入图片描述
b.给item添加js组件
在这里插入图片描述
c.拖动item节点到资源管理器新建的prefab文件夹(任意都行,方便管理新建了prefab文件夹)
在这里插入图片描述
这样就完成了预制体的制作,后面通过cc.instance()来不断实例化和复制,重复利用

4)在canvasjs.js中编写代码,要加载icon图片时候,直接调用itemstab.js就可以同步加载,解决异步问题

  //items和equipte相关代码
  loadItems: function (e, customerData) {
    var itemsview = cc.find('Canvas').getChildByName('UI').getChildByName('itemScrollView');
    if (!itemsview) { cc.log('找不到itemScrollView'); return; }
    //customerData:i类-formal items  E类-equipment  W类-weapon
    //是否有缓存,有则取缓存的档案,没有取json的初始档案
    var items = cc.sys.localStorage.getItem('items');
    if (!items) {//from json
      var url = 'json/main';//resources/json/..
      // cc.loader.loadRes(url, cc.RawAsset, function (err, res) {//异步跟下面异步获取spriteframe有冲突
      // if (!err) {
      // var rs = res.json.items;//json的obj:mapobj  items  acts
      for (var i = 0; i < TOOLS.length; i++) {
        if (TOOLS[i].owner == 'player') {
          var obj;
          obj = cc.instantiate(this.item);   //(new cc.Node());//this.floor无效
          if (obj) {
            obj.name = TOOLS[i].id;//TOOLS[i].name;
            obj.angle = - TOOLS[i].rotation;//方向
            // obj.addComponent(cc.Sprite);
            // obj.parent = itemsview.getChildByName('grid'); //父本 sv-view-content-item
            // obj.setPosition(cc.v2(rs[i].posx, rs[i].posy));
            // cc.loader.loadRes(rs[i].icon,cc.SpriteFrame,function(err,res){
            //     obj.getComponent(cc.Sprite).spriteFrame = res; 
            // });

            var itemjs = obj.getComponent('itemstab');
            var icons = TOOLS[i].icon;
            itemjs.setSpriteFrame(icons);//直接调用item的方法
            itemsview.getChildByName('grid').addChild(obj);
          }
        }
      }
      // } else { cc.log(err); }            //异步 往往会执行后面之后再回调函数
      // });
    } else {//from localstorage

    }
  },
  setItems: function (e) {

  },

最终效果:比较“斋”,目的达到就好,后面再找时间美化下
在这里插入图片描述

2.2拖动和排序实现

item拖动可以通过touch_move的方法实现,移动时候鼠标变为图片,停止时候执行排序,排列顺序呢目前是按照grad layout标准方法排列:新的放到最后,旧的不变

    onLoad() {
        var self = this;
        this.initpos;
        this.endpos;
          this.node.on(cc.Node.EventType.TOUCH_START, function (e) {
            this.initpos = e.getLocation;
        }.bind(this), this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, function (e) {
            var dis = e.getDelta();        //    cc.log(dis.x +':'+ dis.y);
            if(self.node.parent.parent.name == 'equipment'){return;}
            var dy = self.node.position.y + dis.y;
            var dx = self.node.position.x + dis.x;
            var isv = cc.find('Canvas').getChildByName('UI').getChildByName('itemScrollView');
            // cc.log(self.node.parent);//需要添加不等于装备 
            self.node.parent = isv;//grid 里面是不能随便拖动的,转到别的父本
            self.node.setPosition(cc.v2(dx, dy));
        }.bind(this), this);
        this.node.on(cc.Node.EventType.TOUCH_END, function (e) {

        }.bind(this), this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, function (e) {
            //    self.node.removeFromParent();//移走
            //没有移到其他栏目则回来原来grid
            if (self.node.parent == cc.find('Canvas').getChildByName('UI').getChildByName('itemScrollView')) {
                self.node.parent = cc.find('Canvas').getChildByName('UI').getChildByName('itemScrollView').getChildByName('grid');
            }
        }.bind(this), this);
    },

2.3 equipment-碰撞实现加入栏位

而考虑交互事件较多、冒泡事件传递较复杂,我们需要在itemstab.js脚本文件来编写items的拖拉筛选等代码
原理剖析:首先我们是拖动item,故应该在每个item启用touch方法;拖动后放到装备栏或者使用按钮,有两种方法实现:a.判断坐标是否落入 b.直接使用碰撞,碰撞后从物品栏去掉,加载到具体装备栏。我选择b资源不用重复加载,换一个副本即可。另外我们需要把装备类item节点命名为E+名称,这样就可以简单判断。

2.3.1为equipment栏添加碰撞组件

在这里插入图片描述

2.3.2在itemstab.js添加碰撞检测代码

(1)开启碰撞

    onLoad() {
        //开启碰撞检测
        var collider = cc.director.getCollisionManager();
        collider.enabled = true;
        // collider.enabledDebugDraw = true; //debug
        // collider.enabledDrawBoundingBox = true;
        ...

检查碰撞组:UI之间还是要碰撞(也可以单独给item分配新的组)
在这里插入图片描述

(2)检测碰撞时候改变副本为具体的equipment栏

    //碰撞检测
    onCollisionEnter:function(other,self){
        // cc.log('ot:'+other.node.name);
        // cc.log('se:'+self.node.name.substr(0,1));
        if(self.node.name.substr(0,1) != 'W' && self.node.name.substr(0,1) != 'S' && self.node.name.substr(0,1) != 'E'){return;}
        var i = 0;
        switch(other.node.name){//对应equipment节点所有的装备栏
            case 'head':i =1;break;
            case 'body':i =2;break;
            case 'lhand':i =3;break;
            case 'rhand':i =4;break;
            case 'lfoot':i =5;break;
            case 'rfoot':i =6;break;
            case 'skill1':i =7;break;
            case 'skill2':i =8;break;
            case 'skill3':i =9;break;
            // case '':break;
            // case '':break;
            // case '':break;
        }
        if(i!= 0 && other.node.children.length<1){
            self.node.parent = other.node ;
            // cc.log(other.node.name);
            self.node.setPosition(cc.v2(0,0));
        }
    },

总结

有点复杂,花了较长时间只做了item栏和装备栏的互动,后面还要做数据运算等,地图和关卡文本放到(二)文章处理吧。
这里提供物品栏制作的文章供参考,非常感谢博主对我们这些菜鸟的指引:
https://blog.csdn.net/La_vie_est_belle/article/details/105147837

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猿的hello World

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值