Cocos Creator 3.0 preview | Joystick Full Script example

Hello,
Can anyone give me an example of how to create Joystick on cocos creator 3.0 preview?

I found some old tutorials but never saw one for cocos creator 3.0 preview.


i was reading the documentation

this.node.on(Node.EventType.TOUCH_START, this.Joystick_Touch_Start, this);

    this.node.on(Node.EventType.TOUCH_MOVE, this.Joystick_Touch_Move, this);

    this.node.on(Node.EventType.TOUCH_END, this.Joystick_Touch_End, this);

    this.node.on(Node.EventType.TOUCH_CANCEL, this.Joystick_Touch_End, this);

and all is good, but I just need a full example script to understand it more and test it.

@Rainbowin you can refer to the rocker.scene in the demo-ui example.

export const instance = new EventTarget();

/**

  • 方向类型

*/

export enum DirectionType {

FOUR,

EIGHT,

ALL,

}

/**

  • 速度类型

*/

export enum SpeedType {

STOP,

NORMAL,

FAST,

}

/**

  • 摇杆类型

*/

export enum JoystickType {

FIXED,

FOLLOW,

}

import { _decorator, Component, Node, Enum, EventTouch, v2 } from ‘cc’;

const { ccclass, property } = _decorator;

@ccclass(‘Joystickplay’)

export class Joystickplay extends Component {

@property({

    type: Node,

    displayName: "Dot",

    tooltip: "摇杆操纵点",

  })

  dot = null;



  @property({

    type: Node,

    displayName: "Ring",

    tooltip: "摇杆背景节点",

  })

  ring = null;



  @property({

    type: Enum(JoystickType),

    displayName: "Touch Type",

    tooltip: "触摸类型",

  })

  joystickType = JoystickType.FIXED;



  @property({

    type: Enum(DirectionType),

    displayName: "Direction Type",

    tooltip: "方向类型",

  })

  directionType = DirectionType.ALL;



  @property({

    type: Node,

    tooltip: "摇杆所在位置",

  })

  _stickPos = null;



  @property({

    type: Node,

    tooltip: "触摸位置",

  })

  _touchLocation = null;



  @property({

    tooltip: "半径",

  })

  _radius = 0;

  

  onLoad() {

    this._radius = this.ring.width / 2;

    this._initTouchEvent();

    // hide joystick when follow

    if (this.joystickType === JoystickType.FOLLOW) {

      this.node._uiProps.opacity = 0;

    }

  }



  /**

   * 启用时

   */

  onEnable() {

    instance.on("set_joystick_type", this._onSetJoystickType, this);

  }



  /**

   * 禁用时

   */

  onDisable() {

    instance.off("set_joystick_type", this._onSetJoystickType, this);

  }



  /**

   * 改变摇杆类型

   * @param type

   */

  _onSetJoystickType(type: JoystickType) {

    this.joystickType = type;

    this.node._uiProps.opacity = type === JoystickType.FIXED ? 255 : 0;

  }



  /**

   * 初始化触摸事件

   */

  _initTouchEvent() {

    // set the size of joystick node to control scale

    this.node.on(Node.EventType.TOUCH_START, this._touchStartEvent, this);

    this.node.on(Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this);

    this.node.on(Node.EventType.TOUCH_END, this._touchEndEvent, this);

    this.node.on(Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this);

  }



  /**

   * 触摸开始回调函数

   * @param event

   */

  _touchStartEvent(event: EventTouch) {

    instance.emit(Node.EventType.TOUCH_START, event);



    const touchPos = this.node.convertToNodeSpaceAR(event.getLocation());



    if (this.joystickType === JoystickType.FIXED) {

      this._stickPos = this.ring.getPosition();



      // 触摸点与圆圈中心的距离

      const distance = touchPos.sub(this.ring.getPosition()).mag();



      // 手指在圆圈内触摸,控杆跟随触摸点

      this._radius > distance && this.dot.setPosition(touchPos);

    } else if (this.joystickType === JoystickType.FOLLOW) {

      // 记录摇杆位置,给 touch move 使用

      this._stickPos = touchPos;

      this.node.opacity = 255;

      this._touchLocation = event.getLocation();



      // 更改摇杆的位置

      this.ring.setPosition(touchPos);

      this.dot.setPosition(touchPos);

    }

  }



  /**

   * 触摸移动回调函数

   * @param event

   */

  _touchMoveEvent(event: EventTouch) {

    // 如果 touch start 位置和 touch move 相同,禁止移动

    if (

      this.joystickType === JoystickType.FOLLOW &&

      this._touchLocation === event.getLocation()

    ) {

      return false;

    }



    // 以圆圈为锚点获取触摸坐标

    const touchPos = this.ring.convertToNodeSpaceAR(event.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();



    let speedType;



    if (this._radius > distance) {

      this.dot.setPosition(v2(posX, posY));



      speedType = SpeedType.NORMAL;

    } 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));



      speedType = SpeedType.FAST;

    }



    instance.emit(Node.EventType.TOUCH_MOVE, event, {

      speedType: speedType,

      moveDistance: p,

    });

  }



  /**

   * 触摸结束回调函数

   * @param event

   */

  _touchEndEvent(event: cc.Event.EventTouch) {

    this.dot.setPosition(this.ring.getPosition());

    if (this.joystickType === JoystickType.FOLLOW) {

      this.node.opacity = 0;

    }



    instance.emit(Node.EventType.TOUCH_END, event, {

      speedType: SpeedType.STOP,

    });

  }

}

what is the solution for this script to make work on cocos creator 3.0

a good example but waw it made me go crazy,

the problem there is no enough resources to learn, i mean learn learn for real game development,

full script example sometimes is a good thing for new developers on cocos creator 3+

Sorry I don’t quite understand what you mean. But looking at the code, I found that you are using a lot of 2D APIs which are incompatible/deprecated in 3.0 and will definitely cause a lot of problems, we suggest you to read our official documentation first. Some of the errors are as follows:

    cc.v2(posX, posY).sub(this.ring.getPosition()) // cc.v2(posX, posY) -> Vec2, this.ring.getPosition() -> Vec3
    // convertToNodeSpaceAR (worldPoint: Vec3, out?: Vec3)
    this.node.convertToNodeSpaceAR(event.getLocation()) // event.getLocation() -> Vec2, convertToNodeSpaceAR -> this.node.getComponent(UITransform).convertToNodeSpaceAR

thanks i will try again to create a virtual joystick

convertToNodeSpaceAr won’t work on coco creator again

I’ve updated the extension from cocos store to 3.2 version. Uploaded the sample here…

https://cdn.discordapp.com/attachments/634693782822060045/862753301875392552/VirtualJoyStick.zip