天天看点

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区块时,方向确定在这两个区块的角平分线,再根据玩家的习惯将坐标轴旋转,得到最终的效果.

继续阅读