UI设计部分
@H_404_2@ @H_404_2@代码部分
import {Vec2Pool} from "../../Common/Pools/Vec2Pool"; const {ccclass,property} = cc._decorator; @ccclass export class Joystick extends cc.Component { @property(cc.Integer) anglePreDirQuadrant:number = 23;//每个象限的大小 @property(cc.Node) fixedPoint:cc.Node; @property(cc.Node) movePoint:cc.Node; @property({default:100}) movePointMoveRadius:number=100; private touchID:number;//触摸事件ID(多点触控) private touchArea:cc.Vec2;//触摸区域大小 private fixedPointMoveCenterPos:cc.Vec2;//固定点移动中心 private fixedPointMoveRadius:number;//固定点移动半径 private movePointMoveCenterPos:cc.Vec2;//移动点移动中心 private joystickInputDir:cc.Vec2; onLoad() { let nodeSize = this.node.getContentSize() this.touchArea = new cc.Vec2(nodeSize.width,nodeSize.height) //固定点位置范围 this.fixedPointMoveCenterPos = this.touchArea.divƒ) this.fixedPointMoveRadius = this.touchArea.x/2 - this.movePointMoveRadius; this.node.on(cc.Node.EventType.TOUCH_START,function (event:cc.Event.EventTouch) { if (this.touchID==-1){ //触摸位置 let touchStartPos = event.getLocation() let _pos = new cc.Vec2(touchStartPos.x,touchStartPos.y) _pos.subSelf(this.node.position) //控制位置 let pos = this.clampPos(_pos,this.fixedPointMoveCenterPos,this.fixedPointMoveRadius) this.movePointMoveCenterPos = pos; //设置固定点位置 this.setFixedPointPos(pos) this.setMovePointPos(pos) this.touchID = event.getID() } },this) this.node.on(cc.Node.EventType.TOUCH_MOVE,function (event:cc.Event.EventTouch) { if (this.touchID==event.getID()){ //触摸位置 let nowPos = event.getLocation() let _pos = new cc.Vec2(nowPos.x,nowPos.y) _pos.subSelf(this.node.position) //控制位置 let pos = this.clampPos(_pos,this.movePointMoveCenterPos,this.movePointMoveRadius) //设置固定点位置 this.setMovePointPos(pos) } },this) this.node.on(cc.Node.EventType.TOUCH_END,function (event) { this.init() },this) this.node.on(cc.Node.EventType.TOUCH_CANCEL,this) this.init() } /** * 初始化 */ init(){ this.touchID = -1; this.joystickInputDir = new cc.Vec2() this.setFixedPointPos(this.fixedPointMoveCenterPos) this.setMovePointPos(this.fixedPointMoveCenterPos) } /** * 设置固定点位置 */ public setFixedPointPos(pos:cc.Vec2){ this.fixedPoint.setPosition(pos) } /** * 获取固定点位置 */ public getFixedPointPos(){ return this.fixedPoint.getPosition() } /** * 设置移动点位置 */ public setMovePointPos(pos:cc.Vec2){ this.movePoint.setPosition(pos) } /** * 获取移动点位置 */ public getMovePointPos(){ return this.movePoint.getPosition() } /** * 圆形限制,防止溢出 * @param pos 需要固定位置 * @param centerPos 限制中心位置 * @param radius 限制半径 */ public clampPos(pos:cc.Vec2,centerPos:cc.Vec2,radius:number):cc.Vec2{ let dpos = pos.sub(centerPos) if (dpos.mag()>radius){ return dpos.normalize().mul(radius).add(centerPos) }else{ return pos; } } /** * 获取摇杆输入方向 */ public getInputDir():cc.Vec2{ let dir = this.movePoint.getPosition().sub(this.fixedPoint.getPosition()) if (dir.mag()>0){ dir.normalizeSelf() } return dir; } /** * 获取摇杆象限输入方向(轴) */ public getInputQuadrantDir():cc.Vec2{ return this.getVec2ByQuadrant(this.getDirQuadrant(this.getInputDir())) } /** * 获取方向所在象限 * @param vec 方向 */ public getDirQuadrant(vec:cc.Vec2):number{ let dirQuadrant:number = null; if (vec.mag()>0){ //非零向量 dirQuadrant = Math.floor(this.getAngleByVec2(vec)/this.anglePreDirQuadrant) } //console.log(this.getAngleByVec2(vec),dirQuadrant) return dirQuadrant; } /** * 二维方向获取角度 * @param vec 方向 */ public getAngleByVec2(vec:cc.Vec2):number{ return -Math.atan2(vec.y,vec.x)*鳴/Math.PI) + this.anglePreDirQuadrant/2;//this.anglePreDirQuadrant/2 用于旋转坐标系 } /** * 角度获取二位方向 * @param angle */ public getVec2ByAngle(angle:number):cc.Vec2 { let dir:cc.Vec2=new cc.Vec2() let rad:number = (this.anglePreDirQuadrant/2-angle)*(Math.PI/180)//this.anglePreDirQuadrant/2 用于旋转坐标系 dir.x=Math.cos(rad) dir.y=Math.sin(rad) return dir.normalizeSelf() } /** * 根据方向象限获取角度 * @param dirQuadrant */ public getVec2ByQuadrant(dirQuadrant:number):cc.Vec2{ if (dirQuadrant!=null){ let angle:number = dirQuadrant*this.anglePreDirQuadrant; //获取象限的中心轴向 angle+=this.anglePreDirQuadrant/2; return this.getVec2ByAngle(angle) }else{ return cc.Vec2.ZERO; } } }
@H_404_2@ 作用:摇杆模拟n向轴效果,有些游戏中并不需要使用万向轴,譬如马里奥只需要简单4向轴作为摇杆即可。 @H_404_2@ 实现:黑色为坐标轴,红色为象限的角平分线,当坐标落在1、2区块时,方向确定在这两个区块的角平分线,再根据玩家的习惯将坐标轴旋转,得到最终的效果.