예제 #1
0
 public float Distance(Vector2 p)
 {
     return(GeometryHelper.GetLineToPointDistance(StartPos, EndPos, p));
 }
예제 #2
0
 public GeometryHelper.LineIntersectionStates Intersects(LineSegment l2)
 {
     return(GeometryHelper.LinesIntersect(this, l2, true, true));
 }
예제 #3
0
 public bool Contains(Vector2 p)
 {
     return(GeometryHelper.IsPointOnLine(this, p) == GeometryHelper.PointOnLineStates.PointIsOnTheSegment);
 }
예제 #4
0
 public Vector2 GetIntersectionPoint(LineSegment l2)
 {
     return(GeometryHelper.GetIntersectionPoint(this, l2));
 }
예제 #5
0
        void UpdateBody(int i)
        {
            if (MaxUpdatePerBody < ++bodyUpdateCount[i])
            {
                return;
            }

            Vector2 a, v, p, r;
            var     body = Bodies[i];

            //if (body.IsStatic) return;

            a = body.Force * body.InverseMass -
                (body.AttachToGravity ?
                 new Vector2(Gravity.X * body.GravityNormal.X, Gravity.Y * body.GravityNormal.Y) :
                 Vector2.Zero) + body.Acceleration;
            v = a * Speed + body.Velocity;
            Vector2 position, size;

            body.Mesh.GetPositionAndSize(out position, out size);

            v.X = MathHelper.Clamp(v.X, -body.MaxSpeed.X, body.MaxSpeed.X);
            v.Y = MathHelper.Clamp(v.Y, -body.MaxSpeed.Y, body.MaxSpeed.Y);

            r = v * Speed;
            p = r + position;

            body.Mesh.AutoTriangulate = true;
            if (!body.Convex && body.Mesh.Triangles == null)
            {
                body.Mesh.Triangulate();
            }

            body.Mesh.Offset(r);

            if (body.IsStatic)
            {
                return;
            }

            List <KeyValuePair <Polygon, Polygon> > polys = new List <KeyValuePair <Polygon, Polygon> >();

            if (!body.IsFree && !body.IsStatic)
            {
                for (int j = 0; j < Bodies.Count; j++)
                {
                    var item = Bodies[j];
                    if (i == j)
                    {
                        continue;
                    }
                    if (item.NotCollideWith.Contains(body) ||
                        body.NotCollideWith.Contains(item))
                    {
                        continue;
                    }

                    var push = Vector2.Zero;

                    polys.Clear();

                    if (item.Convex && body.Convex)
                    {
                        if (Polygon.Collide(body.Mesh, item.Mesh, out push))
                        {
                            polys.Add(new KeyValuePair <Polygon, Polygon>(body.Mesh, item.Mesh));
                        }
                    }
                    else
                    {
                        #region SAT With Triangles
                        if (body.Convex)
                        {
                            if (item.Mesh.Triangles == null)
                            {
                                item.Mesh.Triangulate();
                            }
                            foreach (var pTri in item.Mesh.Triangles)
                            {
                                var temppush = Vector2.Zero;
                                if (Polygon.Collide(body.Mesh, pTri, out temppush))
                                {
                                    if (polys.Count == 0)
                                    {
                                        push = temppush;
                                    }
                                    polys.Add(new KeyValuePair <Polygon, Polygon>(body.Mesh, pTri));
                                }
                            }
                        }
                        else if (item.Convex)
                        {
                            foreach (var pTri in body.Mesh.Triangles)
                            {
                                var temppush = Vector2.Zero;
                                if (Polygon.Collide(pTri, item.Mesh, out temppush))
                                {
                                    if (polys.Count == 0)
                                    {
                                        push = temppush;
                                    }
                                    polys.Add(new KeyValuePair <Polygon, Polygon>(pTri, item.Mesh));
                                }
                            }
                        }
                        else
                        {
                            foreach (var p1 in body.Mesh.Triangles)
                            {
                                if (item.Mesh.Triangles == null)
                                {
                                    item.Mesh.Triangulate();
                                }
                                foreach (var p2 in item.Mesh.Triangles)
                                {
                                    var temppush = Vector2.Zero;

                                    if (Polygon.Collide(p1, p2, out temppush))
                                    {
                                        if (polys.Count == 0)
                                        {
                                            push = temppush;
                                        }
                                        polys.Add(new KeyValuePair <Polygon, Polygon>(p1, p2));
                                    }
                                }
                            }
                        }
                        #endregion
                    }

                    for (int pi = 0; pi < polys.Count; pi++)
                    {
                        if (pi == 0 || Polygon.Collide(polys[pi].Key, polys[pi].Value, out push))
                        {
                            Vector2 pd = push;
                            pd.Normalize();
                            pd = push - AllowedPenetrationDepth * pd;
                            if (body.PreventSlippingOnSlopes)
                            {
                                if (Math.Abs(pd.X) < StickCoef)
                                {
                                    pd.X = 0;
                                }
                            }
                            if (GeometryHelper.IsNaN(pd))
                            {
                                pd = Vector2.Zero;
                            }

                            /*
                             * EXPERIMENT:
                             * Move both bodies based on their weight
                             */
                            else if (item.IsStatic)
                            {
                                if (!item.IsFree)
                                {
                                    body.Mesh.Offset(pd);
                                }
                                if (body.Collide != null)
                                {
                                    body.Collide(item.Entity, pd);
                                }
                            }
                            else
                            {
                                //Lerp between masses
                                var massSum = body.InverseMass + item.InverseMass;
                                var bodyW   = body.InverseMass / massSum;
                                var itemW   = bodyW - 1.0f;
                                var bodyPV  = pd * bodyW;
                                var itemPV  = pd * itemW;

                                if (!item.IsFree)
                                {
                                    UpdateBody(j);
                                    body.Mesh.Offset(bodyPV);
                                }
                                if (body.Collide != null)
                                {
                                    body.Collide(item.Entity, bodyPV);
                                }
                                if (item.Collide != null)
                                {
                                    item.Collide(body.Entity, itemPV);
                                }
                            }
                        }
                    }
                }
            }

            var newP          = body.Mesh.GetPosition();
            var movedDistance = newP - p;
            if (movedDistance.Length() > _bigNumber) //We don't want no weird teleports, do we?
            {
                body.Mesh.Offset(-movedDistance);    //rollback
            }
            else
            {
                v += movedDistance / Speed;
            }
            body.Velocity     = v * DampingCoef;
            body.Acceleration = a;

            /////////////////////
            // Check for NaNs generated by bugs
            /////////////////////
            if (GeometryHelper.IsNaN(body.Velocity))
            {
                body.Velocity = Vector2.Zero;
            }
            if (GeometryHelper.IsNaN(body.Acceleration))
            {
                body.Acceleration = Vector2.Zero;
            }

            if (body.MaxSpeed.X >= 0 && Math.Abs(body.Velocity.X) > body.MaxSpeed.X)
            {
                body.Velocity.X = body.MaxSpeed.X * Math.Sign(body.Velocity.X);
            }
            if (body.MaxSpeed.Y >= 0 && Math.Abs(body.Velocity.Y) > body.MaxSpeed.Y)
            {
                body.Velocity.Y = body.MaxSpeed.Y * Math.Sign(body.Velocity.Y);
            }

            if (body.MaxAcceleration.X >= 0 && Math.Abs(body.Acceleration.X) > body.MaxAcceleration.X)
            {
                body.Acceleration.X = body.MaxAcceleration.X * Math.Sign(body.Acceleration.X);
            }
            if (body.MaxAcceleration.Y >= 0 && Math.Abs(body.Velocity.Y) > body.MaxAcceleration.Y)
            {
                body.Acceleration.Y = body.MaxAcceleration.Y * Math.Sign(body.Acceleration.Y);
            }

            body.Force        = Vector2.Zero;
            body.Acceleration = Vector2.Zero;
        }
예제 #6
0
파일: Body.cs 프로젝트: ARLM-Attic/neat
 void bd_impact(IList <string> args)
 {
     ApplyImpact(GeometryHelper.String2Vector(args[1]));
 }