unity程序员转Laya入门(5) 纯手写一个摇杆joystick

7 篇文章 2 订阅

laya目前没发现像unity那么多好用的插件,或者代码库。所以很多基础功能都要手写。昨天琢磨一天,写了一个摇杆算法,分享给大家。

原创不易,写代码不易,转载请注明出处!

 

写摇杆之前,先说一下理论:

摇杆三要素:

1,响应区域(一般不可见,但是会有一个范围,是摇杆操作的响应区域。一般都不会全屏都能搓摇杆)

2,摇杆底盘(也就是摇杆的那个大圈)

3,摇杆控制杆(就是摇杆中间那个小圈)

 

用Laya制作摇杆

1,分别制作上面说的摇杆三要素,如下:

显示如下:这里我把响应区域,调了一个可见颜色,也就是灰色部分。

 

写TS代码,实现摇杆功能:

代码如下:

export default class CCG_Joystick extends Laya.Script {
    /*
    设计编写:常成功
    创建时间:2021/02/20
    脚本功能:摇杆功能-Laya版
    挂载位置:摇杆响应区
    */

    /** @prop {name:stick_x, tips:"摇杆x偏移", type:Int, default:0}*/
    public stick_x: number = 0;
    /** @prop {name:stick_y, tips:"摇杆y偏移", type:Int, default:0}*/
    public stick_y: number = 0;
    // 摇杆控制杆, 最大的摇动范围-像素
    private max_px:number = 200; 


    // 基本思路是, 先要有一个摇杆响应的最大区域(例如刺激战场: 左半边屏幕), 这里我们叫: Joystick Zone
    private j_zone: Laya.Image;
    // 摇杆底盘
    private joystick: Laya.Image;
    // 摇杆控制杆
    private j_handle: Laya.Image;
    // 是否按下的变量
    private is_pressed: boolean = false;
    // 记录按下的那一刻, 鼠标的位置
    private pressed_vec2: Laya.Vector2 = new Laya.Vector2(0, 0);
    // 摇杆底盘对点击点的相对偏移量 
    private j_height_offset:number = 256;
    private j_width_offset:number = 256;
    // joystick的原始位置
    private joystick_raw_vec2: Laya.Vector2 = new Laya.Vector2(0, 0);
    // 控制杆的原生位置, 相对于父物体的坐标
    private j_handle_origin_vec2: Laya.Vector2 = new Laya.Vector2(0, 0);
    

    constructor() { super(); }
    
    onEnable(): void {
    }

    onDisable(): void {
    }

    onAwake(): void{
        console.log("Joystick Awake!"); 
        // 获取[响应区域] 
        this.j_zone = this.owner as laya.ui.Image; 
        console.log(this.j_zone);
        // 响应区域, 绑定[鼠标按下]事件处理
        this.j_zone.on(Laya.Event.MOUSE_DOWN, this, this.press_down); 
        // 从上一级(也就是整个scene), 绑定监听[鼠标抬起]事件, 以免移出范围后, 监听不到抬起事件
        let the_scene = this.owner.parent as Laya.Scene; 
        the_scene.on(Laya.Event.MOUSE_UP, this, this.release_it); 

        // 获取[摇杆-底盘] 
        let joystick_node: Laya.Node = this.owner.parent.getChildByName("image_joystick_0"); 
        this.joystick = joystick_node as Laya.Image;
        // 记录[摇杆-底盘]初始位置
        this.joystick_raw_vec2.x = this.joystick.x; 
        this.joystick_raw_vec2.y = this.joystick.y; 
        // 获取[摇杆-控制杆]
        this.j_handle = joystick_node.getChildByName("image_joystick_1") as Laya.Image; 
        // 记录[摇杆-控制杆]初始位置(相对于底盘的)
        this.j_handle_origin_vec2.x = this.j_handle.x; 
        this.j_handle_origin_vec2.y = this.j_handle.y; 

        this.j_height_offset = this.joystick.height/2; 
        this.j_width_offset = this.joystick.width/2; 

    }
 

    // 用onUpdate去处理长按屏幕的逻辑
	onUpdate()
    {
        // 如果按着屏幕滑屏 ----
        if (this.is_pressed) {
            // 当前鼠标位置, 比按下的时候, x轴的变化
            let x_offset:number = Laya.stage.mouseX - this.pressed_vec2.x; 
            let y_offset:number = Laya.stage.mouseY - this.pressed_vec2.y;
            // 更新摇杆控制杆位置 ---- 不知道为什么感觉有延迟!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            this.j_handle.pos(this.j_handle_origin_vec2.x+x_offset, this.j_handle_origin_vec2.y+y_offset, true); 

            //计算控制点在摇杆中的角度
            var dx:number = x_offset * x_offset;
            var dy:number = y_offset * y_offset;
            var angle = Math.atan2(x_offset, y_offset) * 180 / Math.PI; 
            if(angle < 0) angle += 360;
            // 对角度取整
            angle = Math.round(angle);
            // 计算控制点在摇杆中的弧度
            let radians = Math.PI / 180 * angle;
            // 算出控制杆图片应该在位置
            let pos_x: number = 0;
            let pos_y: number = 0;
            // 强制控制点与中心距离不超过指定像素值, 例如200像素
            if(dx+dy >= this.max_px*this.max_px){
                //控制点在半径为200像素的位置(根据弧度变化)
                pos_x = Math.floor(Math.sin(radians) * this.max_px +this.j_handle_origin_vec2.x);
                pos_y = Math.floor(Math.cos(radians) * this.max_px + this.j_handle_origin_vec2.y); 
            }
            else{
                // 不超过, 则取原坐标
                pos_x = this.j_handle_origin_vec2.x+x_offset;
                pos_y = this.j_handle_origin_vec2.y+y_offset; 
            }
            // 移动操纵杆
            this.j_handle.pos(pos_x, pos_y); 
            // 记录摇杆的偏移量
            this.stick_x = pos_x - this.j_handle_origin_vec2.x;
            this.stick_y = pos_y - this.j_handle_origin_vec2.y;
            console.log("stick:", this.stick_x, ",", this.stick_y);
            // 根据偏移计算,仿unity的摇杆系数(-1.0 ~ 1.0), 暂时未做 ----------
        }
    }

    // -------------- [按下鼠标后] --------------
    private press_down(e:Laya.Event): void{
        console.log("Joystick press_down");
        this.is_pressed = true;
        // 定位点在图片的左上角(laya屏幕坐标系貌似从左上角起), 所以要减去图片宽高的一半儿  
        this.joystick.pos(Laya.stage.mouseX-this.j_width_offset, Laya.stage.mouseY-this.j_height_offset);
        // 记录鼠标按下的那一刻的位置
        this.pressed_vec2.x = Laya.stage.mouseX; 
        this.pressed_vec2.y = Laya.stage.mouseY; 
    }

    // -------------- [抬起鼠标后] --------------
    private release_it(): void{
        console.log("Joystick release_it");
        this.is_pressed = false;
        // 还原[摇杆底盘]到初始化时候的位置
        this.joystick.pos(this.joystick_raw_vec2.x, this.joystick_raw_vec2.y);
        // 还原[摇杆控制杆]到初始化时候的位置
        this.j_handle.pos(this.j_handle_origin_vec2.x, this.j_handle_origin_vec2.y);
        // 记录控制杆的偏移量为0
        this.stick_x = 0;
        this.stick_y = 0;
    } 

}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值