两种屏幕HUD区域限制的做法(矩形,弧形)

HUD区域限制算是比较常用到的功能,方形的HUD区域限制多见于小地图,弧形或者椭圆多见于屏幕范围约束。

 

 

 

 

我没有研究倒角矩形做法,而是将椭圆和矩形进行插值得到一个弧度比较高的形状:

 

当插值为0时限制范围是椭圆,插值为1限制范围是矩形

矩形的判断使用了线段相交函数,函数来自网络收集

线段相交: http://www.cnblogs.com/hont/p/6106043.html

 

代码如下

using UnityEngine;
using System;
using System.Collections;

public class HUDTest2 : MonoBehaviour
{
    [Serializable]
    public class EllipseSetting
    {
        public float radius = 2f;
        public Vector2 scale = new Vector2(1, 1);
    }

    public Transform[] hudObjectArray;
    public EllipseSetting ellipseSetting = new EllipseSetting();
    [Range(0, 1)]
    public float lerp;


    void OnGUI()
    {
        for (int i = 0; i < hudObjectArray.Length; i++)
        {
            var item = hudObjectArray[i];

            var screenPosition = Camera.main.WorldToScreenPoint(item.transform.position);
            screenPosition.z = 0;
            screenPosition.y = Screen.height - screenPosition.y;
            screenPosition = HUDFix(screenPosition);

            GUI.Box(new Rect(screenPosition, Vector3.one * 15), "");
        }
    }

    Vector3 HUDFix(Vector3 position)
    {
        var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f;

        var ellipsePoint = GetEllipsePoint(position);
        var quadPoint = GetRectPoint(position);

        var finalPoint = Vector3.Lerp(ellipsePoint, quadPoint, lerp);

        if (Vector3.Distance(center, finalPoint) >= Vector3.Distance(center, position))
            return position;
        else
            return finalPoint;
    }

    Vector3 GetEllipsePoint(Vector3 currentPoint)
    {
        var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f;
        var current = center + (currentPoint - center).normalized * ellipseSetting.radius;

        current.x *= ellipseSetting.scale.x;
        current.y *= ellipseSetting.scale.y;

        return current;
    }

    Vector3 GetRectPoint(Vector3 currentPoint)
    {
        var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f;

        const float INNER = 25;
        const float RAY = 10000 * 10;
        var p0 = new Vector3(INNER, INNER, 0);
        var p1 = new Vector3(Screen.width - INNER, INNER, 0);
        var p2 = new Vector3(INNER, Screen.height - INNER, 0);
        var p3 = new Vector3(Screen.width - INNER, Screen.height - INNER, 0);

        var dir = (currentPoint - center).normalized * RAY;

        var contractPoint = default(Vector3);
        var r = GetIntersection(p0, p1, center, center + dir, out contractPoint);
        if (r == 1)
            return contractPoint;

        r = GetIntersection(p1, p3, center, center + dir, out contractPoint);
        if (r == 1)
            return contractPoint;

        r = GetIntersection(p0, p2, center, center + dir, out contractPoint);
        if (r == 1)
            return contractPoint;

        GetIntersection(p2, p3, center, center + dir, out contractPoint);
        return contractPoint;
    }

    int GetIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 contractPoint)
    {
        contractPoint = new Vector3(0, 0);

        if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) + Mathf.Abs(d.y - c.y)
                + Mathf.Abs(d.x - c.x) == 0)
        {
            if ((c.x - a.x) + (c.y - a.y) == 0)
            {
                //Debug.Log("ABCD是同一个点!");
            }
            else
            {
                //Debug.Log("AB是一个点,CD是一个点,且AC不同!");
            }
            return 0;
        }

        if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) == 0)
        {
            if ((a.x - d.x) * (c.y - d.y) - (a.y - d.y) * (c.x - d.x) == 0)
            {
                //Debug.Log("A、B是一个点,且在CD线段上!");
            }
            else
            {
                //Debug.Log("A、B是一个点,且不在CD线段上!");
            }
            return 0;
        }
        if (Mathf.Abs(d.y - c.y) + Mathf.Abs(d.x - c.x) == 0)
        {
            if ((d.x - b.x) * (a.y - b.y) - (d.y - b.y) * (a.x - b.x) == 0)
            {
                //Debug.Log("C、D是一个点,且在AB线段上!");
            }
            else
            {
                //Debug.Log("C、D是一个点,且不在AB线段上!");
            }
            return 0;
        }

        if ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y) == 0)
        {
            //Debug.Log("线段平行,无交点!");
            return 0;
        }

        contractPoint.x = ((b.x - a.x) * (c.x - d.x) * (c.y - a.y) -
                c.x * (b.x - a.x) * (c.y - d.y) + a.x * (b.y - a.y) * (c.x - d.x)) /
                ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y));
        contractPoint.y = ((b.y - a.y) * (c.y - d.y) * (c.x - a.x) - c.y
                * (b.y - a.y) * (c.x - d.x) + a.y * (b.x - a.x) * (c.y - d.y))
                / ((b.x - a.x) * (c.y - d.y) - (b.y - a.y) * (c.x - d.x));

        if ((contractPoint.x - a.x) * (contractPoint.x - b.x) <= 0
                && (contractPoint.x - c.x) * (contractPoint.x - d.x) <= 0
                && (contractPoint.y - a.y) * (contractPoint.y - b.y) <= 0
                && (contractPoint.y - c.y) * (contractPoint.y - d.y) <= 0)
        {

            //Debug.Log("线段相交于点(" + contractPoint.x + "," + contractPoint.z + ")!");
            return 1; // '相交  
        }
        else
        {
            //Debug.Log("线段相交于虚交点(" + contractPoint.x + "," + contractPoint.z + ")!");
            return -1; // '相交但不在线段上  
        }
    }
}

 

posted @ 2017-05-16 00:35  HONT  阅读(689)  评论(0编辑  收藏  举报