2D物理算法分享

分享两个简单的2D碰撞算法,线段和线段,圆和线段, 代码库 https://gitee.com/huqiang0204/HGUI

        /// <summary>

        ///

        /// </summary>

        /// <param name="a">线段1起点</param>

        /// <param name="b">线段1终点</param>

        /// <param name="c">线段2起点</param>

        /// <param name="d">线段2终点</param>

        /// <param name="p0">线段的交点</param>

        /// <returns></returns>

        public static bool LineToLine(ref Vector3 a, ref Vector3 b, ref Vector3 c, ref Vector3 d, ref Vector3 p0)//相交线相交点

        {

            float ax = b.x - a.x;

            float ay = b.y - a.y;

            float cx = d.x - c.x;

            float cy = d.y - c.y;

            float y = ay * cx - ax * cy;

            if (y == 0)

                return false;

            float x = (c.y - a.y) * cx + (a.x - c.x) * cy;

            float r = x / y;

            if (r >= 0 & r <= 1)

            {

                if (cx == 0)

                {

                    y = (a.y - c.y + r * ay) / cy;

                }

                else

                {

                    y = (a.x - c.x + r * ax) / cx;

                }

                if (y >= 0 & y <= 1)

                {

                    p0.x = a.x + r * ax;

                    p0.y = a.y + r * ay;

                    return true;

                }

            }

            return false;

        }

        /// <summary>

        /// 圆与线相交

        /// </summary>

        /// <param name="C">圆心位置</param>

        /// <param name="r">半径</param>

        /// <param name="A">线段起点</param>

        /// <param name="B">线段终点</param>

        /// <param name="p0">切点</param>

        /// <param name="p1">相交点1,如果超出起点则为起点</param>

        /// <param name="p2">相交点2,如果超出终点则为终点</param>

        /// <returns></returns>

        public static bool CircleToLine(Vector2 C, float r, Vector2 A, Vector2 B, ref Vector2 p0, ref Vector2 p1, ref Vector2 p2)

        {

            float o = r * r;

            Vector2 v1 = A - C;

            float a = v1.x * v1.x + v1.y * v1.y;

            if (a <= o)

            {

                p1 = A;//A点在圆里面

            }

            Vector2 v2 = B - C;

            float b = v2.x * v2.x + v2.y * v2.y;

            if (b <= o)

            {

                p2 = B;//B点在圆里面

            }

            Vector2 v3 = C - A;

            Vector2 v4 = B - A;

            float sl = v4.x * v4.x + v4.y * v4.y;

            float l = Mathf.Sqrt(sl);

            Vector2 p = Vector3.Project(v3, v4);

            float pl = Mathf.Sqrt(p.x * p.x + p.y * p.y) / l;//百分比位置

            if (Vector2.Dot(v3, v4) < 0)//反方向

                pl = -pl;

            p.x += A.x;

            p.y += A.y;//实际投影位置

            v2.x = p.x - C.x;

            v2.y = p.y - C.y;

            float sp = v2.x * v2.x + v2.y * v2.y;//圆心投影的长度的平方

            if (sp < o)//如过小于半径的平方

            {

                float ol = o - sp;

                var v = v4.normalized;

                float sx = v.x * v.x + v.y * v.y;

                float os = Mathf.Sqrt(ol / sx);

                float pos = os / l;

                v *= os;

                p0 = p;

                if (pl - pos > 0 & pl - pos < 1)

                    p1 = p - v;

                if (pl + pos > 0 & pl + pos < 1)

                    p2 = p + v;

                return true;

            }

            return false;

        }

下面是具体的示例演示

using huqiang.Core.HGUI;

using huqiang.UIEvent;

using UnityEngine;

public class PhysicalTestPage:UIPage

{

    class View

    {

        public UserEvent circle;

        public HImage line;

        public Transform A;

        public Transform B;

        public Transform C;

        public Transform D;

        public UserEvent line2;

    }

    View view;

    public override void Initial(Transform parent, object dat = null)

    {

        base.Initial(parent, dat);

        view = LoadUI<View>("baseUI", "Test");//"baseUI"创建的bytes文件名,"page"为创建的页面名

        view.circle.Drag = Drag;

        view.line2.Drag = Drag;

    }

    void Drag(UserEvent user, UserAction action, Vector2 v)

    {

        var trans = user.Context.transform;

        var p = trans.localPosition;

        p.x += v.x;

        p.y += v.y;

        trans.localPosition = p;

    }

    void CheckCircle()

    {

        var con = view.circle.Context;

        var trans = con.transform;

        var p = trans.localPosition;

        trans.localPosition = p;

        var op = view.line.transform.localPosition;

        var q = view.line.transform.localRotation;

        float x = view.line.SizeDelta.x;

        float hx = x * 0.5f;

        var a = q * new Vector3(hx, 0, 0) + op;

        var b = q * new Vector3(-hx, 0, 0) + op;

        Vector2 o0 = new Vector3(0, 400, 0);

        Vector2 o1 = new Vector3(0, 400, 0);

        Vector2 o2 = new Vector3(0, 400, 0);

        huqiang.Physics2D.CircleToLine(p, con.SizeDelta.x * 0.5f, a, b, ref o0, ref o1, ref o2);

        view.A.transform.localPosition = o0;

        view.B.transform.localPosition = o1;

        view.C.transform.localPosition = o2;

    }

    void CheckLine()

    {

        var op = view.line.transform.localPosition;

        var q = view.line.transform.localRotation;

        float x = view.line.SizeDelta.x;

        float hx = x * 0.5f;

        var a = q * new Vector3(hx, 0, 0) + op;

        var b = q * new Vector3(-hx, 0, 0) + op;

        var con = view.line2.Context;

        var trans = con.transform;

        var p = trans.localPosition;

        var q2 = trans.localRotation;

        float x2 = con.SizeDelta.x;

        float hx2 = x2 * 0.5f;

        var c = q2 * new Vector3(hx2, 0, 0) + p;

        var d = q2 * new Vector3(-hx2, 0, 0) + p;

        Vector3 o = new Vector3(0,400,0);

        huqiang.Physics2D.LineToLine(ref a, ref b, ref c, ref d, ref o);

        view.D.transform.localPosition = o;

    }

    public override void Update(float time)

    {

        view.line.transform.rotation*=Quaternion.Euler(0,0,0.5f);

        CheckCircle();

        CheckLine();

    }

}

具体效果展示


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容