天天看點

Cocos Creator Joystick虛拟搖杆

UI設計部分

Cocos Creator Joystick虛拟搖杆
Cocos Creator Joystick虛拟搖杆

代碼部分

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;
        }
    }
}
           
Cocos Creator Joystick虛拟搖杆

getInputQuadrantDir()函數作用及實作

作用:搖杆模拟n向軸效果,有些遊戲中并不需要使用萬向軸,譬如馬裡奧隻需要簡單4向軸作為搖杆即可。

實作:黑色為坐标軸,紅色為象限的角平分線,當坐标落在1、2區塊時,方向确定在這兩個區塊的角平分線,再根據玩家的習慣将坐标軸旋轉,得到最終的效果.

繼續閱讀