import { _decorator, Component, Node, Enum, EventTouch, UITransformComponent, Vec3, view, UITransform, Vec2 } from "cc"; import { config } from "../config"; import { DirType } from "../data"; import { car } from "./car"; const { ccclass, property } = _decorator; //触摸类型 const TOUCH_TYPE = Enum({ DEFAULT: 0,//按钮和背景距离不变,背景位置与触碰点一致,不可改变按钮背景位置,按钮背景随着按钮移动而移动,松手后无法恢复到初始位置 FOLLOW: 1,//按钮和背景距离不变,背景位置与触碰点一致,不可改变按钮背景位置,按钮背景随着按钮移动而移动,松手后恢复到初始位置 FOLLOW_ALWAYS: 2, //按钮和背景距离不变,背景位置与触碰点一致,可改变按钮背景位置,按钮背景随着按钮移动而移动,松手后恢复到初始位置 FOLLOW_DOT: 3 //按钮和背景距离可改变,按钮位置与触碰点可不一致,不可改变按钮背景位置,按钮背景不随着按钮移动而移动,松手后恢复到初始位置 }); //方向 const DIRECTION_TYPE = Enum({ FOUR: 4, EIGHT: 8, ALL: 0, }); const screenHeight = view.getVisibleSize().height;//屏幕可视范围高度 @ccclass("Joystick") export class Joystick extends Component { @property({type: Node, displayName: '摇杆背景节点'}) public ndRing: Node = null!; @property({type: Node, displayName: '摇杆节点'}) public ndDot: Node = null!; @property({type: TOUCH_TYPE, displayName: '触摸类型'}) public touchType = TOUCH_TYPE.DEFAULT; @property({type: DIRECTION_TYPE, displayName: '方向类型'}) public directionType = DIRECTION_TYPE.ALL; @property({displayName: '启动半透明'}) public isEnableTransparent: boolean = false; @property({displayName: '点击跟随'}) public isFollowStart: boolean = false; @property({displayName: '内圈大小'}) public innerSize: number = 10; @property(Node) spr_dun:Node = null; public onClickCb: Function = null!; public onEndCb: Function = null!; public clearFECb: Function = null!; public onBeginFECb: Function = null!; public onSuccessFECb: Function = null!; public isMoving: boolean = false;//是否正在移动 private mCar:car = null private mDir:DirType = DirType.NONE public get distanceRate () { return this._distanceRate; } public get angle () { return this._angle; } public set angle (v: number) { this._angle = v; } private _angle: number = 0;//当前的角度 private _oriRingPos: Vec3 = null!;//圆圈初始位置 private _targetRingPos: Vec3 = new Vec3();//圆圈背景位置 private _touchStartLocation: Vec3 = new Vec3();//开始触碰位置 private _touchMoveLocation: Vec3 = new Vec3();//移动触碰位置 private _touchEndLocation: Vec3 = new Vec3();//结束触碰位置 private _isOutInnerSize: Boolean = false;//终点拖动的点是否超出按钮圆圈背景 private _distanceRate: number = 0; //遥感移动距离比 private _checkInterval: number = 0.04;//每40ms刷新一次 private _oldAngle: number = 0;//之前的角度 private _oldDotPos: number = 0; private _currentTime: number = 0;//当前累积时间 private _oriDotPos: Vec3 = new Vec3();//中间按钮初始坐标 private _movePos: Vec3 = new Vec3();//移动坐标 private _curRingPos_1: Vec3 = new Vec3();//当前圆圈坐标 private _curRingPos_2: Vec3 = new Vec3();// private _origin_pos:Vec3 = Vec3.ZERO private mCallBack = null; start () { // Your initialization goes here. } public init(call_back,car:car) { this.mCar = car this.mCallBack = call_back this.node.on(Node.EventType.TOUCH_START, this._touchStartEvent, this); this.node.on(Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this); // 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0 this.node.on(Node.EventType.TOUCH_END, this._touchEndEvent, this); this.node.on(Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this); } public unInit(){ this.node.off(Node.EventType.TOUCH_START, this._touchStartEvent, this); this.node.off(Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this); // 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0 this.node.off(Node.EventType.TOUCH_END, this._touchEndEvent, this); this.node.off(Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this); //重置 this.isMoving = false; this.ndDot.setPosition(this._oriDotPos); this._origin_pos = this._oriDotPos if (this._oriRingPos) { this.ndRing.setPosition(this._oriRingPos); } } private _touchStartEvent (event: EventTouch) { // 记录触摸的世界坐标,给touch move使用 // this.dot.opacity = 255; this._targetRingPos = null!; let touch = event.getUILocation(); this._touchStartLocation.set(touch.x, touch.y, 0); let touchPos = this.node.getComponent(UITransformComponent)?.convertToNodeSpaceAR(this._touchStartLocation) as Vec3; if (!this._oriRingPos) { this._oriRingPos = this.ndRing.getPosition().clone(); } // 记录摇杆位置,给touch move使用 // this._stickPos.set(touchPos); this._isOutInnerSize = false; if (!this.isFollowStart) { touchPos = this.ndRing.getComponent(UITransformComponent)?.convertToNodeSpaceAR(this._touchStartLocation) as Vec3; //触摸点与圆圈中心的距离 let distance = touchPos.length(); let width = this.ndRing.getComponent(UITransformComponent)?.contentSize.width as number; //圆圈半径 let radius = width / 2; //手指在圆圈内触摸,控杆跟随触摸点 if (radius > distance) { this.ndDot.setPosition(touchPos); this._updateAngle(touchPos); return true; } return false; } else { //设置遥感可移动范围 if (this.touchType === TOUCH_TYPE.FOLLOW) { touchPos.y = touchPos.y >= -screenHeight/6 ? -screenHeight/6 : touchPos.y; } this.ndRing.setPosition(touchPos); } } private _touchMoveEvent (event: EventTouch) { let touch = event.getUILocation(); this._touchMoveLocation.set(touch.x, touch.y, 0); let touchPos = this.ndRing.getComponent(UITransformComponent)?.convertToNodeSpaceAR(this._touchMoveLocation) as Vec3; // if (this.touchType === TOUCH_TYPE.FOLLOW) { // let offsetPos = cc.v3(touchPos.x - this._stickPos.x, touchPos.y - this._stickPos.y, 0); // touchPos = offsetPos; // } let dir_type = DirType.NONE if(touchPos.x>this.ndDot.position.x){ dir_type = DirType.RIGHT }else if(touchPos.x this.innerSize) { this.isMoving = true; this._isOutInnerSize = true; } else { this._isOutInnerSize = false; } let width = this.ndRing.getComponent(UITransformComponent)?.contentSize.width as number; //圆圈半径 let radius = width / 2; let rate = 0; // 由于摇杆的postion是以父节点为锚点,所以定位要加上ring和dot当前的位置(stickX,stickY) if (radius > distance) { rate = Number((distance / radius).toFixed(3)); this.ndDot.setPosition(touchPos); } else if (this.touchType !== TOUCH_TYPE.FOLLOW_DOT) { rate = 1; //控杆永远保持在圈内,并在圈内跟随触摸更新角度 let radian = Math.atan2(touchPos.y, touchPos.x); let x = Math.cos(radian) * radius; let y = Math.sin(radian) * radius; this._movePos.set(x, y, 0); if (this.touchType === TOUCH_TYPE.FOLLOW_ALWAYS) { this._curRingPos_2.set(touch.x - x, touch.y - y, 0); let ringPos = this.node.getComponent(UITransformComponent)?.convertToNodeSpaceAR(this._curRingPos_2) as Vec3; this._targetRingPos = ringPos; } this.ndDot.setPosition(this._movePos); } else { // 点跟随移动 this.ndDot.setPosition(touchPos); } //更新角度 this._updateAngle(touchPos); //更新遥感移动距离百分比 this._distanceRate = rate; } private _touchEndEvent (event: EventTouch) { if (!this.isMoving) { //可以判断为点击 this.onClickCb && this.onClickCb(); } else { let touch = event.getUILocation(); this._touchEndLocation.set(touch.x, touch.y, 0); let touchPos = this.ndRing.getComponent(UITransformComponent)?.convertToNodeSpaceAR(this._touchEndLocation) as Vec3; let isDragToInner = false; if (touchPos.length() < this.innerSize) { //取消掉 isDragToInner = true; this.onEndCb && this.onEndCb(isDragToInner); } else { this.onEndCb && this.onEndCb(isDragToInner); } } this.isMoving = false; this.mDir = DirType.NONE this.ndDot.setPosition(this._oriDotPos); this._origin_pos = this._oriDotPos if (this.touchType === TOUCH_TYPE.FOLLOW || this.touchType === TOUCH_TYPE.FOLLOW_ALWAYS || this.touchType === TOUCH_TYPE.FOLLOW_DOT) { this._targetRingPos = null!; this.ndRing.setPosition(this._oriRingPos); } } private _updateAngle (pos: Vec3) { this._angle = Math.round(Math.atan2(pos.y, pos.x) * 180 / Math.PI); return this._angle; } public reset () { this.isMoving = false; this._origin_pos = this._oriDotPos this.ndDot.setPosition(this._oriDotPos); } public getJoyInfo(){ this.mCar.setDir(this.mDir) console.log("this.mDir",this.mDir) this.mCar.setMoveSpeedX(Math.abs(this.ndDot.position.x-this._origin_pos.x)/130*50) } update (deltaTime: number) { // Your update function goes here. //设置终终点按钮位置 // if (this._targetRingPos) { // this._curRingPos_1.set(0, 0, 0); // Vec3.lerp(this._curRingPos_1, this.ndRing.position, this._targetRingPos, 20 * deltaTime); // this.ndRing.setPosition(this._curRingPos_1); // } this._currentTime += deltaTime; if (this._currentTime >= this._checkInterval) { this._currentTime = 0; if (this.isMoving) { if (this.angle !== this._oldAngle) { this._oldAngle = this.angle; } } else { this.isMoving = false; } if(this.mCallBack !=null ){ this.mCallBack() } this._oldDotPos = this.ndDot.position.x this.getJoyInfo() } } }