unity 中实现摇杆

作者:雨辰 发布于:2015-1-19 16:00 Monday 分类:Unity3D

 
//锁定摇杆在固定半径范围内运动 并同时获取摇杆手指滑动下面的碰撞提的物体对象
using UnityEngine;
using System.Collections;

public class JoyControl : UIDragDropItem
{
    public GameObject obj;
    public GameObject selectSprte1;
    public GameObject selectSprte2;

    public TweenScale selectObj1;
    public TweenScale selectObj2;

    public float joyMoveDistance;        // 摇杆最大可移动的距离 
    private float joyInitX;                        // 摇杆的圆心初始坐标X 
    private float joyInitY;                        // 摇杆的圆心初始坐标Y 
    
    private float currentDistance;        // 单签摇杆圆心离初始圆心的距离 
    private float joyControlDistance = 5.0f ;        // 摇杆开始控制坦克移动的最小距离 
    private float mousePositionX;        // 鼠标相对NGUI坐标系的坐标X 
    private float mousePositionY;        // 鼠标相对NGUI坐标系的坐标X 

    public System.Action<DMGame.ESelectBtn> callback;

    private Vector3 objVec;
    protected override void Start()
    {
        base.Start();
        objVec = obj.transform.localPosition;
        joyInitX = this.transform.localPosition.x;
        joyInitY = this.transform.localPosition.y;
        mousePositionX = this.transform.localPosition.x;
        mousePositionY = this.transform.localPosition.y;
    }

    void Update()
    {
        if (obj == null)
        {
            return;
        }

        if (obj.transform.localPosition == objVec)
        {
            selectSprte1.SetActive(false);
            selectSprte2.SetActive(false);
            selectObj1.enabled = false;
            selectObj1.transform.localScale = Vector3.one;
            selectObj2.enabled = false;
            selectObj2.transform.localScale = Vector3.one;
            obj.transform.localScale = Vector3.one;

            obj.GetComponent<UISprite>().alpha = 1f;
            return;
        }
    }

    protected override void OnDragDropMove(Vector3 delta)
    {
        base.OnDragDropMove(delta);

        GameObject gameObj = UICamera.hoveredObject;
        if (gameObj != null)
        {
            if (gameObj.name == "SelectBox1")
            {
                selectSprte1.SetActive(true);
                selectSprte2.SetActive(false);
                selectObj1.enabled = true;
                selectObj2.enabled = false;
                selectObj2.transform.localScale = Vector3.one;
                obj.transform.localScale = new Vector3(1.2f, 1.2f, 1.2f);
                obj.GetComponent<UISprite>().alpha = 0.2f;
            }
            else if (gameObj.name == "SelectBox2")
            {
                selectSprte2.SetActive(true);
                selectSprte1.SetActive(false);
                selectObj1.enabled = false;
                selectObj2.enabled = true;
                selectObj1.transform.localScale = Vector3.one;
                obj.transform.localScale = new Vector3(1.2f, 1.2f, 1.2f);
                obj.GetComponent<UISprite>().alpha = 0.2f;
            }
            else
            {
                selectSprte1.SetActive(false);
                selectSprte2.SetActive(false);
                selectObj1.enabled = false;
                selectObj2.enabled = false;
                selectObj1.transform.localScale = Vector3.one;
                selectObj2.transform.localScale = Vector3.one;
                obj.transform.localScale = Vector3.one;
                obj.GetComponent<UISprite>().alpha = 1f;
            }
        }
        else
        {
            selectSprte1.SetActive(false);
            selectSprte2.SetActive(false);
            selectObj1.enabled = false;
            selectObj2.enabled = false;
            selectObj1.transform.localScale = Vector3.one;
            selectObj2.transform.localScale = Vector3.one;
            obj.transform.localScale = Vector3.one;
            obj.GetComponent<UISprite>().alpha = 1f;
        }
        //摇杆随鼠标移动
        mousePositionX = Input.mousePosition.x - (float)Screen.width / 2;
        mousePositionY = Input.mousePosition.y - (float)Screen.height / 2;
        this.transform.localPosition = new Vector3(mousePositionX, mousePositionY, 0);
        //获得单签摇杆圆心离初始圆心的距离
        currentDistance = Mathf.Sqrt(getAbs(this.transform.localPosition.x, joyInitX) * getAbs(this.transform.localPosition.x, joyInitX)
                                                                 + getAbs(this.transform.localPosition.y, joyInitY) * getAbs(this.transform.localPosition.y, joyInitY));
        //判断摇杆移动距离是否超过最大距离,超过则设为最边沿的点
        if (currentDistance < joyControlDistance)
        {
            //isTankMove = false;
        }
        else if (currentDistance > joyMoveDistance)
        {
            SetJoyMoveMaxPosition();
            //isTankMove = true;
        }
        else
        {
            //isTankMove = true;
        }

    }

    protected override void OnDragDropRelease(GameObject surface)
    {
        base.OnDragDropRelease(surface);
        if (selectSprte1.activeSelf)
        {
            if (callback != null)
            {
                callback(DMGame.ESelectBtn.Left_Select);
            }
        }

        if (selectSprte2.activeSelf)
        {
            if (callback != null)
            {
                callback(DMGame.ESelectBtn.Right_Select);
            }
        }

        LeanTween.delayedCall(0.1f, delegate
        {
            //结束后回到初始点
            LeanTween.moveLocal(this.gameObject, objVec, 0.1f);
        });
    }

    /// <summary>
    /// 计算两个值的绝对值之差的绝对值
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    private float getAbs(float a, float b)
    {
        return Mathf.Abs(Mathf.Abs(a) - Mathf.Abs(b));
    }
    /// <summary>
    /// 摇杆可移动最大边界点的坐标
    /// </summary>
    private void SetJoyMoveMaxPosition()
    {
        /*
         *  移动鼠标控制摇杆超过规定距离,则摇杆保持以摇杆为圆心的当前两点的原斜率,长度为最大长度 
         *  其中x,y为(joyInitX, joyInitY),而(x1,y1)为当前摇杆坐标,R为和joyMoveDistance 
         *  (x2, y2)为最后要求的结果坐标,并且赋给当前的摇杆 
         *  算法: 
         *  由直线公式:y = kx + b; 推出k 和 b 
         *  k = (y1 - y) / (x1 - x);   b = y - k * x; 
         *  再由园的公式(x2 - x)^2 + (y2 - y)^2 = R^2; 
         *  进行带入运算得出关于x2的一元二次方程: (x2 - x)^2 + (k * x2 + b - y)^2 = R^2; 
         *  整理后得出:(1 + k^2) * x2^2 + 2 * (k*b - k*y - x)x2 + x^2 + b^2 + y^2 - 2*b*y - R^2 = 0; 
         *  再根据求根公式:x=[-b±√(b^2-4ac)]/2a 和 当前摇杆坐标X与初始坐标X的比较可得出x2的值,继而得出相应的y2 
         */
        try 
        {
            float k, b;                                // 直线的参数 
            float a1, b1, c1;                // 一元二次方程的参数 
            float tempX1, tempX2;        // 最后得出的两个X坐标 

            k = (this.transform.localPosition.y - joyInitY) / (this.transform.localPosition.x - joyInitX);
            b = joyInitY - k * joyInitX;
            a1 = 1 + k * k;
            b1 = 2 * (k * b - k * joyInitY - joyInitX);
            c1 = joyInitX * joyInitX + b * b + joyInitY * joyInitY - 2 * b * joyInitY - joyMoveDistance * joyMoveDistance;
            tempX1 = (-b1 + Mathf.Sqrt(b1 * b1 - 4 * a1 * c1)) / (2 * a1);
            tempX2 = (-b1 - Mathf.Sqrt(b1 * b1 - 4 * a1 * c1)) / (2 * a1);
            if (this.transform.localPosition.x > joyInitX)
            {
                if (tempX1 > joyInitX)
                {
                    this.transform.localPosition = new Vector3(tempX1, k * tempX1 + b, 0);
                }
                else
                {
                    this.transform.localPosition = new Vector3(tempX2, k * tempX2 + b, 0);
                }
            }
            else
            {
                if (tempX1 < joyInitX)
                {
                    this.transform.localPosition = new Vector3(tempX1, k * tempX1 + b, 0);
                }
                else
                {
                    this.transform.localPosition = new Vector3(tempX2, k * tempX2 + b, 0);
                }
            }
        }catch(System.Exception e)
        {
            Debug.Log(e.ToString());
        }
        
    }
}

标签: Unity3D C#

发表评论:

雨辰 joyimp|@2011-2018 京ICP备16030765号