예제 #1
0
        public override float ComputeSweepRadius(Vec2 pivot)
        {
            float ds1 = Vec2.DistanceSquared(_v1, pivot);
            float ds2 = Vec2.DistanceSquared(_v2, pivot);

            return(Common.Math.Sqrt(Common.Math.Max(ds1, ds2)));
        }
예제 #2
0
 public void Update(double dt)
 {
     Time    += (float)dt;
     Position = StartingPosition + Velocity * Time;
     if (Vec2.DistanceSquared(Position, StartingPosition) > Range * Range)
     {
         Active = false;
     }
 }
예제 #3
0
            internal void Initialize(ContactConstraint cc)
            {
                Box2DXDebug.Assert(cc.PointCount > 0);

                switch (cc.Type)
                {
                case ManifoldType.Circles:
                {
                    Vec2 pointA = cc.BodyA.GetWorldPoint(cc.LocalPoint);
                    Vec2 pointB = cc.BodyB.GetWorldPoint(cc.Points[0].LocalPoint);
                    if (Vec2.DistanceSquared(pointA, pointB) > Settings.FLT_EPSILON_SQUARED)
                    {
                        Normal = pointB - pointA;
                        Normal.Normalize();
                    }
                    else
                    {
                        Normal.Set(1.0f, 0.0f);
                    }

                    Points[0]      = 0.5f * (pointA + pointB);
                    Separations[0] = Vec2.Dot(pointB - pointA, Normal) - cc.Radius;
                }
                break;

                case ManifoldType.FaceA:
                {
                    Normal = cc.BodyA.GetWorldVector(cc.LocalPlaneNormal);
                    Vec2 planePoint = cc.BodyA.GetWorldPoint(cc.LocalPoint);

                    for (int i = 0; i < cc.PointCount; ++i)
                    {
                        Vec2 clipPoint = cc.BodyB.GetWorldPoint(cc.Points[i].LocalPoint);
                        Separations[i] = Vec2.Dot(clipPoint - planePoint, Normal) - cc.Radius;
                        Points[i]      = clipPoint;
                    }
                }
                break;

                case ManifoldType.FaceB:
                {
                    Normal = cc.BodyB.GetWorldVector(cc.LocalPlaneNormal);
                    Vec2 planePoint = cc.BodyB.GetWorldPoint(cc.LocalPoint);

                    for (int i = 0; i < cc.PointCount; ++i)
                    {
                        Vec2 clipPoint = cc.BodyA.GetWorldPoint(cc.Points[i].LocalPoint);
                        Separations[i] = Vec2.Dot(clipPoint - planePoint, Normal) - cc.Radius;
                        Points[i]      = clipPoint;
                    }

                    // Ensure normal points from A to B
                    Normal = -Normal;
                }
                break;
                }
            }
예제 #4
0
        static Vec2 ValidateActionPosition(IEntity player, PlayerAction action)
        {
            Vec2 position = action.Position;

            // If the position provided by the client seems legit, we take it. Otherwise, we ignore it
            // and log it (might be a hacker).
            if (Vec2.DistanceSquared(player.Position, position) >= MAX_TOLERATED_OFF_DISTANCE * MAX_TOLERATED_OFF_DISTANCE)
            {
                position = player.Position;
            }

            return(position);
        }
예제 #5
0
        void SmoothTowardsInterpolatedPosition()
        {
            float distanceSq = Vec2.DistanceSquared(DrawnPosition, Position);

            if (distanceSq < POSITION_DISTANCE_TO_SNAP * POSITION_DISTANCE_TO_SNAP)
            {
                DrawnPosition = Vec2.Lerp(DrawnPosition, Position, SMOOTH_LERP_FACTOR);
            }
            else
            {
                ILogger.Log(String.Format("Snapping remote client position({0}) to simulated({1}). -> distance squared:{2}", DrawnPosition, Position, distanceSq), LogPriority.High);
                DrawnPosition = Position;
            }
        }
예제 #6
0
        /// <summary>
        /// Lerps the drawn position towards our simulated position.
        /// </summary>
        void LerpTowardsSimulatedPosition(double deltaSeconds)
        {
            float distanceSq = Vec2.DistanceSquared(Position, DrawnPosition);

            if (distanceSq >= POSITION_DISTANCE_TO_SNAP * POSITION_DISTANCE_TO_SNAP)               // if we must snap directly to the simulated position
            {
                ILogger.Log(String.Format("Snapping position({0}) to simulated({1}). -> distance squared:{2}", DrawnPosition, Position, distanceSq), LogPriority.High);
                DrawnPosition = Position;
            }
            else                 // If we must interpolate our position (we're not too far)
            {
                DrawnPosition = Vec2.Lerp(DrawnPosition, Position, SMOOTH_FACTOR);
            }
        }
예제 #7
0
        public override float ComputeSweepRadius(Vec2 pivot)
        {
            int vCount = _vertexCount;

            Box2DNetDebug.Assert(vCount > 0);
            float sr = Vec2.DistanceSquared(_vertices[0], pivot);

            for (int i = 1; i < vCount; ++i)
            {
                sr = Common.Math.Max(sr, Vec2.DistanceSquared(_vertices[i], pivot));
            }

            return(Common.Math.Sqrt(sr));
        }
예제 #8
0
        private void GetClosestPointTo(Vec2 point, out Vec2 closest, out int lineIndex)
        {
            closest   = Vec2.Invalid;
            lineIndex = -1;
            float num1 = float.MaxValue;

            for (int index = 0; index < this.LineCount; ++index)
            {
                Vec2  lineSegmentToPoint = MBMath.GetClosestPointInLineSegmentToPoint(point, this._navigationData.Points[index], this._navigationData.Points[index + 1]);
                float num2 = lineSegmentToPoint.DistanceSquared(point);
                if ((double)num2 < (double)num1)
                {
                    num1      = num2;
                    closest   = lineSegmentToPoint;
                    lineIndex = index;
                }
            }
        }
예제 #9
0
        protected override void CalculateCurrentOrder()
        {
            Vec2 vec2_1;

            if (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation != null && this._mainFormation != null)
            {
                Vec2 vec2_2 = (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized();
                Vec2 v      = (this._mainFormation.QuerySystem.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized();
                vec2_1 = (double)vec2_2.DotProduct(v) <= 0.5 ? vec2_2 : this._mainFormation.FacingOrder.GetDirection(this._mainFormation);
            }
            else
            {
                vec2_1 = this.formation.Direction;
            }
            WorldPosition medianPosition;

            if (this._mainFormation == null)
            {
                medianPosition = this.formation.QuerySystem.MedianPosition;
                medianPosition.SetVec2(this.formation.QuerySystem.AveragePosition);
            }
            else
            {
                medianPosition = this._mainFormation.QuerySystem.MedianPosition;
                medianPosition.SetVec2(medianPosition.AsVec2 - vec2_1 * (float)(((double)this._mainFormation.Depth + (double)this.formation.Depth) * 0.5));
            }
            WorldPosition worldPosition = this.CurrentOrder.GetPosition(this.formation);

            if (worldPosition.IsValid && this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.IsRangedCavalryFormation)
            {
                Vec2     averagePosition = this.formation.QuerySystem.AveragePosition;
                ref Vec2 local           = ref averagePosition;
                worldPosition = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition;
                Vec2 asVec2 = worldPosition.GetNavMeshVec3().AsVec2;
                if ((double)local.DistanceSquared(asVec2) < (double)this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MissileRange * (double)this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MissileRange)
                {
                    worldPosition = this.CurrentOrder.GetPosition(this.formation);
                    if ((double)worldPosition.GetNavMeshVec3().DistanceSquared(medianPosition.GetNavMeshVec3()) < (double)this.formation.Depth * (double)this.formation.Depth)
                    {
                        goto label_10;
                    }
                }
            }
예제 #10
0
 public override void Draw()
 {
     Canvas.Clear(Color.Black);
     foreach (var particle in Particles)
     {
         var  color = Color.Lerp(Color.Cyan, Color.DarkCyan, particle.Velocity.LengthSquared() / 1000);
         Vec2?closestGravityPoint = null;
         foreach (var gravityPoints in GravityPoints)
         {
             if (closestGravityPoint is null)
             {
                 closestGravityPoint = gravityPoints;
             }
             else if (closestGravityPoint?.DistanceSquared(particle.Position) > gravityPoints.DistanceSquared(particle.Position))
             {
                 closestGravityPoint = gravityPoints;
             }
         }
         color = Color.Lerp(Color.Red, color, Vec2.Distance(particle.Position, closestGravityPoint.Value) / 100);
         Canvas.DrawRectangle(particle.Position, new Vec2(5, 5), true, color);
     }
     Canvas.Present();
 }
예제 #11
0
        public static void CircleToPolygon(Manifold m, Body a, Body b)
        {
            Circle  shapeA = a.shape as Circle;
            Polygon shapeB = b.shape as Polygon;

            m.contactCount = 0;

            // Transform circle center to Polygon model space
            Vec2 center = a.position;

            center = shapeB.transform.WorldToLocalPosition(center);

            // Find edge with minimum penetration
            // Exact concept as using support points in Polygon vs Polygon
            float separation = float.MinValue;
            int   faceNormal = 0;

            for (int i = 0; i < shapeB.VertexCount; ++i)
            {
                float s = Vec2.Dot(shapeB.normals[i], center - shapeB.vertices[i]);

                if (s > shapeA.radius)
                {
                    return;
                }

                if (s > separation)
                {
                    separation = s;
                    faceNormal = i;
                }
            }

            // Grab face's vertices
            Vec2 v1 = shapeB.vertices[faceNormal];
            int  i2 = faceNormal + 1 < shapeB.VertexCount ? faceNormal + 1 : 0;
            Vec2 v2 = shapeB.vertices[i2];

            Contact c = new Contact(Vec2.Zero);

            // Check to see if center is within polygon
            if (separation < float.Epsilon)
            {
                m.normal      = -shapeB.transform.LocalToWorldDirection(shapeB.normals[faceNormal]);
                c.position    = m.normal * shapeA.radius + a.position;
                c.penetration = shapeA.radius;
                m.Update(1, c);
                return;
            }

            // Determine which voronoi region of the edge center of circle lies within
            float dot1 = Vec2.Dot(center - v1, v2 - v1);
            float dot2 = Vec2.Dot(center - v2, v1 - v2);

            c.penetration = shapeA.radius - separation;

            // Closest to v1
            if (dot1 <= 0.0f)
            {
                if (Vec2.DistanceSquared(center, v1) > shapeA.radius * shapeA.radius)
                {
                    return;
                }

                Vec2 n = v1 - center;
                n = shapeB.transform.LocalToWorldDirection(n);
                n.Normalize();
                m.normal = n;

                v1         = shapeB.transform.LocalToWorldPosition(v1);
                c.position = v1;
                m.Update(1, c);
            }

            // Closest to v2
            else if (dot2 <= 0.0f)
            {
                if (Vec2.DistanceSquared(center, v2) > shapeA.radius * shapeA.radius)
                {
                    return;
                }

                Vec2 n = v2 - center;
                v2         = shapeB.transform.LocalToWorldPosition(v2);
                c.position = v2;
                m.Update(1, c);

                n = shapeB.transform.LocalToWorldDirection(n);
                n.Normalize();
                m.normal = n;
            }

            // Closest to face
            else
            {
                Vec2 n = shapeB.normals[faceNormal];
                if (Vec2.Dot(center - v1, n) > shapeA.radius)
                {
                    return;
                }

                n          = shapeB.transform.LocalToWorldDirection(n);
                m.normal   = -n;
                c.position = m.normal * shapeA.radius + a.position;
                m.Update(1, c);
            }
        }
예제 #12
0
        /// Evaluate the manifold with supplied transforms. This assumes
        /// modest motion from the original state. This does not change the
        /// point count, impulses, etc. The radii must come from the shapes
        /// that generated the manifold.
        public void Initialize(Manifold manifold, XForm xfA, float radiusA, XForm xfB, float radiusB)
        {
            if (manifold.PointCount == 0)
            {
                return;
            }

            switch (manifold.Type)
            {
            case ManifoldType.Circles:
            {
                Vec2 pointA = Math.Mul(xfA, manifold.LocalPoint);
                Vec2 pointB = Math.Mul(xfB, manifold.Points[0].LocalPoint);
                Vec2 normal = new Vec2(1.0f, 0.0f);
                if (Vec2.DistanceSquared(pointA, pointB) > Settings.FltEpsilonSquared)
                {
                    normal = pointB - pointA;
                    normal.Normalize();
                }

                Normal = normal;

                Vec2 cA = pointA + radiusA * normal;
                Vec2 cB = pointB - radiusB * normal;
                Points[0] = 0.5f * (cA + cB);
            }
            break;

            case ManifoldType.FaceA:
            {
                Vec2 normal     = Math.Mul(xfA.R, manifold.LocalPlaneNormal);
                Vec2 planePoint = Math.Mul(xfA, manifold.LocalPoint);

                // Ensure normal points from A to B.
                Normal = normal;

                for (int i = 0; i < manifold.PointCount; ++i)
                {
                    Vec2 clipPoint = Math.Mul(xfB, manifold.Points[i].LocalPoint);
                    Vec2 cA        = clipPoint + (radiusA - Vec2.Dot(clipPoint - planePoint, normal)) * normal;
                    Vec2 cB        = clipPoint - radiusB * normal;
                    Points[i] = 0.5f * (cA + cB);
                }
            }
            break;

            case ManifoldType.FaceB:
            {
                Vec2 normal     = Math.Mul(xfB.R, manifold.LocalPlaneNormal);
                Vec2 planePoint = Math.Mul(xfB, manifold.LocalPoint);

                // Ensure normal points from A to B.
                Normal = -normal;

                for (int i = 0; i < manifold.PointCount; ++i)
                {
                    Vec2 clipPoint = Math.Mul(xfA, manifold.Points[i].LocalPoint);
                    Vec2 cA        = clipPoint - radiusA * normal;
                    Vec2 cB        = clipPoint + (radiusB - Vec2.Dot(clipPoint - planePoint, normal)) * normal;
                    Points[i] = 0.5f * (cA + cB);
                }
            }
            break;
            }
        }
예제 #13
0
        // This implements 2-sided edge vs circle collision.
        public static void CollideEdgeAndCircle(ref Manifold manifold, EdgeShape edge, XForm transformA, CircleShape circle, XForm transformB)
        {
            manifold.PointCount = 0;
            Vec2  cLocal = Common.Math.MulT(transformA, Common.Math.Mul(transformB, circle._position));
            Vec2  normal = edge._normal;
            Vec2  v1     = edge._v1;
            Vec2  v2     = edge._v2;
            float radius = edge._radius + circle._radius;

            // Barycentric coordinates
            float u1 = Vec2.Dot(cLocal - v1, v2 - v1);
            float u2 = Vec2.Dot(cLocal - v2, v1 - v2);

            if (u1 <= 0.0f)
            {
                // Behind v1
                if (Vec2.DistanceSquared(cLocal, v1) > radius * radius)
                {
                    return;
                }

                manifold.PointCount       = 1;
                manifold.Type             = ManifoldType.FaceA;
                manifold.LocalPlaneNormal = cLocal - v1;
                manifold.LocalPlaneNormal.Normalize();
                manifold.LocalPoint           = v1;
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
            else if (u2 <= 0.0f)
            {
                // Ahead of v2
                if (Vec2.DistanceSquared(cLocal, v2) > radius * radius)
                {
                    return;
                }

                manifold.PointCount       = 1;
                manifold.Type             = ManifoldType.FaceA;
                manifold.LocalPlaneNormal = cLocal - v2;
                manifold.LocalPlaneNormal.Normalize();
                manifold.LocalPoint           = v2;
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
            else
            {
                float separation = Vec2.Dot(cLocal - v1, normal);
                if (separation < -radius || radius < separation)
                {
                    return;
                }

                manifold.PointCount           = 1;
                manifold.Type                 = ManifoldType.FaceA;
                manifold.LocalPlaneNormal     = separation < 0.0f ? -normal : normal;
                manifold.LocalPoint           = 0.5f * (v1 + v2);
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
        }
예제 #14
0
 public void TestDistance(Vec2 a, Vec2 b, float dist, string msg, float eps = float.Epsilon)
 {
     Assert.AreEqual(dist, Vec2.Distance(a, b), eps, msg);
     Assert.AreEqual(dist * dist, Vec2.DistanceSquared(a, b), eps, msg + " squared");
 }
        protected override void CalculateCurrentOrder()
        {
            Vec2 averagePosition = this.formation.QuerySystem.AveragePosition;

            if (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation == null)
            {
                WorldPosition medianPosition = this.formation.QuerySystem.MedianPosition;
                medianPosition.SetVec2(averagePosition);
                this.CurrentOrder = MovementOrder.MovementOrderMove(medianPosition);
            }
            else
            {
                WorldPosition           medianPosition = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition;
                IEnumerable <Formation> source         = this.formation.Team.FormationsIncludingSpecial.Where <Formation>((Func <Formation, bool>)(f => f != this.formation));
                Vec2          vec2_1            = source.Any <Formation>() ? new Vec2(source.Average <Formation>((Func <Formation, float>)(oa => oa.QuerySystem.MedianPosition.AsVec2.x)), source.Average <Formation>((Func <Formation, float>)(oa => oa.QuerySystem.MedianPosition.AsVec2.y))) : averagePosition;
                WorldPosition formationPosition = this.formation.QuerySystem.Team.MedianTargetFormationPosition;
                Vec2          vec2_2            = (formationPosition.AsVec2 - vec2_1).Normalized();
                float         missileRange      = this.formation.QuerySystem.MissileRange;
                WorldPosition position;
                if (this._rushMode)
                {
                    float num = averagePosition.DistanceSquared(medianPosition.AsVec2);
                    if ((double)num > (double)this.formation.QuerySystem.MissileRange * (double)this.formation.QuerySystem.MissileRange)
                    {
                        position = formationPosition;
                        position.SetVec2(position.AsVec2 - vec2_2 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5)));
                    }
                    else if (this.formation.QuerySystem.ClosestEnemyFormation.IsCavalryFormation || (double)num <= 400.0 || (double)this.formation.QuerySystem.UnderRangedAttackRatio >= 0.400000005960464)
                    {
                        position = this.formation.QuerySystem.Team.MedianPosition;
                        position.SetVec2(vec2_1 - ((source.Any <Formation>() ? 30f : 80f) + this.formation.Depth) * vec2_2);
                        this._rushMode = false;
                    }
                    else
                    {
                        position = this.formation.QuerySystem.Team.MedianPosition;
                        Vec2 vec2_3 = (medianPosition.AsVec2 - averagePosition).Normalized();
                        position.SetVec2(medianPosition.AsVec2 - vec2_3 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5)));
                    }
                }
                else
                {
                    if (source.Any <Formation>())
                    {
                        position = this.formation.QuerySystem.Team.MedianPosition;
                        position.SetVec2(vec2_1 - (30f + this.formation.Depth) * vec2_2);
                    }
                    else
                    {
                        position = this.formation.QuerySystem.ClosestEnemyFormation.MedianPosition;
                        position.SetVec2(position.AsVec2 - 80f * vec2_2);
                    }
                    if ((double)position.AsVec2.DistanceSquared(averagePosition) <= 400.0)
                    {
                        position = formationPosition;
                        position.SetVec2(position.AsVec2 - vec2_2 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5)));
                        this._rushMode = true;
                    }
                }
                this.CurrentOrder = MovementOrder.MovementOrderMove(position);
            }
        }
예제 #16
0
        public static void CollidePolygonAndCircle(ref Manifold manifold,
                                                   PolygonShape polygon, XForm xf1, CircleShape circle, XForm xf2)
        {
            manifold.PointCount = 0;

            // Compute circle position in the frame of the polygon.
            Vec2 c      = Common.Math.Mul(xf2, circle._position);
            Vec2 cLocal = Common.Math.MulT(xf1, c);

            // Find the min separating edge.
            int   normalIndex = 0;
            float separation  = -Settings.FLT_MAX;
            float radius      = polygon._radius + circle._radius;
            int   vertexCount = polygon._vertexCount;

            Vec2[] vertices = polygon._vertices;
            Vec2[] normals  = polygon._normals;

            for (int i = 0; i < vertexCount; ++i)
            {
                float s = Vec2.Dot(normals[i], cLocal - vertices[i]);
                if (s > radius)
                {
                    // Early out.
                    return;
                }

                if (s > separation)
                {
                    separation  = s;
                    normalIndex = i;
                }
            }

            // Vertices that subtend the incident face.
            int  vertIndex1 = normalIndex;
            int  vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
            Vec2 v1         = vertices[vertIndex1];
            Vec2 v2         = vertices[vertIndex2];

            // If the center is inside the polygon ...
            if (separation < Common.Settings.FLT_EPSILON)
            {
                manifold.PointCount           = 1;
                manifold.Type                 = ManifoldType.FaceA;
                manifold.LocalPlaneNormal     = normals[normalIndex];
                manifold.LocalPoint           = 0.5f * (v1 + v2);
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
                return;
            }

            // Compute barycentric coordinates
            float u1 = Vec2.Dot(cLocal - v1, v2 - v1);
            float u2 = Vec2.Dot(cLocal - v2, v1 - v2);

            if (u1 <= 0.0f)
            {
                if (Vec2.DistanceSquared(cLocal, v1) > radius * radius)
                {
                    return;
                }

                manifold.PointCount       = 1;
                manifold.Type             = ManifoldType.FaceA;
                manifold.LocalPlaneNormal = cLocal - v1;
                manifold.LocalPlaneNormal.Normalize();
                manifold.LocalPoint           = v1;
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
            else if (u2 <= 0.0f)
            {
                if (Vec2.DistanceSquared(cLocal, v2) > radius * radius)
                {
                    return;
                }

                manifold.PointCount       = 1;
                manifold.Type             = ManifoldType.FaceA;
                manifold.LocalPlaneNormal = cLocal - v2;
                manifold.LocalPlaneNormal.Normalize();
                manifold.LocalPoint           = v2;
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
            else
            {
                Vec2  faceCenter  = 0.5f * (v1 + v2);
                float separation_ = Vec2.Dot(cLocal - faceCenter, normals[vertIndex1]);
                if (separation_ > radius)
                {
                    return;
                }

                manifold.PointCount           = 1;
                manifold.Type                 = ManifoldType.FaceA;
                manifold.LocalPlaneNormal     = normals[vertIndex1];
                manifold.LocalPoint           = faceCenter;
                manifold.Points[0].LocalPoint = circle._position;
                manifold.Points[0].ID.Key     = 0;
            }
        }
예제 #17
0
 public bool ReachedMaxRange()
 {
     return(Vec2.DistanceSquared(Position, StartPosition) >= Info.Range * Info.Range);
 }