自定义虚拟摇杆组件让你一劳永逸
最近在研究虚拟摇杆实现方式的时候,发现网上的教程的实现方式可移植性并不是特别好,于是我决定自己实现一个虚拟摇杆组件,保存到自己的组件库,方便以后用到的时候直接使用(关注公众号后台回复「虚拟摇杆组件」可获取该组件),下面正文开始。
实现思路:
为了实现高度可移植,定义了两个节点属性,用于绑定场景和玩家角色,另外添加 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.可以看到已经可以流畅的控制玩家移动了:
最后:
不知道小伙伴们学会了没有,赶快来试试看吧,有什么好的建议都可以在下面评论或者私信告诉我哦!
推荐阅读:
让蔡徐坤来教你实现游戏中的帧动画(上)
让蔡徐坤来教你实现游戏中的帧动画(中)
一文教你实现「飞机大战」里战机的控制逻辑
https://www.cnblogs.com/yu97271486/p/11459189.html