UI設計部分
代碼部分
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, function (event) {
this.init()
}, 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;
}
}
}
getInputQuadrantDir()函數作用及實作
作用:搖杆模拟n向軸效果,有些遊戲中并不需要使用萬向軸,譬如馬裡奧隻需要簡單4向軸作為搖杆即可。
實作:黑色為坐标軸,紅色為象限的角平分線,當坐标落在1、2區塊時,方向确定在這兩個區塊的角平分線,再根據玩家的習慣将坐标軸旋轉,得到最終的效果.