《Cocos Creator游戏实战》虚拟摇杆实现

虚拟摇杆实现

摇杆布局实现

摇杆功能实现

用摇杆控制主角


在本教程中我们实现一个控制主角转向并移动的虚拟摇杆。

运行效果如下:

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));
},
  • 在onTouchStart中我们通过event.getLocation()获取触摸坐标,由于这里获取到的是世界坐标,我们需要通过convertToNodeSpaceAR方法将其转换成joystick_panel节点上的坐标。转换好后,将其设置成摇杆按钮的坐标。
  • 在onTouchMove中,我们通过event.getDelta()获取手指位移距离(向量),然后加上当前摇杆按钮的坐标就得到了按钮在移动之后的坐标。
  • 在onTouchEnd和onTouchCancel中,我们还原按钮位置。

此时运行游戏,我们发现一个待完善的地方,就是按钮它可以移动到摇杆背景外:

为解决这个问题我们在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节点。

运行截图如下:

好,那到这里虚拟摇杆的功能就全部都实现了,希望大家有所收获!

欢迎关注我的微信公众号,发现更多有趣内容:

发布了83 篇原创文章 · 获赞 157 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/La_vie_est_belle/article/details/102793329