摇杆控制角色移动 摇杆封装 绝对好用

先看效果

本文分为两个部分

如何使用
原理讲解

如何使用

一共需要四个节点

  • bg:作为背景

在这里插入图片描述

  • joystick:作为摇杆的点

在这里插入图片描述

  • player:角色(我这里拿一个小坦克当角色,因为坦克可以更直观的观察角色的旋转)

在这里插入图片描述

  • parent:作为摇杆(joystick)和背景(bg)的父节点 这是一个空节点,我们就把脚本挂在这个节点上

写脚本
先来介绍下属性(不包括刚刚说的那四个节点)

  • max_R
    类型是 number
    摇杆移动的最大半径

  • speed
    类型是 number
    玩家移动速度
    不建议太大,1-10最好

  • rotation
    类型是 number
    玩家的旋转角度

  • vector
    类型是cc.Vec2
    移动向量,通过修改这个平面向量来控制角色的移动

  • is_rotation
    类型是 Boolean
    角色是否根据摇杆的方向旋转

  • is_forbidden
    类型是 Boolean
    是否禁用摇杆
    禁用后摇杆将不能使用

新建一个脚本,把下面的代码复制粘贴到里面

const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    @property(cc.Node)
    bg: cc.Node = null;//摇杆背景

    @property(cc.Node)
    joystick: cc.Node = null;//摇杆 也就是中心点

    @property(cc.Node)
    player: cc.Node = null;//角色

    @property(cc.Node)
    parent: cc.Node = null;//摇杆和背景的父节点

    @property
    max_R: number = 135;//摇杆移动的最大半径

    @property
    speed: number = 10;//角色移动速度
    //不建议太大,1-10最好

    @property
    rotation: number = 0;//角色的旋转角度 不要轻易改

    @property
    vector: cc.Vec2 = cc.v2(0,0);//移动向量

    @property
    is_rotation: boolean = true;//角色是否根据摇杆的方向旋转

    @property
    is_forbidden: boolean = false;//是否禁用摇杆

    onLoad(){
        //绑定事件
        //因为摇杆很小,如果给摇杆绑定事件玩家将很难控制,摇杆的背景比较大,所以把事件都绑定在背景上是不错的选择
        this.bg.on(cc.Node.EventType.TOUCH_MOVE,this.move,this);//当手指在背景上移动时触发move事件
        this.bg.on(cc.Node.EventType.TOUCH_MOVE,this.move_palyer,this);//当手指在背景上移动时触发move_player事件
        this.bg.on(cc.Node.EventType.TOUCH_END,this.finish,this);//当手指在目标节点区域内离开屏幕时触发finish事件
        this.bg.on(cc.Node.EventType.TOUCH_CANCEL,this.finish,this);//当手指在目标节点区域外离开屏幕时触发finish事件
    }

    update(){
        let x = this.player.x + this.vector.x;
        let y = this.player.y + this.vector.y;//每帧获取角色的坐标加上移动向量

        this.player.position = cc.v3(x, y);//让角色的坐标每帧为自身的坐标加上移动的向量
        
        //求出角色的旋转角度
        if(this.vector.y < 0){//当摇杆在原点下方时
            //角度是负的
            this.rotation = (-this.vector.angle(cc.v2(1, 0))) / Math.PI * 180;//根据向量先求出弧度,再求出角度
        }else{//如果摇杆在原点上方时
            //角度是正的
            this.rotation = (this.vector.angle(cc.v2(1, 0))) / Math.PI * 180;//根据向量先求出弧度,再求出角度
        }
    }

    move(event: cc.Event.EventTouch){//负责移动摇杆 手指移动时调用
        if(this.is_forbidden == false){//如果没有禁用摇杆
            let pos = new cc.Vec2(event.getLocationX(), event.getLocationY());//获取触点的坐标
            let pos_0 = this.parent.convertToNodeSpaceAR(pos);//将一个点转换到节点 (局部) 空间坐标系,这个坐标系以锚点为原点。

            //pos_0.mag()是这个触点的长度

            if(pos_0.mag() < this.max_R){//如果触点长度小于我们规定好的最大半径
                this.joystick.x = pos_0.x;//摇杆的坐标为触点坐标
                this.joystick.y = pos_0.y;
            }else{//如果不
                let pos = pos_0.normalizeSelf();//将触点归一化
                let x = pos.x * this.max_R;//归一化的触点坐标 × 最大半径
                let y = pos.y * this.max_R;

                this.joystick.x = x;//给摇杆坐标赋值
                this.joystick.y = y;
            }    
        }
    }

    move_palyer(){//负责移动角色 手指移动时调用
        if(this.is_forbidden == false){//如果没有禁用摇杆
            let dir = this.joystick.position.normalizeSelf();//dir为摇杆坐标的归一化

            this.vector.x = dir.x * this.speed;//给移动向量赋值
            this.vector.y = dir.y * this.speed;//移动向量为方向 × 速度
            if(this.is_rotation == true){//如果角色可以旋转
                this.player.angle = this.rotation;//根据摇杆的方向旋转角色
            }
        }
    }

    finish(){//摇杆弹回原位置
        //摇杆坐标和移动向量都为(0,0)
        this.joystick.position = cc.v3(0, 0);
        this.vector = cc.v2(0, 0);
    }

}

绑定好节点

原理讲解

每句代码我都写了详细的注释哦

先来实现摇杆的移动


这就是表现上的内容,在拉动摇杆的时候角色并没有动,只是摇杆在动,先来实现这个

需要给背景绑定事件,其实应该给摇杆绑定事件,因为摇杆很小,如果给摇杆绑定事件玩家将很难控制,摇杆的背景比较大,所以把事件都绑定在背景上是不错的选择


这就是给背景绑定的事件,当手指在背景上移动时触发

首先获取触点坐标,转化为parent节点局部空间坐标系
我们只希望摇杆在规定好的max_R(最大半径)的范围内,不希望摇杆超出这个范围
所以要判定一下触点的坐标在不在我们制定的最大半径范围内,通过mag获取触点坐标的长度,也就是触点距离原点的长度


比如我想求点A坐标的长度,求出的结果就是绿色线段的长度

再来实现功能内容(控制角色移动)


把摇杆的坐标归一化,然后 × 速度,赋值给vector,如果可以旋转还要让角色旋转

update


根据vector求出夹角弧度,再求出角度,判断角度正负
公式
角度转弧度 π/180×角度
弧度变角度 180/π×弧度

最后一定要在松开摇杆时让摇杆弹回原处
在这里插入图片描述

源码在群里面
Cocos技术交流Q群:1130122408
欢迎进群闲聊、技术交流都欢迎
制作不易,感谢你的观看
Thank You~~

24赞

mark…

1赞

厉害厉害,mark一下

mark:palm_tree:

正好需要,以申请加群

mark!

mark [摇杆]

不错!!!!

mark!!

好东东,正 需要,感谢 了

流啤流啤,mark一下

mark!

路过插眼mark

我觉得将玩家移动和转向逻辑这些业务逻辑,写到摇杆里面的做法并不好,比如说加个加速buff,禁锢什么的,都要修改摇杆里面的代码。好的做法应该是把vector和rotation用回调或者事件抛出来,就可以很方便的复用了

说得有道理,有空整理整理再加个3D版本的摇杆

mark一下

mark~

mark!