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();

    }

}

具体效果展示


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容