123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- import CMath from "./CMath";
- /**
- * 摇杆
- */
- const { ccclass, property } = cc._decorator;
- const TouchType = cc.Enum({
- DEFAULT: 0,//摇杆固定位置
- FOLLOW: 1//摇杆跟随
- });
- const DirectionType = cc.Enum({
- FOUR: 4,
- EIGHT: 8,
- ALL: 0,
- });
- @ccclass
- export default class Joystick extends cc.Component {
- @property({
- type: TouchType,
- displayName: '触摸类型',
- })
- mTouchType = TouchType.DEFAULT;
- @property({
- type: DirectionType,
- displayName: '方向类型',
- })
- mDirectionType = TouchType.DEFAULT;
- @property(cc.Node)
- mDot: cc.Node = null;//摇杆
- @property(cc.Node)
- mRing: cc.Node = null;//摇杆底
- @property(cc.Node)
- mDir: cc.Node = null;//方向指示图
- public isDisable = false;
- private _radius: number;//半径
- private _angle: number;//当前触摸的角度
- private _distance: number = 0;//点击与中心的距离
- private tmpDir = { x: 0, y: 0 }
- /**
- * @runing 行走
- * @angle 角度
- * @distance 距离[0-1]
- */
- private callback: (move: boolean, v2: any, angle: number) => void;
- public onLoad() {
- this._radius = (this.mRing.width - this.mDot.width) / 2;
- this.mDir.opacity = 0;
- this.mDot.opacity = 100;
- this._initTouchEvent();
- }
- public stop() {
- // this.isDisable = true;
- this._touchEndEvent();
- }
- public setCallback(callback: (move: boolean, any, angle: number) => void) {
- this.callback = callback;
- }
- //对圆圈的触摸监听
- private _initTouchEvent() {
- this.node.on(cc.Node.EventType.TOUCH_START, this._touchStartEvent, this);
- this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this);
- // // 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0
- this.node.on(cc.Node.EventType.TOUCH_END, this._touchEndEvent, this);
- this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this);
- cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyPressed, this);
- cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyReleased, this);
- }
- private _touchStartEvent(event) {
- if (this.isDisable) {
- return;
- }
- // 获取触摸位置的世界坐标转换成圆圈的相对坐标(以圆圈的锚点为基准)
- let touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
- // let ringPos = this.mRing.getPosition();
- // //触摸点与圆圈中心的距离
- // let distance = this._getDistance(touchPos, ringPos);
- // //手指在圆圈内触摸,控杆跟随触摸点
- // if (this._radius > distance) {
- // this.mDot.setPosition(touchPos);
- // this.updateAngle();
- // return true;
- // }else{
- // if(this.mTouchType == TouchType.FOLLOW){
- // this.mRing.setPosition(touchPos);
- // this.mDot.setPosition(touchPos);
- // return true;
- // }
- // }
- this.mDir.opacity = 255;
- this.mDot.opacity = 255;
- if (this.mTouchType == TouchType.FOLLOW) {
- this.mRing.setPosition(touchPos);
- this.mDot.setPosition(touchPos);
- this.mDir.setPosition(touchPos);
- return true;
- }
- return false;
- }
- private _touchMoveEvent(event) {
- if (this.isDisable) {
- return;
- }
- var touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
- let ringPos = this.mRing.getPosition();
- var distance = this._getDistance(touchPos, ringPos);
- this._distance = distance;
- if (this._radius > distance) {
- this.mDot.setPosition(touchPos);
- } else {
- //控杆永远保持在圈内,并在圈内跟随触摸更新角度
- let radian = CMath.getAngle(ringPos, touchPos);
- let x = ringPos.x + Math.cos(radian) * this._radius;
- let y = ringPos.y + Math.sin(radian) * this._radius;
- this.mDot.setPosition(cc.v2(x, y));
- }
- //更新角度
- this.updateAngle();
- }
- private getDisTance(): number {
- if (this._distance > this._radius) {
- return 1;
- } else {
- return this._distance / this._radius;
- }
- }
- private _touchEndEvent() {
- this.mDot.setPosition(this.mRing.getPosition());
- this._angle = 0;
- if (this.callback) {
- this.callback(false, { x: 0, y: 0 }, 0);
- }
- this.mDir.opacity = 0;
- this.mDot.opacity = 100;
- }
- private onKeyPressed(event) {
- let keyCode = event.keyCode;
- switch (keyCode) {
- case cc.macro.KEY.w:
- case cc.macro.KEY.up:
- this.tmpDir.y = 1;
- break;
- case cc.macro.KEY.s:
- case cc.macro.KEY.down:
- this.tmpDir.y = -1;
- break;
- case cc.macro.KEY.a:
- case cc.macro.KEY.left:
- this.tmpDir.x = -1;
- break;
- case cc.macro.KEY.d:
- case cc.macro.KEY.right:
- this.tmpDir.x = 1;
- break;
- }
- this.reviseValue();
- }
- private onKeyReleased(event) {
- let keyCode = event.keyCode;
- switch (keyCode) {
- case cc.macro.KEY.w:
- case cc.macro.KEY.up:
- this.tmpDir.y = 0;
- break;
- case cc.macro.KEY.s:
- case cc.macro.KEY.down:
- this.tmpDir.y = 0;
- break;
- case cc.macro.KEY.a:
- case cc.macro.KEY.left:
- this.tmpDir.x = 0;
- break;
- case cc.macro.KEY.d:
- case cc.macro.KEY.right:
- this.tmpDir.x = 0;
- break;
- }
- this.reviseValue();
- }
- private reviseValue() {
- if (this.callback) {
- if (this.tmpDir.x == 0 && this.tmpDir.y == 0) {
- this.callback(false, { x: 0, y: 0 }, 0);
- } else {
- let angle = Math.atan2(this.tmpDir.y, this.tmpDir.x);
- this.callback(true, { x: this.tmpDir.x, y: this.tmpDir.y }, angle);
- }
- }
- }
- private updateAngle() {
- let p1 = this.mRing.getPosition();
- let p2 = this.mDot.getPosition();
- let angle = Math.atan2(p2.y - p1.y, p2.x - p1.x);
- this.mDir.angle = angle * 180 / Math.PI;
- this._angle = angle;
- let xx = this.getDir(this.mDir.angle)
- if (this.callback) {
- this.callback(true, xx, angle);
- }
- return this._angle;
- }
- //计算两点间的距离并返回
- private _getDistance(pos1: cc.Vec2, pos2: cc.Vec2) {
- return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2));
- }
- /**
- * 根据弧度获取方向
- * @param angle
- */
- private getDir(angle: number) {
- if (angle >= -30 && angle < 30) {
- return { x: 1.4, y: 0 }
- } else if (angle >= 30 && angle < 60) {
- return { x: 1, y: 1 }
- } else if (angle >= 60 && angle < 120) {
- return { x: 0, y: 1.4 }
- } else if (angle >= 120 && angle < 150) {
- return { x: -1, y: 1 }
- } else if (angle >= 150 && angle < 180) {
- return { x: -1.4, y: 0 }
- } else if (angle >= -180 && angle < -150) {
- return { x: -1.4, y: 0 }
- } else if (angle >= -150 && angle < -120) {
- return { x: -1, y: -1 }
- } else if (angle >= -120 && angle < -60) {
- return { x: 0, y: -1.4 }
- } else if (angle >= -60 && angle < -30) {
- return { x: 1, y: -1 }
- } else {
- return { x: 0, y: 0 }
- }
- }
- }
|