JoyStick摇杆实现

牧业
2023-12-01

import { _decorator, Component, Node, EventTouch, Vec3, log, input, Input, UITransform, Vec2 } from 'cc';
const { ccclass, property } = _decorator;

/**
 * Predefined variables
 * Name = JoyStick
 * DateTime = Tue Apr 12 2022 11:34:25 GMT+0800 (中国标准时间)
 * Author = D_JJ_Brown
 * FileBasename = JoyStick.ts
 * FileBasenameNoExtension = JoyStick
 * URL = db://assets/JoyStick/Scripts/JoyStick.ts
 * ManualUrl = https://docs.cocos.com/creator/3.4/manual/zh/
 *
 */

@ccclass('JoyStick')
export class JoyStick extends Component {

    @property
    public isDynamic: boolean = false;  //是否为动态模式

    private input: Vec3 = new Vec3(0, 0);

    private joyStickBtn: Node;
    private transform: UITransform;

    onLoad() {

        this.transform = this.node.getComponent(UITransform);
        this.joyStickBtn = this.node.getChildByName('joyStickBtn');

        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.on(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    onDestroy() {
        input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.off(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    update(deltaTime: number) {

        //摇杆到中心的距离
        let len = this.joyStickBtn.position.length();
        //摇杆bg的半径
        let maxLen = this.transform.contentSize.width / 2;
        //比例
        let ratio = len / maxLen;

        //如果摇杆到中心的距离大于摇杆bg的半径,则将摇杆强制限制在摇杆bg的半径内
        if (ratio > 1) {
            this.joyStickBtn.setPosition(this.joyStickBtn.position.divide(new Vec3(ratio, ratio, 1)));
        }
    }


    private onTouchStart(event: EventTouch) {

        let localPos = new Vec3(0, 0, 0);
        let worldPos = event.getLocation();

        //如果是动态模式,则显示摇杆
        if (this.isDynamic) {
            this.node.active = true;

            //设置摇杆bg的位置
            this.node.setWorldPosition(new Vec3(worldPos.x, worldPos.y, 0));
        }

        //设置摇杆位置
        this.node.inverseTransformPoint(localPos, new Vec3(worldPos.x, worldPos.y, 0));
        this.joyStickBtn.setPosition(localPos);
    }

    private onTouchMove(event: EventTouch) {

        //设置摇杆位置
        let posDelta = event.getDelta();
        let pos = new Vec3(posDelta.x, posDelta.y, 0);
        this.joyStickBtn.setPosition(this.joyStickBtn.position.add(pos));

        //更新移动输入值
        let worldPos = event.getLocation();
        let clickPos = new Vec3(worldPos.x, worldPos.y, 0);
        var bgPos: Vec3 = this.node.worldPosition;
        let maxLen = this.transform.contentSize.width / 2;
        //摇杆中心点到触点的向量除以摇杆bg的半径得到移动方向
        this.input = (clickPos.subtract(bgPos)).divide(new Vec3(maxLen, maxLen, 1));
        // log('input: ', this.input);
    }

    private onTouchEnd(event: EventTouch) {

        if (this.isDynamic) {
            this.node.active = false;
        }

        this.joyStickBtn.setPosition(0, 0);
    }

    private onTouchCancel(event: EventTouch) {

        if (this.isDynamic) {
            this.node.active = false;
        }

        this.joyStickBtn.setPosition(0, 0);
    }

    public getInput() {
        return this.input;
    }

    public getHorizontal() {
        if (this.input.x > 1) {
            return 1;
        }
        if (this.input.x < -1) {
            return -1;
        }
        return this.input.x;
    }

    public getVertical() {
        if (this.input.y > 1) {
            return 1;
        }
        if (this.input.y < -1) {
            return -1;
        }
        return this.input.y;
    }
}
 类似资料: