摇杆布局实现
摇杆功能实现
用摇杆控制主角
在本教程中我们实现一个控制主角转向并移动的虚拟摇杆。
运行效果如下:
Cocos Creator版本:2.2.0
公众号后台回复"虚拟摇杆",获取该教程完整代码下载地址:
项目文件的初始内容截图如下:
新建一个名为joystick的场景,textures文件夹中有两张图片分为作为摇杆背景和摇杆按钮,JoyStick.js中存放摇杆功能代码。
首先我们把joystick_panel图片拖到层级管理器中作为Canvas的子节点:
然后再将joystick_btn图片拖到层级管理器中,让它作为joystick_panel的子节点(这样按钮就会自动位于背景的正中央):
接着在属性检查器中设置joystick_btn宽高为60:
现在场景编辑器显示如下:
通常摇杆位于屏幕左下方,所以我们给joystick_panel节点添加一个Widget组件来固定其位置:
我们设置该节点离屏幕左边和底部的距离值都为5%:
游戏运行截图如下:
我们看到左下角的FPS信息遮挡了一些,我们在JoyStick.js中用这行代码可以把它去掉:
onLoad () {
// hide FPS info
cc.debug.setDisplayStats(false);
},
将JoyStick.js挂到joystick_panel节点上后再次运行游戏:
发现已经没有FPS信息了。
这里肯定要用到触摸事件,我们先把这部分相关代码编写完整:
onLoad () {
// hide FPS info
cc.debug.setDisplayStats(false);
// get joyStickBtn
this.joyStickBtn = this.node.children[0];
// touch event
this.node.on('touchstart', this.onTouchStart, this);
this.node.on('touchmove', this.onTouchMove, this);
this.node.on('touchend', this.onTouchEnd, this);
this.node.on('touchcancel', this.onTouchCancel, this);
},
onDestroy() {
// touch event
this.node.off('touchstart', this.onTouchStart, this);
this.node.off('touchmove', this.onTouchMove, this);
this.node.off('touchend', this.onTouchEnd, this);
this.node.off('touchcancel', this.onTouchCancel, this);
},
在onLoad方法中我们也获取了joystick_btn这个节点并存储在joyStickBtn变量中。
下面分别是onTouchStart,onTouchMove,onTouchEnd和onTouchCancel方法实现:
onTouchStart(event) {
// when touch starts, set joyStickBtn's position
let pos = this.node.convertToNodeSpaceAR(event.getLocation());
this.joyStickBtn.setPosition(pos);
},
onTouchMove(event) {
// constantly change joyStickBtn's position
let posDelta = event.getDelta();
this.joyStickBtn.setPosition(this.joyStickBtn.position.add(posDelta));
},
onTouchEnd(event) {
// reset
this.joyStickBtn.setPosition(cc.v2(0, 0));
},
onTouchCancel(event) {
// reset
this.joyStickBtn.setPosition(cc.v2(0, 0));
},
此时运行游戏,我们发现一个待完善的地方,就是按钮它可以移动到摇杆背景外:
为解决这个问题我们在update方法中添加如下代码:
update (dt) {
// get ratio
let len = this.joyStickBtn.position.mag();
let maxLen = this.node.width / 2;
let ratio = len / maxLen;
// restrict joyStickBtn inside the joyStickPanel
if (ratio > 1) {
this.joyStickBtn.setPosition(this.joyStickBtn.position.div(ratio));
}
},
为方便理解以上代码,请看下面这张图:
首先获取摇杆按钮当前所在位置坐标(x1, y1),因为这是一个向量,所以我们可以调用mag()求出该向量的长度len。也就是按钮中心到原点(摇杆背景中心)的直线长度。如果该直线长度大于摇杆背景的半径maxLen(按钮在背景外),那我们就获取超出的比例值ratio,然后让按钮当前的坐标除以它,即x1/ratio和y1/ratio,这样我们其实就得到了按钮在摇杆背景边界上时的x和y坐标。
现在运行游戏你会发现摇杆按钮被限制在了背景中:
这里的主角我们直接用粒子来代替。在层级管理器中创建一个粒子节点并重命名为player:
接着我们在properties中添加两个属性,一个是用于挂载节点,另一个用于设置主角最大移动速度:
properties: {
player: {
default: null,
type: cc.Node
},
maxSpeed: 0,
},
将player节点拖入,并设置maxSpeed属性值为10:
现在来解决主角的移动问题。首先是移动方向,我们在onLoad方法中新建一个dir变量用于存储主角移动方向:
onLoad () {
...
// Player's move direction
this.dir = cc.v2(0, 0);
...
},
读者如果玩过带摇杆功能的游戏的话,应该都知道摇杆按钮的移动方向就是主角的移动方向。而我们在onTouchMove方法中是知道主角移动后的坐标(向量)的,所以获取方向非常简单:
onTouchMove(event) {
// constantly change joyStickBtn's position
let posDelta = event.getDelta();
this.joyStickBtn.setPosition(this.joyStickBtn.position.add(posDelta));
// get direction
this.dir = this.joyStickBtn.position.normalize();
},
我们这里调用了normalize()让向量归一化(方向不变但长度为1)。
接着在update方法中设置玩家位置:
update (dt) {
...
// move Player
let dis = this.dir.mul(this.maxSpeed * ratio);
this.player.setPosition(this.player.position.add(dis));
},
this.maxSpeed *ratio表示主角移动的速度会根据摇杆按钮所移动的距离来变换。如果摇杆按钮只移动一点,那么主角移动速度就慢;如果摇杆按钮处于摇杆背景的边界处,那么移动速度就达到最大值。
然后我们再将得到的值与this.dir这个方向向量相乘,这样就可以得到朝特定方向的位移大小,最后加上主角当前位置即可。
当然我们还得限制主角移动范围,不能移动到屏幕外边:
update (dt) {
...
// move Player
let dis = this.dir.mul(this.maxSpeed * ratio);
this.player.setPosition(this.player.position.add(dis));
// restrict Player inside the Canvas
if (this.player.x > this.player.parent.width / 2)
this.player.x = this.player.parent.width / 2;
else if (this.player.x < -this.player.parent.width / 2)
this.player.x = -this.player.parent.width /2;
if (this.player.y > this.player.parent.height / 2)
this.player.y = this.player.parent.height / 2;
else if (this.player.y < -this.player.parent.height / 2)
this.player.y = -this.player.parent.height / 2;
},
这里的this.player.parent就是Canvas节点。
运行截图如下:
好,那到这里虚拟摇杆的功能就全部都实现了,希望大家有所收获!
欢迎关注我的微信公众号,发现更多有趣内容: