Example #1
0
        internal override void RecalculateBounds(Collider collider)
        {
            // if we dont have rotation or dont care about TRS we use localOffset as the center so we'll start with that
            center = collider.LocalOffset;

            if (collider.ShouldColliderScaleAndRotateWithTransform)
            {
                var      hasUnitScale = true;
                Matrix2D tempMat;
                var      combinedMatrix = Matrix2D.CreateTranslation(-_polygonCenter);

                if (collider.Entity.Transform.Scale != Vector2.One)
                {
                    Matrix2D.CreateScale(collider.Entity.Transform.Scale.X, collider.Entity.Transform.Scale.Y,
                                         out tempMat);
                    Matrix2D.Multiply(ref combinedMatrix, ref tempMat, out combinedMatrix);

                    hasUnitScale = false;

                    // scale our offset and set it as center. If we have rotation also it will be reset below
                    var scaledOffset = collider.LocalOffset * collider.Entity.Transform.Scale;
                    center = scaledOffset;
                }

                if (collider.Entity.Transform.Rotation != 0)
                {
                    Matrix2D.CreateRotation(collider.Entity.Transform.Rotation, out tempMat);
                    Matrix2D.Multiply(ref combinedMatrix, ref tempMat, out combinedMatrix);

                    // to deal with rotation with an offset origin we just move our center in a circle around 0,0 with our offset making the 0 angle
                    // we have to deal with scale here as well so we scale our offset to get the proper length first.
                    var offsetAngle  = Mathf.Atan2(collider.LocalOffset.Y, collider.LocalOffset.X) * Mathf.Rad2Deg;
                    var offsetLength = hasUnitScale
                                                ? collider._localOffsetLength
                                                : (collider.LocalOffset * collider.Entity.Transform.Scale).Length();
                    center = Mathf.PointOnCircle(Vector2.Zero, offsetLength,
                                                 collider.Entity.Transform.RotationDegrees + offsetAngle);
                }

                Matrix2D.CreateTranslation(ref _polygonCenter, out tempMat);                 // translate back center
                Matrix2D.Multiply(ref combinedMatrix, ref tempMat, out combinedMatrix);

                // finaly transform our original points
                Vector2Ext.Transform(_originalPoints, ref combinedMatrix, Points);

                IsUnrotated = collider.Entity.Transform.Rotation == 0;

                // we only need to rebuild our edge normals if we rotated
                if (collider._isRotationDirty)
                {
                    _areEdgeNormalsDirty = true;
                }
            }

            position         = collider.Entity.Transform.Position + center;
            bounds           = RectangleF.RectEncompassingPoints(Points);
            bounds.Location += position;
        }
Example #2
0
        /// <summary>
        /// gets the points for the rectangle with all transforms applied
        /// </summary>
        /// <returns>The transformed points.</returns>
        public Vector2[] GetTransformedPoints()
        {
            var pts = new Vector2[] { new Vector2(X, Y), new Vector2(X + Width, Y), new Vector2(X + Width, Y + Height), new Vector2(X, Y + Height) };
            var mat = GetCombinedMatrix();

            Vector2Ext.Transform(pts, ref mat, pts);

            return(pts);
        }
Example #3
0
        public Vector2[] getTransformedPoints()
        {
            var pts = new Vector2[] { start, end };
            var mat = getCombinedMatrix();

            Vector2Ext.transform(pts, ref mat, pts);

            return(pts);
        }
Example #4
0
        /// <summary>
        /// gets the points that make up the path with any transforms present applied. The points can be used to approximate the path by
        /// drawing lines between them.
        ///
        /// Important notes: ISvgPathBuilder is a faux interface that is required because PCLs cannot access System.Drawing which is used
        /// to get the drawing points. In order to use this method you need to put the SvgPathBuilder in your main project and then pass in
        /// an SvgPathBuilder object to this method.
        /// </summary>
        /// <returns>The transformed drawing points.</returns>
        /// <param name="pathBuilder">Path builder.</param>
        /// <param name="flatness">Flatness.</param>
        public Vector2[] getTransformedDrawingPoints(ISvgPathBuilder pathBuilder, float flatness = 3)
        {
            var pts = pathBuilder.getDrawingPoints(segments, flatness);
            var mat = getCombinedMatrix();

            Vector2Ext.transform(pts, ref mat, pts);

            return(pts);
        }
Example #5
0
        public void LengthBetweenTwoPoints()
        {
            Vector2 v0 = new Vector2(0.0f, 0.0f);
            Vector2 v1 = new Vector2(10.0f, 0.0f);

            var result = Vector2Ext.DistanceBetweenTwoPoints(v0, v1);

            Assert.Equal(10.0f, result);
        }
Example #6
0
        public Vector2[] getTransformedPoints()
        {
            var pts = new Vector2[points.Length];
            var mat = getCombinedMatrix();

            Vector2Ext.transform(points, ref mat, pts);

            return(pts);
        }
Example #7
0
        public Vector2[] GetTransformedPoints()
        {
            var pts = new Vector2[] { Start, End };
            var mat = GetCombinedMatrix();

            Vector2Ext.Transform(pts, ref mat, pts);

            return(pts);
        }
        /// <summary>
        /// gets the points for the rectangle with all transforms applied
        /// </summary>
        /// <returns>The transformed points.</returns>
        public Vector2[] getTransformedPoints()
        {
            var pts = new Vector2[] { new Vector2(x, y), new Vector2(x + width, y), new Vector2(x + width, y + height), new Vector2(x, y + height) };
            var mat = getCombinedMatrix();

            Vector2Ext.transform(pts, ref mat, pts);

            return(pts);
        }
Example #9
0
        private Point FindNearestPoint(List <Vector2> points, List <LineSegment> snap_lines, Vector2 p)
        {
            float min_distance = 1e9f;
            int   min_point    = -1;

            if (points.Count > 0)
            {
                min_point    = 0;
                min_distance = Vector2Ext.Distance(p, points[0]);

                for (int index = 1; index < points.Count; index++)
                {
                    float dist = Vector2Ext.Distance(p, points[index]);
                    if (dist < min_distance)
                    {
                        min_point    = index;
                        min_distance = dist;
                    }
                }
                //return points[min_point];
            }

            int min_line = -1;

            if (snap_lines.Count > 0)
            {
                for (int index = 0; index < snap_lines.Count; index++)
                {
                    float dist = snap_lines[index].Distance(p);
                    if (dist < min_distance)
                    {
                        min_line     = index;
                        min_distance = dist;
                        min_point    = -1;
                    }
                }
            }

            if (min_point == -1)
            {
                if (min_line == -1)
                {
                    return(p.ToPoint());
                }
                else
                {
                    Vector2 nearestPoint = GeometryHelper.GetNearestPointInSegmentToPoint(
                        snap_lines[min_line].StartPos, snap_lines[min_line].EndPos, p);
                    return(nearestPoint.ToPoint());
                }
            }
            else
            {
                return(points[min_point].ToPoint());
            }
        }
Example #10
0
        public void CreateUnitInDirectionTestEqual()
        {
            Vector2 v0 = new Vector2(10.0f, 10.0f);
            Vector2 v1 = new Vector2(10.0f, 10.0f);

            var result = Vector2Ext.UnitInDirection(v0, v1);

            Assert.Equal(0.0f, result.X);
            Assert.Equal(0.0f, result.Y);
        }
Example #11
0
        public override Vector2 getPosition()
        {
            // we need a position that's far enough away to be safe
            // calculate the vector from them to us, then make sure it's at least the approach distance
            // 1. get dir to me
            var dirToMe = Vector2Ext.Normalize(nt.Position - mind.state.me.body.pos);
            // 2. scale to minimum range, find resultant (away)
            var targetAway = approachRange * -dirToMe;

            return(targetAway);
        }
Example #12
0
        public void CreateUnitInDirectionTest()
        {
            Vector2 v0 = new Vector2(0.0f, 0.0f);
            Vector2 v1 = new Vector2(10.0f, -10.0f);

            var result = Vector2Ext.UnitInDirection(v0, v1);

            var expected = (float)Math.Sqrt(0.5f);

            Assert.Equal(expected, result.X, 5);
            Assert.Equal(-expected, result.Y, 5);
        }
Example #13
0
        public static void Spawn(string name, float a = 0f, float s = 0f)
        {
            var wingPly = new BirdPersonality {
                A = a, S = s
            };
            // wingPly.generateRandom();
            var spawnOffset = Vector2Ext.Rotate(new Vector2(0, -120f), Random.NextFloat() * Mathf.PI * 2f);
            var wing        = play.setup.createNpcWing(name,
                                                       play.state.player.Entity.Position + spawnOffset, wingPly);

            play.AddEntity(wing.Entity);
            debugLog($"spawned 1 entity named {wing.Entity.Name}");
        }
Example #14
0
        /// <summary>
        /// gets optimized drawing points with extra points in curves and less in straight lines with any transforms present applied
        /// </summary>
        /// <returns>The optimized drawing points.</returns>
        /// <param name="distanceTolerance">Distance tolerance.</param>
        public Vector2[] getOptimizedTransformedDrawingPoints(float distanceTolerance = 2f)
        {
            var pointList = getOptimizedDrawingPoints(distanceTolerance);
            var points    = pointList.ToArray();

            ListPool <Vector2> .free(pointList);

            var mat = getCombinedMatrix();

            Vector2Ext.transform(points, ref mat, points);

            return(points);
        }
Example #15
0
        static bool CollideEdgeAndCircle(EdgeShape edge, ref FSTransform edgeTransform, CircleShape circle,
                                         ref FSTransform circleTransform, out FSCollisionResult result)
        {
            result = new FSCollisionResult();
            Collision.CollideEdgeAndCircle(ref _manifold, edge, ref edgeTransform, circle, ref circleTransform);
            if (_manifold.PointCount > 0)
            {
                // code adapted from PositionSolverManifold.Initialize
                if (_manifold.Type == ManifoldType.Circles)
                {
                    // this is essentically directly from ContactSolver.WorldManifold.Initialize. To avoid doing the extra math twice we duplicate this code
                    // here because it doesnt return some values we need to calculate separation
                    var pointA = MathUtils.Mul(ref edgeTransform, _manifold.LocalPoint);
                    var pointB = MathUtils.Mul(ref circleTransform, _manifold.Points[0].LocalPoint);

                    result.Normal = pointA - pointB;
                    Vector2Ext.Normalize(ref result.Normal);

                    var cA = pointA - edge.Radius * result.Normal;
                    var cB = pointB + circle.Radius * result.Normal;
                    result.Point  = 0.5f * (cA + cB);
                    result.Point *= FSConvert.SimToDisplay;

                    var separation = Vector2.Dot(pointA - pointB, result.Normal) - edge.Radius - circle.Radius;

                    // Ensure normal points from A to B
                    Vector2.Negate(ref result.Normal, out result.Normal);
                    result.MinimumTranslationVector = result.Normal * Math.Abs(separation);
                }
                else                 // FaceA
                {
                    result.Normal = MathUtils.Mul(edgeTransform.Q, _manifold.LocalNormal);
                    var planePoint = MathUtils.Mul(ref edgeTransform, _manifold.LocalPoint);

                    var clipPoint  = MathUtils.Mul(ref circleTransform, _manifold.Points[0].LocalPoint);
                    var separation = Vector2.Dot(clipPoint - planePoint, result.Normal) - edge.Radius - circle.Radius;
                    result.Point = (clipPoint - result.Normal * circle.Radius) * FSConvert.SimToDisplay;

                    result.MinimumTranslationVector = result.Normal * -separation;
                }

#if DEBUG_FSCOLLISIONS
                Debug.drawPixel(result.point, 5, Color.Red, 0.2f);
                Debug.drawLine(result.point, result.point + result.normal * 20, Color.Yellow, 0.2f);
#endif

                return(true);
            }

            return(false);
        }
Example #16
0
        void preparePolygonForCollisionChecks()
        {
            // we need to setup a Polygon with one edge. It needs the center to be in the opposite direction of it's normal.
            // this is necessary so that SAT knows which way to calculate the MTV, which uses Shape positions.
            var perp = Vector2Ext.perpendicular(_particleTwo.position - _particleOne.position);

            perp.Normalize();

            // set our Polygon points
            var midPoint = Vector2.Lerp(_particleOne.position, _particleTwo.position, 0.5f);

            _polygon.position  = midPoint + perp * 50;
            _polygon.points[0] = _particleOne.position - _polygon.position;
            _polygon.points[1] = _particleTwo.position - _polygon.position;
            _polygon.recalculateCenterAndEdgeNormals();
        }
Example #17
0
        public Gas(float x, float y)
        {
            initialRadius = MoreRandom.Next(8, 17);
            initialColor  = colors[MoreRandom.Next(0, colors.Length)];

            Circle = new Circle(x, y, initialRadius)
            {
                Color = initialColor
            };
            Circle.ApplyChanges();

            velocity = Vector2Ext.Random() * MoreRandom.Next(25, 120);

            rateOfDecay = (float)MoreRandom.NextDouble(8, 40);
            Lingering   = true;
        }
Example #18
0
        public void Update()
        {
            if (CanAccelearte)
            {
                CurrentSpeed += Acceleration * Time.DeltaTime;

                if (CurrentSpeed > MaxSpeed)
                {
                    CurrentSpeed  = MaxSpeed;
                    CanAccelearte = false;
                }
            }

            var motion = Vector2Ext.Normalize(player.Position - Entity.Position) * CurrentSpeed * Time.DeltaTime;

            mover.ApplyMovement(motion);
        }
Example #19
0
        /// <summary>
        /// builds the Polygon edge normals. These are lazily created and updated only by the edgeNormals getter
        /// </summary>
        void buildEdgeNormals()
        {
            // special case for 2 points. we just have a single edge
            if (points.Length == 2)
            {
                if (_edgeNormals == null || _edgeNormals.Length != 1)
                {
                    _edgeNormals = new Vector2[1];
                }

                var perp = Vector2Ext.perpendicular(ref points[0], ref points[1]);
                Vector2Ext.normalize(ref perp);
                _edgeNormals[0] = perp;
                return;
            }

            // for boxes we only require 2 edges since the other 2 are parallel
            var totalEdges = isBox ? 2 : points.Length;

            if (_edgeNormals == null || _edgeNormals.Length != totalEdges)
            {
                _edgeNormals = new Vector2[totalEdges];
            }

            Vector2 p2;

            for (var i = 0; i < totalEdges; i++)
            {
                var p1 = points[i];
                if (i + 1 >= points.Length)
                {
                    p2 = points[0];
                }
                else
                {
                    p2 = points[i + 1];
                }

                var perp = Vector2Ext.perpendicular(ref p1, ref p2);
                Vector2Ext.normalize(ref perp);
                _edgeNormals[i] = perp;
            }

            return;
        }
Example #20
0
        public void update()
        {
            Position getMouseTile()
            {
                // calculate the selection tilepos
                var selectionPos =
                    Vector2Ext.transform(Input.mousePosition, entity.scene.camera.inverseTransformMatrix);
                var relativeSelectionPos = selectionPos - (entity.transform.position + localOffset);
                var mouseTilePos         = new Position((int)relativeSelectionPos.X / TILE_DRAW_SIZE,
                                                        (int)relativeSelectionPos.Y / TILE_DRAW_SIZE);

                return(mouseTilePos);
            }

            var selectionTilePos = getMouseTile();

            if (Input.leftMouseButtonPressed)
            {
                // check if there's a selectable item on that tile
                var therePawn = gameState.pawns.FirstOrDefault(x => x.pos.equalTo(selectionTilePos));
                if (therePawn != null)
                {
                    if (therePawn.lastMove < gameState.time)
                    {
                        selectedThing = therePawn;
                    }
                }
            }

            if (Input.rightMouseButtonPressed)
            {
                // check if we had a selection and apply it
                if (selectedThing != null)
                {
                    if (selectedThing is PawnRef pawn)
                    {
                        // TODO: queue sending move message
                        pawnMove?.Invoke(pawn, selectionTilePos);
                        pawn.lastMove = gameState.time;
                        selectedThing = null; // deselect
                    }
                }
            }
        }
Example #21
0
 public static void Reorder(this List <Vertex> vertices, Vector2 pivot)
 {
     vertices.Sort((a, b) => {
         var localA = a.Position - pivot;
         var angleA = Vector2Ext.PositiveAngle(localA);
         var localB = b.Position - pivot;
         var angleB = Vector2Ext.PositiveAngle(localB);
         if (angleA == angleB)
         {
             return(0);
         }
         var delta = angleA - angleB;
         if (delta > 0)
         {
             return(1);
         }
         return(-1);
     });
 }
        /// <summary>
        /// works for circles whos center is in the box as well as just overlapping with the center out of the box.
        /// </summary>
        /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns>
        /// <param name="circle">First.</param>
        /// <param name="box">Second.</param>
        /// <param name="result">Result.</param>
        public static bool CircleToBox(Circle circle, Box box, out CollisionResult result)
        {
            result = new CollisionResult();

            var closestPointOnBounds =
                box.bounds.GetClosestPointOnRectangleBorderToPoint(circle.position, out result.Normal);

            // deal with circles whos center is in the box first since its cheaper to see if we are contained
            if (box.ContainsPoint(circle.position))
            {
                result.Point = closestPointOnBounds;

                // calculate mtv. Find the safe, non-collided position and get the mtv from that.
                var safePlace = closestPointOnBounds + result.Normal * circle.Radius;
                result.MinimumTranslationVector = circle.position - safePlace;

                return(true);
            }

            float sqrDistance;

            Vector2.DistanceSquared(ref closestPointOnBounds, ref circle.position, out sqrDistance);

            // see if the point on the box is less than radius from the circle
            if (sqrDistance == 0)
            {
                result.MinimumTranslationVector = result.Normal * circle.Radius;
            }
            else if (sqrDistance <= circle.Radius * circle.Radius)
            {
                result.Normal = circle.position - closestPointOnBounds;
                var depth = result.Normal.Length() - circle.Radius;

                result.Point = closestPointOnBounds;
                Vector2Ext.Normalize(ref result.Normal);
                result.MinimumTranslationVector = depth * result.Normal;

                return(true);
            }

            return(false);
        }
Example #23
0
        /// <summary>
        /// iterates all the edges of the polygon and gets the closest point on any edge to point. Returns via out the squared distance
        /// to the closest point and the normal of the edge it is on. point should be in the space of the Polygon (point - poly.position)
        /// </summary>
        /// <returns>The closest point on polygon to point.</returns>
        /// <param name="point">Point.</param>
        /// <param name="distanceSquared">Distance squared.</param>
        /// <param name="edgeNormal">Edge normal.</param>
        public static Vector2 getClosestPointOnPolygonToPoint(
            Vector2[] points,
            Vector2 point,
            out float distanceSquared,
            out Vector2 edgeNormal)
        {
            distanceSquared = float.MaxValue;
            edgeNormal      = Vector2.Zero;
            var closestPoint = Vector2.Zero;

            float tempDistanceSquared;

            for (var i = 0; i < points.Length; i++)
            {
                var j = i + 1;
                if (j == points.Length)
                {
                    j = 0;
                }

                var closest = ShapeCollisions.closestPointOnLine(points[i], points[j], point);
                Vector2.DistanceSquared(ref point, ref closest, out tempDistanceSquared);

                if (tempDistanceSquared < distanceSquared)
                {
                    distanceSquared = tempDistanceSquared;
                    closestPoint    = closest;

                    // get the normal of the line
                    var line = points[j] - points[i];
                    edgeNormal.X = -line.Y;
                    edgeNormal.Y = line.X;
                }
            }

            Vector2Ext.normalize(ref edgeNormal);

            return(closestPoint);
        }
Example #24
0
    public void MoveClockwise(float units)
    {
        if (_target == null)
        {
            return;
        }

        var normalAngle = (_target.rotation + _curPos.normalDegrees) * Mathf.Deg2Rad;
        var normal      = Vector2Ext.FromPolar(1, normalAngle);
        var moveVec     = Vector2Ext.FromPolar(units, normalAngle - Mathf.PI / 2);
        var newPos      = transform.position.AsVector2() + moveVec;

        if (linecastAndSnap(newPos + normal, newPos - normal))
        {
            return;
        }

        var cornerTestRot = -45 * Mathf.Sign(units);
        var cornerNormal  = normal.Rotate(cornerTestRot);
        var cornerMoveVec = moveVec.Rotate(cornerTestRot);
        var cornerNewPos  = transform.position.AsVector2() + cornerMoveVec;

        if (linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal))
        {
            return;
        }

        cornerTestRot = 45 * Mathf.Sign(units);
        cornerNormal  = normal.Rotate(cornerTestRot);
        cornerMoveVec = moveVec.Rotate(cornerTestRot);
        cornerNewPos  = transform.position.AsVector2() + cornerMoveVec;

        if (linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal))
        {
            return;
        }
    }
        private void hitMelee()
        {
            // perform a melee hit
            var meleeWeapon     = entity.getComponent <MeleeWeapon>();
            var dir             = lastFacing == Direction.Right ? 1 : -1;
            var facingFlipScale = new Vector2(dir, 1);
            var offset          = meleeWeapon.offset;

            offset = Vector2Ext.transform(offset, Matrix2D.createScale(facingFlipScale));
            var reach = meleeWeapon.reach;

            // reflect X based on direction
            RectangleExt.scale(ref reach, facingFlipScale);
//            var swordCollider = new BoxCollider(offset.X + reach.X,
//               offset.Y + reach.Y, reach.Width, reach.Height);
            var swordCollider = new BoxCollider(0, 0, reach.Width, reach.Height);

            swordCollider.localOffset = new Vector2(offset.X + reach.X + reach.Width / 2f,
                                                    offset.Y + reach.Y + reach.Height / 2f);
            entity.addComponent(swordCollider);
            collisionResults.Clear();
            swordCollider.collidesWithAnyMultiple(Vector2.Zero, collisionResults);

            for (var i = 0; i < collisionResults.Count; i++)
            {
                var result = collisionResults[i];

                var character = result.collider?.entity.getComponent <Character>();
                if (character != null)
                {
                    hurtCharacter(character);
                }
            }

            entity.removeComponent(swordCollider);
        }
Example #26
0
        private static List <Vector2> CubicCurve(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, int numberOfLimit, bool cubic)
        {
            List <Vector2> output = new List <Vector2>();

            //MoveTo the first Point;
            //How many times the curve change form innegative -> negative or vice versa
            int   _limit = numberOfLimit;
            float t1, t2, _flatness;

            t1 = 0.0f;
            //t1 is the start point of [0..1].
            t2 = 1.0f;
            //t2 is the end point of [0..1]
            _flatness = 1.0f;

            Vector2Ext _pStart, _pEnd, _pMid;

            _pStart = new Vector2Ext(cubic ? EvaluateForCubic(t1, p1, p2, p3, p4) : EvaluateForQuadratic(t1, p1, p2, p3, p4), t1);

            _pEnd = new Vector2Ext(cubic ? EvaluateForCubic(t2, p1, p2, p3, p4) : EvaluateForQuadratic(t2, p1, p2, p3, p4), t2);

            // The point on Line Segment[_pStart, _pEnd] correlate with _t

            _stack.Clear();
            _stack.Push(_pEnd);
            //Push End Point into Stack
            //Array of Change Point
            _limitList.Clear();
            if (_limitList.Capacity < _limit + 1)
            {
                _limitList.Capacity = _limit + 1;
            }

            int _count = 0;

            while (true)
            {
                _count++;
                float _tm = (t1 + t2) / 2;
                //tm is a middle of t1 .. t2. [t1 .. tm .. t2]
                //The point on the Curve correlate with tm
                _pMid = new Vector2Ext(cubic ? EvaluateForCubic(_tm, p1, p2, p3, p4) : EvaluateForQuadratic(_tm, p1, p2, p3, p4), _tm);

                //Calculate Distance from Middle Point to the Flatnet
                float dist = Distance(_pStart.point, ((Vector2Ext)_stack.Peek()).point, _pMid.point);

                //flag = true, Curve Segment must be drawn, else continue calculate other middle point.
                bool flag = false;
                if (dist < _flatness)
                {
                    int   i  = 0;
                    float mm = 0.0f;

                    for (i = 0; i < _limit; i++)
                    {
                        mm = (t1 + _tm) / 2;

                        Vector2Ext _q = new Vector2Ext(cubic ? EvaluateForCubic(mm, p1, p2, p3, p4) : EvaluateForQuadratic(mm, p1, p2, p3, p4), mm);
                        if (_limitList.Count - 1 < i)
                        {
                            _limitList.Add(_q);
                        }
                        else
                        {
                            _limitList[i] = _q;
                        }
                        dist = Distance(_pStart.point, _pMid.point, _q.point);
                        if (dist >= _flatness)
                        {
                            break;
                        }
                        else
                        {
                            _tm = mm;
                        }
                    }

                    if (i == _limit)
                    {
                        flag = true;
                    }
                    else
                    {
                        //Continue calculate the first point has Distance > Flatness
                        _stack.Push(_pMid);

                        for (int j = 0; j <= i; j++)
                        {
                            _stack.Push(_limitList[j]);
                        }
                        t2 = mm;
                    }
                }

                if (flag)
                {
                    output.Add(_pStart.point);
                    output.Add(_pMid.point);

                    _pStart = _stack.Pop();

                    if (_stack.Count == 0)
                    {
                        break;
                    }

                    _pMid = _stack.Peek();
                    t1    = t2;
                    t2    = _pMid.t;
                }
                else if (t2 > _tm)
                {
                    //If Distance > Flatness and t1 < tm < t2 then new t2 is tm.
                    _stack.Push(_pMid);
                    t2 = _tm;
                }
            }
            output.Add(_pStart.point);
            return(output);
        }
 private static List<Vector2> CubicCurve(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, int numberOfLimit, bool cubic) {
     
     List<Vector2> output = new List<Vector2>();
     
     //MoveTo the first Point;
     //How many times the curve change form innegative -> negative or vice versa
     int _limit = numberOfLimit;
     float t1, t2, _flatness;
     t1 = 0.0f;
     //t1 is the start point of [0..1].
     t2 = 1.0f;
     //t2 is the end point of [0..1]
     _flatness = 1.0f;
     
     Vector2Ext _pStart, _pEnd, _pMid;
     _pStart = new Vector2Ext(cubic ? EvaluateForCubic(t1, p1, p2, p3, p4) : EvaluateForQuadratic(t1, p1, p2, p3, p4), t1);
     
     _pEnd = new Vector2Ext(cubic ? EvaluateForCubic(t2, p1, p2, p3, p4) : EvaluateForQuadratic(t2, p1, p2, p3, p4), t2);
     
     // The point on Line Segment[_pStart, _pEnd] correlate with _t
     
     _stack.Clear();
     _stack.Push(_pEnd);
     //Push End Point into Stack
     //Array of Change Point
     _limitList.Clear();
     if(_limitList.Capacity < _limit + 1)
         _limitList.Capacity = _limit + 1;
     
     int _count = 0;
     while(true) {
         _count++;
         float _tm = (t1 + t2) / 2;
         //tm is a middle of t1 .. t2. [t1 .. tm .. t2]
         //The point on the Curve correlate with tm
         _pMid = new Vector2Ext(cubic ? EvaluateForCubic(_tm, p1, p2, p3, p4) : EvaluateForQuadratic(_tm, p1, p2, p3, p4), _tm);
         
         //Calculate Distance from Middle Point to the Flatnet
         float dist = Distance(_pStart.point, ((Vector2Ext)_stack.Peek()).point, _pMid.point);
         
         //flag = true, Curve Segment must be drawn, else continue calculate other middle point.
         bool flag = false;
         if(dist < _flatness) {
             int i = 0;
             float mm = 0.0f;
             
             for(i = 0; i < _limit; i++) {
                 mm = (t1 + _tm) / 2;
                 
                 Vector2Ext _q = new Vector2Ext(cubic ? EvaluateForCubic(mm, p1, p2, p3, p4) : EvaluateForQuadratic(mm, p1, p2, p3, p4), mm);
                 if(_limitList.Count - 1 < i)
                     _limitList.Add(_q);
                 else
                     _limitList[i] = _q;
                 dist = Distance(_pStart.point, _pMid.point, _q.point);
                 if(dist >= _flatness) {
                     break;
                 } else {
                     _tm = mm;
                 }
             }
             
             if(i == _limit) {
                 flag = true;
             } else {
                 //Continue calculate the first point has Distance > Flatness
                 _stack.Push(_pMid);
                 
                 for(int j = 0; j <= i; j++)
                     _stack.Push(_limitList[j]);
                 t2 = mm;
             }
         }
         
         if(flag) {
             output.Add(_pStart.point);
             output.Add(_pMid.point);
             
             _pStart = _stack.Pop();
             
             if(_stack.Count == 0)
                 break;
             
             _pMid = _stack.Peek();
             t1 = t2;
             t2 = _pMid.t;
         } else if(t2 > _tm) {
             //If Distance > Flatness and t1 < tm < t2 then new t2 is tm.
             _stack.Push(_pMid);
             t2 = _tm;
         }
     }
     output.Add(_pStart.point);
     return output;
 }
Example #28
0
        /// <summary>
        /// old SpriteBatch drawing method. This should probably be removed since SpriteBatch was replaced by Batcher
        /// </summary>
        /// <param name="spriteBatch">Sprite batch.</param>
        /// <param name="text">Text.</param>
        /// <param name="position">Position.</param>
        /// <param name="color">Color.</param>
        /// <param name="rotation">Rotation.</param>
        /// <param name="origin">Origin.</param>
        /// <param name="scale">Scale.</param>
        /// <param name="effect">Effect.</param>
        /// <param name="depth">Depth.</param>
        internal void drawInto(SpriteBatch spriteBatch, ref FontCharacterSource text, Vector2 position, Color color,
                               float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth)
        {
            var flipAdjustment = Vector2.Zero;

            var flippedVert = (effect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
            var flippedHorz = (effect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;

            if (flippedVert || flippedHorz)
            {
                Vector2 size;
                measureString(ref text, out size);

                if (flippedHorz)
                {
                    origin.X        *= -1;
                    flipAdjustment.X = -size.X;
                }

                if (flippedVert)
                {
                    origin.Y        *= -1;
                    flipAdjustment.Y = lineHeight - size.Y;
                }
            }


            var requiresTransformation = flippedHorz || flippedVert || rotation != 0f || scale != Vector2.One;

            if (requiresTransformation)
            {
                Matrix2D temp;
                Matrix2D.CreateTranslation(-origin.X, -origin.Y, out _transformationMatrix);
                Matrix2D.CreateScale((flippedHorz ? -scale.X : scale.X), (flippedVert ? -scale.Y : scale.Y), out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
                Matrix2D.CreateTranslation(flipAdjustment.X, flipAdjustment.Y, out temp);
                Matrix2D.Multiply(ref temp, ref _transformationMatrix, out _transformationMatrix);
                Matrix2D.CreateRotationZ(rotation, out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
                Matrix2D.CreateTranslation(position.X, position.Y, out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
            }

            BitmapFontRegion currentFontRegion = null;
            var offset = requiresTransformation ? Vector2.Zero : position - origin;

            for (var i = 0; i < text.Length; ++i)
            {
                var c = text[i];
                if (c == '\r')
                {
                    continue;
                }

                if (c == '\n')
                {
                    offset.X          = requiresTransformation ? 0f : position.X - origin.X;
                    offset.Y         += lineHeight;
                    currentFontRegion = null;
                    continue;
                }

                if (currentFontRegion != null)
                {
                    offset.X += spacing + currentFontRegion.xAdvance;
                }

                if (!_characterMap.TryGetValue(c, out currentFontRegion))
                {
                    currentFontRegion = defaultCharacterRegion;
                }


                var p = offset;

                if (flippedHorz)
                {
                    p.X += currentFontRegion.width;
                }
                p.X += currentFontRegion.xOffset;

                if (flippedVert)
                {
                    p.Y += currentFontRegion.height - lineHeight;
                }
                p.Y += currentFontRegion.yOffset;

                // transform our point if we need to
                if (requiresTransformation)
                {
                    Vector2Ext.Transform(ref p, ref _transformationMatrix, out p);
                }

                var destRect = RectangleExt.fromFloats
                               (
                    p.X, p.Y,
                    currentFontRegion.width * scale.X,
                    currentFontRegion.height * scale.Y
                               );

                spriteBatch.Draw(currentFontRegion.subtexture, destRect, currentFontRegion.subtexture.sourceRect, color, rotation, Vector2.Zero, effect, depth);
            }
        }
Example #29
0
    UpdateResult doUpdatePosition(float vx, Func <Vector2, bool> normalCheck, int collisionValue, bool collisionSolid, bool checkWalls)
    {
        var normalAngle = ((_targetBody ? _targetBody.rotation : _target.transform.rotation.z) + _curPos.normalDegrees) * Mathf.Deg2Rad;

        if (!checkWalls && Mathf.Abs(vx) < 0.0001f)
        {
            return(new UpdateResult {
                stillStanding = normalCheck(Vector2Ext.FromPolar(1, normalAngle)),
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        if (FixVX)
        {
            vx /= Mathf.Cos(normalAngle - Mathf.PI / 2);
        }

        var pos = surfaceCoordsToWorldCoords(_curPos);

        var normal  = Vector2Ext.FromPolar(1, normalAngle);
        var tangent = normal.Rotate(-90);
        var moveVec = vx * tangent;
        var newPos  = pos + moveVec;

        if (checkWalls)
        {
            var newMiddle = newPos + (GravitySetting.Reverse ? -1 : 1) * Vector2.up * _heroDim.HalfHeight;
            var wallTestL = newMiddle - (tangent * _heroDim.HalfWidth) / tangent.x;
            var wallTestR = newMiddle + (tangent * _heroDim.HalfWidth) / tangent.x;

            Debug.DrawLine(wallTestL, wallTestR, Color.magenta);

            bool pushed;
            var  penetration = wallTest(wallTestL, wallTestR, vx > 0 ? PushForce : -PushForce, out pushed, normalCheck);

            if (penetration.HasValue)
            {
                var depth = penetration.Value;
                if (GravitySetting.Reverse)
                {
                    depth *= -1;
                }
                var colVal = 0;
                if (!pushed)
                {
                    colVal = depth > 0 ? 1 : -1;
                }
                return(doUpdatePosition(vx - depth, normalCheck, colVal, !pushed, false));
            }

            if (Mathf.Abs(vx) < 0.0001f)
            {
                return(new UpdateResult {
                    stillStanding = normalCheck(Vector2Ext.FromPolar(1, normalAngle)),
                    wallCollision = collisionValue,
                    solidWallCollision = collisionSolid
                });
            }
        }

        // Check if the center ray of the player hits the target collider.

        if (maybeMoveToSnap(linecastAndSnap(newPos + normal, newPos - normal), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        // Check if we're walking around a 90 degree or greater bend.

        var cornerTestRot = -45 * Mathf.Sign(vx);
        var cornerNormal  = normal.Rotate(cornerTestRot);
        var cornerMoveVec = moveVec.Rotate(cornerTestRot);
        var cornerNewPos  = pos + cornerMoveVec;

        if (maybeMoveToSnap(linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        // Check if we're edging out where the center doesn't collider, but an edge does.
        var edgeVec = tangent * (_heroDim.HalfWidth - _heroDim.InsetX);

        if (maybeMoveToSnap(linecastAndSnap(newPos + edgeVec + normal, newPos + edgeVec - normal, -edgeVec), normalCheck) ||
            maybeMoveToSnap(linecastAndSnap(newPos - edgeVec + normal, newPos - edgeVec - normal, edgeVec), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        return(new UpdateResult {
            stillStanding = false,
            wallCollision = collisionValue,
            solidWallCollision = collisionSolid
        });
    }
Example #30
0
        public void DrawInto(Batcher batcher, ref FontCharacterSource text, Vector2 position, Color color,
                             float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth)
        {
            var flipAdjustment = Vector2.Zero;

            var flippedVert = (effect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
            var flippedHorz = (effect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;

            if (flippedVert || flippedHorz)
            {
                var size = MeasureString(ref text);

                if (flippedHorz)
                {
                    origin.X        *= -1;
                    flipAdjustment.X = -size.X;
                }

                if (flippedVert)
                {
                    origin.Y        *= -1;
                    flipAdjustment.Y = LineHeight - size.Y;
                }
            }


            var requiresTransformation = flippedHorz || flippedVert || rotation != 0f || scale != new Vector2(1);

            if (requiresTransformation)
            {
                Matrix2D temp;
                Matrix2D.CreateTranslation(-origin.X, -origin.Y, out _transformationMatrix);
                Matrix2D.CreateScale((flippedHorz ? -scale.X : scale.X), (flippedVert ? -scale.Y : scale.Y), out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
                Matrix2D.CreateTranslation(flipAdjustment.X, flipAdjustment.Y, out temp);
                Matrix2D.Multiply(ref temp, ref _transformationMatrix, out _transformationMatrix);
                Matrix2D.CreateRotation(rotation, out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
                Matrix2D.CreateTranslation(position.X, position.Y, out temp);
                Matrix2D.Multiply(ref _transformationMatrix, ref temp, out _transformationMatrix);
            }

            var       previousCharacter = ' ';
            Character currentChar       = null;
            var       offset            = requiresTransformation ? Vector2.Zero : position - origin;

            for (var i = 0; i < text.Length; ++i)
            {
                var c = text[i];
                if (c == '\r')
                {
                    continue;
                }

                if (c == '\n')
                {
                    offset.X    = requiresTransformation ? 0f : position.X - origin.X;
                    offset.Y   += LineHeight;
                    currentChar = null;
                    continue;
                }

                if (currentChar != null)
                {
                    offset.X += Spacing.X + currentChar.XAdvance;
                }

                currentChar = ContainsCharacter(c) ? this[c] : DefaultCharacter;

                var p = offset;

                if (flippedHorz)
                {
                    p.X += currentChar.Bounds.Width;
                }
                p.X += currentChar.Offset.X + GetKerning(previousCharacter, currentChar.Char);

                if (flippedVert)
                {
                    p.Y += currentChar.Bounds.Height - LineHeight;
                }
                p.Y += currentChar.Offset.Y;

                // transform our point if we need to
                if (requiresTransformation)
                {
                    Vector2Ext.Transform(ref p, ref _transformationMatrix, out p);
                }

                var destRect = RectangleExt.FromFloats
                               (
                    p.X, p.Y,
                    currentChar.Bounds.Width * scale.X,
                    currentChar.Bounds.Height * scale.Y
                               );

                batcher.Draw(Textures[currentChar.TexturePage], destRect, currentChar.Bounds, color, rotation, Vector2.Zero, effect, depth);
                previousCharacter = c;
            }
        }
Example #31
0
    SnapResult linecastAndSnap(Vector2 p0, Vector2 p1, Vector2 offset)
    {
        var hitsPrime = Physics2D.LinecastAll(p0, p1, MooseController.CollisionLayerMask);
        var hitsDos   = new List <RaycastHit2D>();

        for (var i = 0; i < hitsPrime.Length; ++i)
        {
            if (_targetBody)
            {
                if (hitsPrime[i].rigidbody == _targetBody)
                {
                    hitsDos.Add(hitsPrime[i]);
                }
            }
            else
            {
                if (hitsPrime[i].collider == _target)
                {
                    hitsDos.Add(hitsPrime[i]);
                }
            }
        }
        if (hitsDos.Count == 0)
        {
            return new SnapResult {
                       success = false
            }
        }
        ;
        var hit = hitsDos[0];

        return(new SnapResult {
            success = true,
            newPos = worldCoordsToSurfaceCoords(hit.point + offset, hit.normal),
            normal = hit.normal
        });
    }

    bool maybeMoveToSnap(SnapResult snap, Func <Vector2, bool> normalCheck)
    {
        if (!snap.success || !normalCheck(snap.normal))
        {
            return(false);
        }
        moveToSurfaceCoord(snap.newPos);
        return(true);
    }

    void moveToSurfaceCoord(SurfaceCoords pos)
    {
        _lastPos    = _curPos;
        _curPos     = pos;
        _updateFlag = true;
    }

    Vector2 surfaceCoordsToWorldCoords(SurfaceCoords s)
    {
        var targetObject = _targetBody ? _targetBody.gameObject : _target.gameObject;

        var theta = (targetObject.transform.rotation.eulerAngles.z + s.degrees) * Mathf.Deg2Rad;

        return(Vector2Ext.FromPolar(s.radius, theta) + targetObject.transform.position.AsVector2());
    }

    SurfaceCoords worldCoordsToSurfaceCoords(Vector2 pos, Vector2 normal)
    {
        var ds          = pos - (_targetBody ? _targetBody.position : _target.transform.position.AsVector2());
        var angleOffset = _targetBody ? _targetBody.rotation : _target.transform.rotation.z;

        return(new SurfaceCoords {
            radius = ds.magnitude,
            degrees = Mathf.Atan2(ds.y, ds.x) * Mathf.Rad2Deg - angleOffset,
            normalDegrees = Mathf.Atan2(normal.y, normal.x) * Mathf.Rad2Deg - angleOffset
        });
    }
}