欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cocos Creator Joystick虚拟摇杆

程序员文章站 2024-02-15 09:35:58
...

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