zoukankan      html  css  js  c++  java
  • 两种屏幕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; // '相交但不在线段上  
            }
        }
    }
  • 相关阅读:
    COCO2018 目标检测
    最小生成树[摘录自严长生老师的网站]
    PANet训练自己的数据(VIA标注)
    图的遍历[摘录自严长生老师的网站]
    图的链式存储(邻接表)【摘录自严长生老师的网站】
    Android写入到mysql里的中文总是乱码?
    Mac 当xampp里mysql无法启动的解决办法
    【代码段】Android Studio使用DatePicker选择日期
    Android jdbc连接mysql报错解决方案 (Communications link failure)
    绝命毒师口语精析(4)
  • 原文地址:https://www.cnblogs.com/hont/p/6859185.html
Copyright © 2011-2022 走看看