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

Pelagia ·
更新时间:2024-09-21
· 561 次阅读

现在很多微信小游戏或宣传能赚钱的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=0 && wpData_index>=0) break; } MyLog.show("wpData_index=", wpData_index); if (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=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,添加时备注一下:“小游戏”。


作者:honesthgx



cocos 小游戏

需要 登录 后方可回复, 如果你还没有账号请 注册新账号