Ⅰ, 三角函数
ox1/ox = oy1/oy (相似三角形)
二 , 关于弧度 Math.atan2 在-PI (3,4象限)到 PI(1,2象限) 之间 . 如果要在3,4象限得到正值, 则需要使用 2PI - X的方式. 角度也是一样, 代码如下:/** * 获取方向弧度 */ public getRadian(): number { if( this.dir.x == 0 && this.dir.y == 0){ return 0; } let radian: number = Math.atan2( this.dir.y ,this.dir.x ); if( radian >= 0 ) return radian; return 2*Math.PI + radian; } /** * 获取方向角度 */ public getAngle(): number{ let angle: number = this.getRadian()/ Math.PI * 180; if( angle >= 0 ) return angle; return 360 + angle; }三, 层级管理器如下
场景设计如下图, 可以看到要把stick限制在bg内需要用到相似三角形的原理, 部分代码如下:
let screenPos: Vec2 = e.getLocation();//获取屏幕坐标(stick所在的) let pos: Vec3 = (this.node.getComponent(UITransform) as UITransform).convertToNodeSpaceAR( v3( screenPos.x, screenPos.y, 0 ));//转joystick和bg一样 let len: number = Vec2.len( v2(pos.x,pos.y) );//求模 this.dir.x = pos.x / len;//cos x this.dir.y = pos.y / len;//sin y if( len > this.maxR ){ pos.x = pos.x * this.maxR/len; pos.y = pos.y * this.maxR/len; }else if( len < this.minR && this.minR > 0){ pos.x = pos.x * this.minR/len; pos.y = pos.y * this.minR/len; } this.stick.setPosition( pos.x,pos.y);
import { _decorator, Component, Node, log, EventTouch, Vec2, UITransform, Vec3, v3, v2 } from 'cc'; const { ccclass, property } = _decorator; @ccclass('JoyStickCtr') export class JoyStickCtr extends Component { @property( { type: Node } ) // @ts-ignore private stick: Node; @property private maxR: number = 128;//最大移动半径 @property private minR: number = 20;//最小移动半径 //@ts-ignore private dir: Vec2; onEnable(){ this.listener( true ); } onDisable(){ this.listener( false ); } private listener( isAdd: boolean ): void { if( isAdd ) { this.stick.on( Node.EventType.TOUCH_START, this.onTouchHandler, this); this.stick.on( Node.EventType.TOUCH_MOVE, this.onTouchHandler, this); this.stick.on( Node.EventType.TOUCH_END, this.onTouchHandler, this); this.stick.on( Node.EventType.TOUCH_CANCEL, this.onTouchHandler, this); }else{ this.stick.off( Node.EventType.TOUCH_START, this.onTouchHandler, this); this.stick.off( Node.EventType.TOUCH_MOVE, this.onTouchHandler, this); this.stick.off( Node.EventType.TOUCH_END, this.onTouchHandler, this); this.stick.off( Node.EventType.TOUCH_CANCEL, this.onTouchHandler, this); } } private onTouchHandler( e : EventTouch): void{ switch (e.type){ case Node.EventType.TOUCH_START: break; case Node.EventType.TOUCH_MOVE: let screenPos: Vec2 = e.getLocation();//获取屏幕坐标(stick所在的) let pos: Vec3 = (this.node.getComponent(UITransform) as UITransform).convertToNodeSpaceAR( v3( screenPos.x, screenPos.y, 0 ));//转joystick和bg一样 let len: number = Vec2.len( v2(pos.x,pos.y) );//求模 this.dir.x = pos.x / len;//cos x this.dir.y = pos.y / len;//sin y if( len > this.maxR ){ pos.x = pos.x * this.maxR/len; pos.y = pos.y * this.maxR/len; }else if( len < this.minR && this.minR > 0){ pos.x = pos.x * this.minR/len; pos.y = pos.y * this.minR/len; } this.stick.setPosition( pos.x,pos.y); break; case Node.EventType.TOUCH_END: case Node.EventType.TOUCH_CANCEL: this.stick.setPosition(0,0); this.dir.x = this.dir.y = 0; break; } } /** * 获取方向向量 */ public getDir(): Vec2{ return this.dir; } /** * 获取方向弧度(0~2PI) */ public getRadian(): number { if( this.dir.x == 0 && this.dir.y == 0){ return 0; } let radian: number = Math.atan2( this.dir.y ,this.dir.x ); if( radian >= 0 ) return radian; return 2*Math.PI + radian; } /** * 获取方向角度(0~360) */ public getAngle(): number{ let angle: number = this.getRadian()/ Math.PI * 180; if( angle >= 0 ) return angle; return 360 + angle; } start () { this.dir = v2(0,0); // this.listener( true ); } // update (deltaTime: number) { // // [4] // } }
注: 使用Cocos Creator 3.0.1 引擎