/** * 8方向摇杆 */ const {ccclass, property} = cc._decorator; @ccclass export default class Joystick_8d extends cc.Component { @property({ type: cc.Node, displayName: '按下显示效果', }) mTouchView: cc.Node = null; @property({ type: cc.Node, displayName: '摇杆中心', }) mCneter: cc.Node = null; @property({ type: cc.Sprite, displayName: '上', }) mUp: cc.Sprite = null; @property({ type: cc.Sprite, displayName: '下', }) mDown: cc.Sprite = null; @property({ type: cc.Sprite, displayName: '左', }) mLeft: cc.Sprite = null; @property({ type: cc.Sprite, displayName: '右', }) mRight: cc.Sprite = null; @property({ type: cc.SpriteFrame, displayName: '点击高亮', }) mTouchOn: cc.SpriteFrame = null; @property({ type: cc.SpriteFrame, displayName: '灰色', }) mTouchOff: cc.SpriteFrame = null; private tmpDir = {x:0,y:0} /** * @runing 行走 * @angle 角度 * @distance 距离[0-1] */ private callback:(dir:any)=>void; onLoad () { this.mTouchView.active = false; this._initTouchEvent(); } public setCallback(callback:(dir:cc.Vec2)=>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) { let p1 = this.node.convertToNodeSpaceAR(event.getLocation()); let p2 = this.mCneter.getPosition(); let distance = this._getDistance(p1,p2); // cc.log('distance = ',distance); if(distance > 10 &&distance < 175){ this.mTouchView.active = true; this.mTouchView.x = p1.x; this.mTouchView.y = p1.y; let angle = this._getAngle(p1,p2); let dir = this.getDir(angle); this.updateIcon(dir); if(this.callback){ this.callback(dir); } } } private _touchMoveEvent(event) { if(this.mTouchView.active){ let p1 = this.node.convertToNodeSpaceAR(event.getLocation()); let p2 = this.mCneter.getPosition(); this.mTouchView.x = p1.x; this.mTouchView.y = p1.y; let angle = this._getAngle(p1,p2); let dir = this.getDir(angle); this.updateIcon(dir); if(this.callback){ this.callback(dir); } } } private _touchEndEvent(event) { this.stop(); } 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.updateIcon(this.tmpDir); if(this.callback){ this.callback(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.updateIcon(this.tmpDir); if(this.callback){ this.callback(this.reviseValue()); } } private reviseValue(){ let pos = { x:this.tmpDir.x, y:this.tmpDir.y }; let ax = Math.abs(pos.x); let ay = Math.abs(pos.y); if(ax != ay){ if(ax == 1){ pos.x = pos.x*1.4; }else if(ay == 1){ pos.y = pos.y*1.4; } } return pos; } public stop(){ this.mTouchView.active = false; this.updateIcon(null); if(this.callback){ this.callback({x:0,y:0}); } } //计算弧度并返回 private _getAngle(p1,p2):number { return Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI); } //计算两点间的距离并返回 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} } } private updateIcon(dir){ if(dir){ if(dir.x == 0){ this.mLeft.spriteFrame = this.mTouchOff; this.mRight.spriteFrame = this.mTouchOff; }else if(dir.x > 0){ this.mLeft.spriteFrame = this.mTouchOff; this.mRight.spriteFrame = this.mTouchOn; }else{ this.mLeft.spriteFrame = this.mTouchOn; this.mRight.spriteFrame = this.mTouchOff; } if(dir.y == 0){ this.mUp.spriteFrame = this.mTouchOff; this.mDown.spriteFrame = this.mTouchOff; }else if(dir.y > 0){ this.mUp.spriteFrame = this.mTouchOn; this.mDown.spriteFrame = this.mTouchOff; }else{ this.mUp.spriteFrame = this.mTouchOff; this.mDown.spriteFrame = this.mTouchOn; } }else{ this.mLeft.spriteFrame = this.mTouchOff; this.mRight.spriteFrame = this.mTouchOff; this.mUp.spriteFrame = this.mTouchOff; this.mDown.spriteFrame = this.mTouchOff; } } }