cocos creater实现微信小游戏中常见的拖动合成升级的思路和代码例子

 

现在很多微信小游戏或宣传能赚钱的app游戏、以及合成塔防游戏,都用到了拖动合成升级的操作方式。所以我在也尝试做了一个这功能。

思路很简单:1、实现触摸道具并拖动时,道具跟随触摸点位置移动;2、在触摸事件中检查移动的道具与其他道具是矩形相交,即简单的碰撞检查功能;3、如果发生碰撞,则判断是否同级道具,如果是则调用方法删除或隐藏移动的道具和被碰撞的道具,生成新道具(高一级道具);

上面就是简单的实现方法,当然还有不同等级的位置交换或空位置的移动,最大等级判断和重现碰撞检测等问题需要一起解决,比较简单。

 

具体的实现步骤,用下面截图和代码简单说明:

首先要创建并初始化放置道具的位置节点并编号和列表保存,如图

然后,第1步:实现触摸道具并拖动时,道具跟随触摸点位置移动。

 挂载到具道具prefab上的脚本,实现跟随移动的代码:

    onLoad () {
        this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);        
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);   
        this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnd, this);   
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
        
        //初始时,武器不可见,即为不存在
        this.node.active= false;
        //根目录
        this._rootNode= this.node.getParent().getParent().getParent();
        this._rootScript= this._rootNode.getComponent("weapen_scene");            
    },

    start () {

    },

    update (dt) {

    },

    _onTouchStart(event) {
        MyLog.show("=============拖动开始=============");
       // MyLog.show(event);
        let pow=event.getLocation();//世界坐标
        let local_pow=this.node.convertToNodeSpaceAR(pow);//世界坐标转还为节点坐标   

        //记录开始的位置
        this._start_pos= cc.v2(this.node.x, this.node.y);
    },

    _onTouchMove(event) {
        MyLog.show("=============拖动持续=============");
        //MyLog.show(event);
        let pow=event.getLocation() ;//世界坐标
        //let local_pow=this.node.convertToNodeSpaceAR(pow);//世界坐标转还为节点坐标   

        //this.node.x=  local_pow.x;
        //this.node.y=  local_pow.y;

        //移动物体
        let delta=event.getDelta();
        this.node.x+=delta.x;
        this.node.y+=delta.y;              
        this.node.opacity= 100;

        //检查碰撞
        this._checkHitOther();

        //回收碰撞
        this._recoveryWeapen();
    },
    
    _onTouchEnd(event) {
        MyLog.show("=============拖动结束=============");
        //MyLog.show(event);
        let pow=event.getLocation();//世界坐标
        let local_pow=this.node.convertToNodeSpaceAR(pow);//世界坐标转还为节点坐标   

        let bRetStartPos= true;
        if (bRetStartPos) {
            MyLog.show("物体归位");
            this.node.x= this._start_pos.x;
            this.node.y= this._start_pos.y;

            MyLog.show("this._start_pos: "+ this._start_pos.x+","+this._start_pos.y);

            this.node.opacity= 255;
        }
    },
    
    _onTouchCancel(event) {
        MyLog.show("=============拖动取消=============");
        let pow=event.getLocation();//世界坐标
        let local_pow=this.node.convertToNodeSpaceAR(pow);//世界坐标转还为节点坐标   
    },   

2、在道具的触摸事件中检查移动的道具与其他道具是矩形相交,即简单的碰撞检查功能;

    //碰撞检查
    _checkHitOther() {
        let baseNode= this.node.getParent().getParent();
        //MyLog.show("baseNode.children.length= ",baseNode.children.length);
        //MyLog.show("baseNode.children: ",baseNode.children);
        for (let i = 0, ed= baseNode.children.length; i < ed; i++) {
            let wpNode = baseNode.children[i];  
            //MyLog.show("wpNode.name= ", wpNode.name);      
            //MyLog.show("this.name= ", this.node.parent.name);      
            let mv_wp_name= this.node.parent.name;
            if (wpNode.name===mv_wp_name)
                continue;

            //MyLog.show("wpNode: ",wpNode);
            let wp= wpNode.getChildByName("wp"); //被碰的
            if (!wp || wp.active===false) {
                //不可见的武器,无效的位置
                MyLog.show("忽略不可见的武器,无效的位置");
                continue;
            }

            //操作状态检查
            MyLog.show("操作状态检查:_comb_state=", this.node._comb_state);
            if (this.node._comb_state===1) { //|| wpNode._comb_state===1) {
                MyLog.show("合成操作中,不再检测碰撞");
                break;
            }

            let wp_box= wp.getBoundingBoxToWorld();
            let mv_box= this.node.getBoundingBoxToWorld();

            //MyLog.show("wp_box:",wp_box);
            //MyLog.show("mv_box:",mv_box);
            //let bHit= gameTools.RectIntersectRect(wp_box, mv_box); //这里检测区域太大了,要缩小避免误操作。
            let bHit= wp_box.contains(mv_box.center); //用中心点与矩形包含判断
            if (bHit) {
                MyLog.show("======发生碰撞=====");
                MyLog.show("wpNode.name= ", wpNode.name);      
                MyLog.show("this.name= ", this.node.parent.name);                 
                //wp.active= false;

                //检查是否满足合成条件
                let hit_wp_lv= wp.getChildByName("lvLabel").getComponent(cc.Label).string; //被碰撞的
                let mv_wp_lv= this.node.getChildByName("lvLabel").getComponent(cc.Label).string; //移动的

                if (hit_wp_lv===mv_wp_lv) {
                    MyLog.show("同等级武器,可合成");
            
                    cc.tween(wpNode)
                    .to(0.1, {scale:1.5})
                    .to(0.1, {scale:1})
                    .start();

                    //合成状态锁定
                    this.node._comb_state= 1;
                    //wpNode._comb_state= 1;

                    let wp_index= gameTools.findNumFromString(wpNode.name);
                    let mv_wp_index= gameTools.findNumFromString(mv_wp_name);
                    //合成操作
                    this._combWeapen(mv_wp_index, wp_index);
                    return;
                }

                cc.tween(wpNode)
                .to(0.1, {scale:1.3})
                .to(0.1, {scale:1})
                .start();

                //检查是否满足换位条件
                if (hit_wp_lv!==mv_wp_lv) {
                    //可以交换
                    MyLog.show("可以互换");
                    //break;
                }
                
            }else{
                //MyLog.show("------未发生碰撞");
                //wp.active= true;
            }
        }
    },

3、如果发生碰撞,则判断是否同级道具,如果是则调用方法删除或隐藏移动的道具和被碰撞的道具,生成新道具(高一级道具);

	//合成操作
	_combWeapen(wp_index, mv_wp_index) { 
        MyLog.show("合成操作");
        if (wp_index>=0 && mv_wp_index>=0) {
            let ret= this._rootScript._combWeapen(wp_index-1, mv_wp_index-1 );
            if (ret) {
                MyLog.show("合成 操作成功");
         
            } else {
                MyLog.show("合成 失败或取消");
            }
        }else{
            MyLog.show("合成失败:参数错误,");
            MyLog.show("wp_index=,", wp_index);
            MyLog.show("mv_wp_index=,", mv_wp_index);
        }	     
        //合成状态解锁
        this.node._comb_state= 0;
        //wpNode._comb_state= 0;       	
    },     

主场景中脚本方法(合成实现)

	//合成武器
	_combWeapen(wpNode_index, nx_wpNode_index) {
		MyLog.show("合成武器:wpNode_index=", wpNode_index);
		MyLog.show("nx_wpNode_index=", nx_wpNode_index);
		//_updateBaseWp(op_type , wpNode_index, wpData_index, nx_wpNode_index, nx_wpData_index)
		if (wpNode_index>=0 && nx_wpNode_index>=0) {
			let wpData_index= -1;
			let nx_wpData_index= -1;

			MyLog.show("合成前数据列表, _wpList:", this._wpList);
			for(let i=0, ed=this._wpList.length; i< ed; i++) {
				let index= this._wpList[i].wpNode_index;
				if ( index === wpNode_index) {
					wpData_index= this._wpList[i].wpData_index;
				}

				if (index === nx_wpNode_index) {
					nx_wpData_index= this._wpList[i].wpData_index;
				}	
				if (nx_wpData_index>=0 && wpData_index>=0)			
					break;
			}		
			MyLog.show("wpData_index=", wpData_index);	
			if (wpData_index<0 || wpData_index>=this._wpLv_max-1) {
				MyLog.show("非法参数,或最大等级,不可再合成");
				return false;
			}

			//更新武器节点
			let new_wpData_index= wpData_index + 1; //合成后数据编号
			MyLog.show("合成后数据编号 new_wpData_index=", new_wpData_index);	
			wpNode_index= this._updateBaseWp("comb", wpNode_index, null, nx_wpNode_index, new_wpData_index);
			if (wpNode_index<0) {
				MyLog.show("合成武器失败:", wpNode_index);
				return false;
			}

			let bSuccess= false;
			//从列表中,删除武器
			bSuccess= this._del_wpNodeData(wpNode_index);
			if (bSuccess) {
				MyLog.show("删除数据失败:wpNode_index=",wpNode_index);
			}
			bSuccess= this._del_wpNodeData(nx_wpNode_index);
			if (bSuccess) {
				MyLog.show("删除数据失败:nx_wpNode_index=",nx_wpNode_index);
			}
			//添加合成等级武器数据
			MyLog.show("合成的武器: 位置,nx_wpNode_index="+ nx_wpNode_index+", 数据,new_wpData_index=", new_wpData_index);
			this._add_wpNodeData(nx_wpNode_index, new_wpData_index);
				
			MyLog.show("合成武器成功: LV=", new_wpData_index);
		} else {
			MyLog.show("错误的武器节点编号:", wpNode_index);
			return false;
		}
		return true;
	},

最后还有回收的实现

(道具脚本)

	//回收操作
	_recoveryWeapen() {
        let btn_decompose= this._rootNode.getChildByName("btn_decompose");
        
        let rv_Box= btn_decompose.getBoundingBoxToWorld();
        let mv_box= this.node.getBoundingBoxToWorld();
        //let bHit= gameTools.RectIntersectRect(rv_Box, mv_box); //这里检测区域太大了,要缩小避免误操作。
        let bHit= rv_Box.contains(mv_box.center); //用中心点与矩形包含判断
        //this._recovery_state= 0;
        if (bHit && !btn_decompose._recovery_state) {
            btn_decompose._recovery_state= 1; //回收状态锁定
            MyLog.show("======回收,发生碰撞=====");            

            cc.tween(btn_decompose)
            .to(0.5, {scale:1.5})
            .to(0.5, {scale:1})
            .start();  
            
            let wpName= this.node.parent.name;
            let wp_index= gameTools.findNumFromString(wpName);
            MyLog.show("wp_index", wp_index);
            let ret= this._rootScript._confrimRecoveryWp(wp_index-1);
            if (ret) {
                MyLog.show("回收操作成功");
            } else {
                MyLog.show("回收失败或取消");
            }
           // this._recovery_state= 0;
        }else{
           // MyLog.show("------回收,未发生碰撞");
        }		
    },

主场景脚本部分

	//回收武器
	_recoveryWeapen(wpNode_index) {

		if (wpNode_index>=0) {
			let wpNode= this._wpNodeList[wpNode_index];
			if (wpNode) {
				//隐藏武器节点
				wpNode_index= this._updateBaseWp("del", wpNode_index);
				if (wpNode_index<0) {
					MyLog.show("删除武器失败:", wpNode_index);
					return false;
				}

				let bSuccess= false;
				let wpData_index= -1;
				//从列表中,删除武器
				for(let i=0, ed=this._wpList.length; i< ed; i++) {
					if (this._wpList[i].wpNode_index === wpNode_index) {
						wpData_index= this._wpList[i].wpData_index;
						this._wpList.splice(i, 1);						
						bSuccess= true;
						break;
					}
				}

				//回收成功,返还蛋壳
				if (bSuccess && wpData_index>=0) {
					let wpData= this.json_weapendata[wpData_index];
					//MyLog.show("回收武器,返还蛋壳:",wpData);
					let rec_price= - Math.floor(wpData.combList.dkCnt/2);
					MyLog.show("回收武器,返还半价的蛋壳:", rec_price);
					this.update_dk_show(rec_price);
				}

			} else {
				MyLog.show("无效的武器节点:", wpNode);
				return false;
			}
		} else {
			MyLog.show("错误的武器节点编号:", wpNode_index);
			return false;
		}
		return true;
	},

交换或移动位置等,大家可以按这思想去实现完善。

上面的拖动合成功能,已经应用到这个小游戏中,但没有做引导。大家可以体验一下:

欢迎做小游戏的朋友一起交流,我的QQ:31911030,添加时备注一下:“小游戏”。

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值