分享手机端摇杆+按钮的操作代码,欢迎讨论

代码借鉴了论坛上的开源代码,完成的功能是摇杆控制角色移动,按钮可以自定义功能(代码里面有我自己写的一些功能,看懂了直接改代码就行),我设置的按钮最多有两个,有一些按钮是有蓄力功能,应该可以扩展。有问题可以在下方留言,希望大佬批评建议。

主要代码如下:

import JoystickCommon from 'JoystickCommon'
cc.Class({
  extends: cc.Component,

  properties: {
    dot: {
      default: null,
      type: cc.Node,
      displayName: 'Dot',
      tooltip: '摇杆操纵点',
    },
    ring: {
      default: null,
      type: cc.Node,
      displayName: 'Ring',
      tooltip: '摇杆背景节点',
    },

    playerAllInfo: {
      default: null,
      type: cc.Node,
      displayName: 'PlayerAllInfo',
      tooltip: '操控角色',
    },
    haveButton_01:false,
    button_01:{
      type: cc.Node,
      default: null,
      tooltip: '右边第一按钮',
      visible(){
        return (this.haveButton_01===true);
      }
    },
    haveButton_02:false,
    button_02:{
      type: cc.Node,
      default: null,
      tooltip: '右边第二按钮',
      visible(){
        return (this.haveButton_02===true);
      }
    },
    _stickPos: {
      default: null,
      type: cc.Node,
      tooltip: '摇杆所在位置',
    },
    _touchLocation: {
      default: null,
      type: cc.Node,
      tooltip: '触摸位置',
    },
    _isThrow:false,
    _isUpForTime:false,
    _moveArray:[],
    _moveIDArray:[],
    _button_01Array:[],
    _button_01IDArray:[],
    _button_02Array:[],
    _button_02IDArray:[],
    width:0,
    height:0,
  },
  //需要将父节点对象的大小设定为屏幕大小,并且在节点上加上wigth组件
  onLoad() {
    this.width=cc.winSize.width;
    this.height=cc.winSize.height;
    this.ring.setPosition(-this.width/2+235,-this.height/2+170);
    this.dot.setPosition(-this.width/2+235,-this.height/2+170);
    if(this.haveButton_02===false){
      this.button_01.setPosition(this.width/2-235,-this.height/2+170);
    }
    else{
      this.button_01.setPosition(this.width/2-120,-this.height/2+180);
      this.button_02.setPosition(this.width/2-250,-this.height/2+80);
    }
    this._radius = this.ring.width / 2;
    this._initTouchEvent();
    this._playerAllInfo=this.playerAllInfo.getComponent("PlayerMove");
    //固定摇杆位置
    this._stickPos = this.ring.getPosition();
  },

  _initTouchEvent() {
    const self = this;
    self.node.on(cc.Node.EventType.TOUCH_START, self._touchStartEvent, self);
    self.node.on(cc.Node.EventType.TOUCH_MOVE, self._touchMoveEvent, self);
    self.node.on(cc.Node.EventType.TOUCH_END, self._touchEndEvent, self);
    self.node.on(cc.Node.EventType.TOUCH_CANCEL, self._touchEndEvent, self);
  },

  _touchStartEvent(event) {
    var startTouchNow=event.touch;
    if(this.button_01.getBoundingBoxToWorld().contains(startTouchNow.getLocation())){
      this._button_01Array.push(startTouchNow);
      this._button_01IDArray.push(startTouchNow.getID());
    }
    else if( this.button_02!==null&&this.button_02.getBoundingBoxToWorld().contains(startTouchNow.getLocation())){
      this._button_02Array.push(startTouchNow);
      this._button_02IDArray.push(startTouchNow.getID());
    }
    else{
      this._moveArray.push(startTouchNow);
      this._moveIDArray.push(startTouchNow.getID());
    }
    //点击不同的右按钮进行相应的动作
    if (this._button_01Array[0]&&this.button_01.getBoundingBoxToWorld().contains(this._button_01Array[0].getLocation())) {
      this.button_01.opacity=255;
      if(this.button_01.name==="Button_Up"){
        this._playerAllInfo._Up=true;
      }
      else if(this.button_01.name==="Button_Sprint"){
        this._playerAllInfo._Sprint=true;
      }
      else if(this.button_01.name==="Button_Long"){
        this._playerAllInfo._long=true;
      }
      else if(this.button_01.name==="Button_ZhongQiuUp"){
        this._playerAllInfo._ZhongQiuUp=true;
      }
      else if(this.button_01.name==="Button_UpForTime"){
        this._isUpForTime=true;
        this._playerAllInfo._upForTime=true;
      }
    }
    if(this.button_02!==null){
      if (this._button_02Array[0]&&this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())) {
        if(this.haveButton_02===true){
          this.button_02.opacity=255;
          if(this.button_02.name==="Button_Throw"){
            this._isThrow=true;
            this._playerAllInfo._throw=true;
          }
        }
      }
    }
    //End
    //从世界坐标转换为节点坐标系
    const touchPos = this.node.convertToNodeSpaceAR(this._moveArray[0].getLocation());
    // 触摸点与圆圈中心的距离
    const distance = touchPos.sub(this.ring.getPosition()).mag();
    const p =cc.v2(touchPos.x,touchPos.y).sub(this.ring.getPosition()).normalize();
    // 手指在圆圈内触摸,控杆跟随触摸点
    if (this._radius > distance) {
      this.dot.setPosition(touchPos);
    }
    else{
        const x = this._stickPos.x + p.x * this._radius;
        const y = this._stickPos.y + p.y * this._radius;
        this.dot.setPosition(cc.v2(x, y));
    }
    this._playerAllInfo.moveDir = p;
    this._playerAllInfo._speedType = JoystickCommon.SpeedType.NORMAL;
  },






  _touchMoveEvent(event) {
    //判断点击的地方是不是在button对应的区域中,如果在button的区域中就不让左摇杆产生作用
    if (this._button_01Array[0]&&this.button_01.getBoundingBoxToWorld().contains(this._button_01Array[0].getLocation())) {
      if(this.haveButton_01===true){
        this.button_01.opacity=255;
        if(this.button_01.name==="Button_UpForTime"&&this._isUpForTime===true){
          this._isUpForTime=true;
          this._playerAllInfo._upForTime=true;
        }
      }
    }
    //如果在移动过程中移出了按钮的范围,就直接结束计时
    if(this.button_02!==null){
      if (this._button_02Array[0]&&this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())) {
        this.button_02.opacity=255;
        if(this.button_02.name==="Button_Throw"&&this._isThrow){
          this._playerAllInfo._throw=true;
        }
      }
      else if(this._button_02Array[0]&&!this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())&&this._isThrow){
        this.button_01.opacity=128;
        this.button_02.opacity=128;
        this._playerAllInfo._throw=false;
        this._isThrow=false;
      }
    }
    //End
    // 以圆圈为锚点获取触摸坐标
    if(this._moveArray[0]){
      
      const touchPos = this.ring.convertToNodeSpaceAR(this._moveArray[0].getLocation());
      const distance = touchPos.mag();

      // 由于摇杆的 postion 是以父节点为锚点,所以定位要加上 touch start 时的位置
      const posX = this._stickPos.x + touchPos.x;
      const posY = this._stickPos.y + touchPos.y;

      // 归一化
      const p = cc.v2(posX, posY).sub(this.ring.getPosition()).normalize();

      if (this._radius > distance) {
        this.dot.setPosition(cc.v2(posX, posY));
      } else {
        // 控杆永远保持在圈内,并在圈内跟随触摸更新角度
        const x = this._stickPos.x + p.x * this._radius;
        const y = this._stickPos.y + p.y * this._radius;
        this.dot.setPosition(cc.v2(x, y));
      }
      //向Player对象传递方向
      this._playerAllInfo.moveDir = p;
      //想Player对象传递速度
      this._playerAllInfo._speedType = JoystickCommon.SpeedType.NORMAL;
    }
  },





  _touchEndEvent(event) {
    if(this.button_01!==null){
      this.button_01.opacity=128;
      if(this.button_01.name==="Button_UpForTime"){
        this._isUpForTime=false;
        this._playerAllInfo._upForTime=false;
      }
    }
    if(this.button_02!==null){
        this.button_02.opacity=128;
        if(this.button_02.name==="Button_Throw"){
          this._isThrow=false;
          this._playerAllInfo._throw=false;
        }
    }
    //如果是中秋或者重阳节,那么玩家松开摇杆的默认方向是0,0
    if(cc.director.getScene().name==="Festival_ZhongQiu"||cc.director.getScene().name==="Festival_ChongYang"){
      this._playerAllInfo.moveDir=cc.v2(0,0);
    }
    this._playerAllInfo._speedType = JoystickCommon.SpeedType.STOP;

    //如果手指结束触摸了,就从三个数组中找到这个手指的信息并删除
    for (let i = 0; i < this._moveIDArray.length; i++) {
      if (this._moveIDArray[i]===event.touch.getID()) {
        this._moveArray.splice(i,1);
        this._moveArray.splice(i,1);
        if(this._moveArray.length===0){
          this.dot.setPosition(this.ring.getPosition());
        }
      }
    }
    for (let i = 0; i < this._button_01IDArray.length; i++) {
      if (this._button_01IDArray[i]===event.touch.getID()) {
        this._button_01Array.splice(i,1);
        this._button_01Array.splice(i,1);
      }
    }
    for (let i = 0; i < this._button_02IDArray.length; i++) {
      if (this._button_02IDArray[i]===event.touch.getID()) {
        this._button_02Array.splice(i,1);
        this._button_02Array.splice(i,1);
      }
    }
  },
});

JoystickCommon代码如下:

export default {
  SpeedType: cc.Enum({
    STOP: 0,
    NORMAL: 1
  }),
};
1赞