Example #1
0
        /// <summary>
        /// Construye un circulo según las opciones dadas
        /// </summary>
        /// <param name="id">Id del body</param>
        /// <param name="owner">Owner del body</param>
        /// <param name="isSolid">Si el body es sólido</param>
        /// <param name="relativeToFacing">Determina si se debe tomar en cuenta la dirección 
        /// a la que está mirando la entidad para posicionar el body 
        /// relativo a esa dirección</param>
        /// <param name="radius">Radio del circulo</param>
        /// <returns>Circulo generado</returns>
        public static Sphere CreateCircle(string id, IEntity owner, bool isSolid, bool relativeToFacing, float radius)
        {
            Sphere sphere = new Sphere(id, Vector2.Zero, radius, owner, isSolid);

            if (relativeToFacing)
            {
                bool facingRight = owner.getState(EntityState.FacingRight);
                if (facingRight != true)
                {
                    sphere.MirrorHorizontal(owner.getVectorProperty(EntityProperty.Position));
                }
            }

            return sphere;
        }
Example #2
0
        /// <summary>
        /// Verifica si este poligono esta colisionando o va a colisionar
        /// con una esféra dada.
        /// Para esto se ubica el punto centro de la esfera en la región de voronoi
        /// que le corresponde según el poligono, de forma que obtenemos el punto
        /// mas cercano de la esfera al poligono junto al respectivo eje.
        /// </summary>
        /// <param name="sphere">Esféra con la cual se hará la verificacion</param>
        /// <param name="distance">Distancia por la cual se movera este poligono</param>
        /// <param name="result">Referencia del objeto que contendrá la información necesaria sobre 
        /// si se esta intersectando, si se intersectará y la distancia necesaria 
        /// para evitar una intersección</param>
        protected override CollisionResult IntersectWithSphere(Sphere sphere, ref Vector2 distance)
        {
            CollisionResult result = new CollisionResult();
            result.triggeringBody = this;
            result.affectedBody = sphere;
            // Empezamos asumiendo que las dos figuras no
            // se encuentran intersectando
            result.intersect = false;
            result.willIntersect = false;
            // Se toman tanto la cantidad de puntos
            // como la cantidad de lados del poligono
            int sideCountPolygon = this.sides.Count;
            int pointCountPolygon = this.vertices.Count;
            // Dos valores distintos para guardar
            float minIntervalDistanceAfterMove = float.PositiveInfinity;
            float minIntervalDistance = float.PositiveInfinity;
            Vector2 translationAxis = new Vector2();

            // Ahora se estudia cada lado del poligono para verificar si el centro
            // de la esfera se encuentra perpendicular a algun punto de ese lado
            for (int sideIndex = 0; sideIndex < sideCountPolygon; sideIndex++)
            {
                Line currentSide = this.sides[sideIndex];

                // Se crea un vector paralelo al lado donde puedan proyectase
                // ambos puntos del lado actual mas el centro de la esfera
                Vector2 axis = new Vector2(currentSide.Edge.X, currentSide.Edge.Y);
                axis.Normalize();

                float minA = Vector2.Dot(axis, currentSide.StartPoint);
                float maxA = Vector2.Dot(axis, currentSide.EndPoint);
                float centerB = Vector2.Dot(axis, sphere.Center);

                float velocityProjection = Vector2.Dot(axis, distance);

                // Se realiza un chequeo preliminar antes de sumar el vector
                // de distancia
                #region Verificaciones de intersección actual

                // Si el punto centro se encuentra perpendicular a algun
                // punto del lado actual, entonces la esfera puede encontrarse en esa region
                if (minA <= centerB && maxA >= centerB)
                {
                    // Creamos un eje perpendicular a la linea para obtener la distancia
                    // entre un punto de la linea y el centro de la esfera
                    axis = new Vector2(-currentSide.Edge.Y, currentSide.Edge.X);
                    axis.Normalize();

                    // Ya que el eje es perpendicular, tanto el punto inicial de la linea
                    // como el final terminan en la misma posicion al ser proyectados
                    float pointA = Vector2.Dot(axis, currentSide.EndPoint);
                    float pointB = Vector2.Dot(axis, sphere.Center);

                    // Se obtiene el intervalo y se guarda en caso de que sea menor
                    // al intervalo anterior (La esfera se encontrara en la region de voronoi
                    // que tenga el punto mas cercano desde la esfera hacia el poligono)
                    float intervalDistance = Math.Abs(pointA - pointB);
                    if (intervalDistance < minIntervalDistance)
                    {
                        minIntervalDistance = intervalDistance;
                    }
                }
                #endregion

                // Aplicamos la proyeccion de velocidad a el lado actual
                if (velocityProjection < 0)
                {
                    minA += velocityProjection;
                }
                else
                {
                    maxA += velocityProjection;
                }

                // Si el punto centro se encuentra perpendicular a algun
                // punto del lado actual, entonces la esfera puede encontrarse en esa region
                if (minA <= centerB && maxA >= centerB)
                {
                    // Creamos un eje perpendicular a la linea para obtener la distancia
                    // entre un punto de la linea y el centro de la esfera
                    axis = new Vector2(-currentSide.Edge.Y, currentSide.Edge.X);
                    axis.Normalize();

                    // Volvemos a aplicar la proyeccion de velocidad puesto que
                    // esta vez estamos proyectando en un diferente eje
                    velocityProjection = Vector2.Dot(axis, distance);
                    // Ya que el eje es perpendicular, tanto el punto inicial de la linea
                    // como el final terminan en la misma posicion al ser proyectados
                    float pointA = Vector2.Dot(axis, currentSide.EndPoint) + velocityProjection;
                    float pointB = Vector2.Dot(axis, sphere.Center);

                    // Se obtiene el intervalo y se guarda en caso de que sea menor
                    // al intervalo anterior (La esfera se encontrara en la region de voronoi
                    // que tenga el punto mas cercano desde la esfera hacia el poligono)
                    float intervalDistance = Math.Abs(pointA - pointB);
                    if (intervalDistance < minIntervalDistanceAfterMove)
                    {
                        minIntervalDistanceAfterMove = intervalDistance;
                        translationAxis = axis;

                        Vector2 d = this.Center - sphere.Center;
                        if (Vector2.Dot(d, translationAxis) < 0)
                        {
                            translationAxis = -translationAxis;
                        }
                    }
                }
            }

            // Luego se estudia la distancia entre cada vertice del poligono
            // contra el centro de la esfera, si se encuentra alguna distancia
            // menor que las ya guardadas entonces se guarda
            for (int pointIndex = 0; pointIndex < pointCountPolygon; pointIndex++)
            {
                Vector2 currentPoint = this.vertices[pointIndex];
                // Creamos una linea que vaya desde el vertice hasta el centro
                // de la esfera, sumandole el vector de distancia al vertice
                Line line = new Line(currentPoint + distance, sphere.Center);

                Vector2 axis = new Vector2(line.Edge.X, line.Edge.Y);
                axis.Normalize();

                if (line.Lenght < minIntervalDistanceAfterMove)
                {
                    minIntervalDistanceAfterMove = line.Lenght;
                    translationAxis = axis;

                    Vector2 d = this.Center - sphere.Center;
                    if (Vector2.Dot(d, translationAxis) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }

                // Misma verificacion sin sumar el vector de distancia
                #region Verificaciones de intersección actual
                line = new Line(currentPoint, sphere.Center);

                axis = new Vector2(line.Edge.X, line.Edge.Y);
                axis.Normalize();

                if (line.Lenght < minIntervalDistance)
                {
                    minIntervalDistance = line.Lenght;
                }
                #endregion
            }

            // Se verifica si el poligono intersecta
            bool isInside = this.PointInBody(sphere.Center);
            if (isInside || minIntervalDistance < sphere.Radius)
            {
                result.intersect = true;
            }

            // Se verifica si intersectaran y aplica un vector de transicion
            // diferente dependiendo de si el centro de la esfera se encuentra
            // dentro o fuera del poligono
            isInside = this.PointInBody(sphere.Center - distance);
            if (isInside)
            {
                result.minimumTranslationVector =
                       translationAxis * (sphere.Radius + minIntervalDistanceAfterMove);
                result.willIntersect = true;
            }
            else if (minIntervalDistanceAfterMove < sphere.Radius)
            {
                result.minimumTranslationVector =
                       translationAxis * Math.Abs(sphere.Radius - minIntervalDistanceAfterMove);
                result.willIntersect = true;
            }

            result.translationAxis = translationAxis;
            return result;
        }
Example #3
0
        /// <summary>
        /// Construye un circulo según las opciones dadas
        /// </summary>
        /// <param name="id">Id del body</param>
        /// <param name="owner">Owner del body</param>
        /// <param name="isSolid">Si el body es sólido</param>
        /// <param name="relativeToFacing">Determina si se debe tomar en cuenta la dirección 
        /// a la que está mirando la entidad para posicionar el body 
        /// relativo a esa dirección</param>
        /// <param name="radius">Radio del circulo</param>
        /// <param name="startPosition">Coordenadas de inicio del body</param>
        /// <param name="startCenter">Determina si las coordenadas de inicio se refieren
        /// al punto de inicio desde donde se crea el body o al centro del mismo</param>
        /// <param name="layer">Capa de colisión donde se encontrará el body</param>
        /// <returns>Circulo generado</returns>
        public static Sphere CreateCircle(string id, IEntity owner, bool isSolid, bool relativeToFacing, float radius, Vector2 startPosition, bool startCenter, float layer)
        {
            if (startCenter)
            {
                startPosition.X -= radius;
                startPosition.Y -= radius;
            }

            Sphere sphere = new Sphere(id, startPosition, radius, owner, isSolid);
            sphere.Layer = layer;

            if (relativeToFacing)
            {
                bool facingRight = owner.getState(EntityState.FacingRight);
                if (facingRight != true)
                {
                    sphere.MirrorHorizontal(owner.getVectorProperty(EntityProperty.Position));
                }
            }

            return sphere;
        }
Example #4
0
 /// <summary>
 /// Verifica si este cuerpo esta colisionando o va a colisionar
 /// con una esféra dada
 /// </summary>
 /// <param name="sphere">Esféra con la cual se hará la verificacion</param>
 /// <param name="distance">Distancia por la cual se movera este cuerpo</param>
 /// <param name="result">Referencia del objeto que contendrá la información necesaria sobre 
 /// si se esta intersectando, si se intersectará y la distancia necesaria 
 /// para evitar una intersección</param>
 protected abstract CollisionResult IntersectWithSphere(Sphere sphere, ref Vector2 distance);
Example #5
0
        /// <summary>
        /// Verifica si esta esfera esta colisionando o va a colisionar
        /// con otra esféra dada
        /// </summary>
        /// <param name="sphere">Segunda esféra con la cual se hará la verificacion</param>
        /// <param name="distance">Distancia por la cual se movera la esfera principal (this)</param>
        /// <param name="result">Referencia del objeto que contendrá la información necesaria sobre 
        /// si se esta intersectando, si se intersectará y la distancia necesaria 
        /// para evitar una intersección</param>
        protected override CollisionResult IntersectWithSphere(Sphere sphere, ref Vector2 distance)
        {
            CollisionResult result = new CollisionResult();
            result.triggeringBody = this;
            result.affectedBody = sphere;

            float distanceBetween = 0;
            distanceBetween = Vector2.Distance(this.center, sphere.center);
            result.intersect = distanceBetween < this.radius + sphere.radius;
            distanceBetween = Vector2.Distance(this.center, sphere.center + distance);
            result.willIntersect = distanceBetween < this.radius + sphere.radius;

            if (result.willIntersect)
            {
                Vector2 translationAxis = new Vector2((this.center.X) - (sphere.center.X + distance.X),
                    (this.center.Y) - (sphere.center.Y + distance.Y));
                translationAxis = Vector2.Normalize(translationAxis);
                result.translationAxis = translationAxis;
                result.minimumTranslationVector =
                       translationAxis * ((this.radius + sphere.radius) - distanceBetween);
            }

            return result;
        }