最近在研究虚拟摇杆实现方式的时候,发现网上的教程的实现方式可移植性并不是特别好,于是我决定自己实现一个虚拟摇杆组件,保存到自己的组件库,方便以后用到的时候直接使用(关注公众号后台回复「虚拟摇杆组件」可获取该组件),下面正文开始。
实现思路:
为了实现高度可移植,定义了两个节点属性,用于绑定场景和玩家角色,另外添加 PlayerNodeSpeed 属性和 MaxR 属性用于控制玩家移动速度和摇杆节点的移动范围。
实现过程:
1.首先创建一个空节点 Rocker,下面挂载上虚拟摇杆的背景 rockerBg 和摇杆节点 joystick:
2.然后给创建好节点添加合适的虚拟摇杆资源,没有资源的小伙伴可以关注公众号后台回复「虚拟摇杆」获取多套美术资源:
3.之后编写脚本如下,代码中已经尽可能详细做好了备注,如果仍有不清楚的小伙伴可以后台私信我,看到后我会及时回复的:
1 // Rocker.js 2 3 cc.Class({ 4 extends: cc.Component, 5 6 properties: { 7 sceneNode: { // 场景节点 8 type: cc.Node, 9 default: null, 10 }, 11 12 playerNode: { // player节点 13 type: cc.Node, 14 default: null, 15 }, 16 17 playerNodeSpeed: 100, // player移动速度 18 19 Max_r: 100, // 摇杆移动半径,根据自己美术资源进行调整 20 }, 21 22 onLoad() { 23 // 隐藏摇杆组件节点 24 this.node.active = false; 25 26 // 获取摇杆节点并初始化摇杆节点位置及角度 27 this.joystick = this.node.getChildByName('joystick') 28 this.joystick.setPosition(cc.v2(0, 0)); 29 this.dir = cc.v2(0, 0); 30 31 // 注册父节点的 touch 监听事件 32 this.sceneNode.on(cc.Node.EventType.TOUCH_START, this.cbTouchStart, this); 33 this.sceneNode.on(cc.Node.EventType.TOUCH_MOVE, this.cbTouchMove, this); 34 this.sceneNode.on(cc.Node.EventType.TOUCH_END, this.cbTouchEnd, this); 35 this.sceneNode.on(cc.Node.EventType.TOUCH_CANCEL, this.cbTouchCancel, this); 36 }, 37 38 update(dt) { 39 if (this.dir.mag() < 0.5) { 40 return; 41 } 42 43 let vx = this.dir.x * this.playerNodeSpeed; 44 let vy = this.dir.y * this.playerNodeSpeed; 45 46 let sx = vx * dt; 47 let sy = vy * dt; 48 //移动 49 this.playerNode.x += sx; 50 this.playerNode.y += sy; 51 52 let windowsSize = cc.winSize; 53 54 let minX = -windowsSize.width / 2 + this.playerNode.width / 2; // 最小X坐标 55 let maxX = Math.abs(minX); // 最大X坐标 56 let minY = -windowsSize.height / 2 + this.playerNode.height / 2; // 最小Y坐标 57 let maxY = Math.abs(minY); // 最大Y坐标 58 59 let currentPos = this.playerNode.getPosition(); 60 61 if (currentPos.x < minX) { 62 currentPos.x = minX; 63 } else if (currentPos.x > maxX) { 64 currentPos.x = maxX; 65 } 66 67 if (currentPos.y < minY) { 68 currentPos.y = minY; 69 } else if (currentPos.y > maxY) { 70 currentPos.y = maxY; 71 } 72 73 this.playerNode.setPosition(currentPos); 74 75 //方向计算 76 var r = Math.atan2(this.dir.y, this.dir.x); 77 var degree = r * 180 / (Math.PI); 78 degree = 360 - degree + 90; 79 this.playerNode.rotation = degree; 80 }, 81 82 cbTouchStart(event) { 83 let pos = event.getLocation(); 84 85 // 点击时显示摇杆组件节点并设置位置 86 this.node.active = true; 87 let rPos = this.sceneNode.convertToNodeSpaceAR(pos); // 将世界坐标转化为场景节点的相对坐标 88 this.node.setPosition(rPos); 89 90 // 初始化摇杆节点位置及角度 91 this.joystick.setPosition(cc.v2(0, 0)); 92 this.dir = cc.v2(0, 0); 93 }, 94 95 cbTouchMove(event) { 96 var pos = event.getLocation(); 97 98 var jPos = this.node.convertToNodeSpaceAR(pos); // 将世界坐标转化为摇杆组件节点的相对坐标 99 100 // 获取摇杆的角度 101 let len = jPos.mag(); 102 this.dir.x = jPos.x / len; 103 this.dir.y = jPos.y / len; 104 105 // 设置摇杆的位置 106 if (len > this.Max_r) { 107 jPos.x = this.Max_r * jPos.x / len; 108 jPos.y = this.Max_r * jPos.y / len; 109 } 110 this.joystick.setPosition(jPos); 111 }, 112 113 cbTouchEnd(event) { 114 // 初始化摇杆节点位置及角度 115 this.joystick.setPosition(cc.v2(0, 0)); 116 this.dir = cc.v2(0, 0); 117 this.node.active = false; 118 }, 119 120 cbTouchCancel(event) { 121 // 初始化摇杆节点位置及角度 122 this.joystick.setPosition(cc.v2(0, 0)); 123 this.dir = cc.v2(0, 0); 124 this.node.active = false; 125 } 126 });
4.最后将写好的脚本挂载到 Rocker 节点上保存为 Prefab 就可以使用了:
使用步骤:
1.创建好场景和玩家角色后,将 Rocker 组件拖到场景中,并将 Canvas 和 玩家角色挂载到对应的位置,设置好合适的移动速度和摇杆移动半径后就可以使用了:
2.可以看到已经可以流畅的控制玩家移动了:
最后:
不知道小伙伴们学会了没有,赶快来试试看吧,有什么好的建议都可以在下面评论或者私信告诉我哦!
推荐阅读:
让蔡徐坤来教你实现游戏中的帧动画(上)
让蔡徐坤来教你实现游戏中的帧动画(中)
一文教你实现「飞机大战」里战机的控制逻辑
我是「Super于」,立志做一个每天都有正反馈的人!