Ejemplo n.º 1
0
Archivo: Mover.cs Proyecto: prime31/Nez
		/// <summary>
		/// moves the entity taking collisions into account
		/// </summary>
		/// <returns><c>true</c>, if move actor was newed, <c>false</c> otherwise.</returns>
		/// <param name="motion">Motion.</param>
		/// <param name="collisionResult">Collision result.</param>
		public bool move( Vector2 motion, out CollisionResult collisionResult )
		{
			collisionResult = new CollisionResult();

			// no collider? just move and forget about it
			if( entity.getComponent<Collider>() == null || _triggerHelper == null )
			{
				entity.transform.position += motion;
				return false;
			}

			// 1. move all non-trigger Colliders and get closest collision
			var colliders = entity.getComponents<Collider>();
			for( var i = 0; i < colliders.Count; i++ )
			{
				var collider = colliders[i];

				// skip triggers for now. we will revisit them after we move.
				if( collider.isTrigger )
					continue;

				// fetch anything that we might collide with at our new position
				var bounds = collider.bounds;
				bounds.x += motion.X;
				bounds.y += motion.Y;
				var neighbors = Physics.boxcastBroadphaseExcludingSelf( collider, ref bounds, collider.collidesWithLayers );

				foreach( var neighbor in neighbors )
				{
					// skip triggers for now. we will revisit them after we move.
					if( neighbor.isTrigger )
						continue;

					if( collider.collidesWith( neighbor, motion, out collisionResult ) )
					{
						// hit. back off our motion
						motion -= collisionResult.minimumTranslationVector;
					}
				}
			}
			ListPool<Collider>.free( colliders );

			// 2. move entity to its new position if we have a collision else move the full amount. motion is updated when a collision occurs
			entity.transform.position += motion;

			// 3. do an overlap check of all Colliders that are triggers with all broadphase colliders, triggers or not.
			//    Any overlaps result in trigger events.
			_triggerHelper.update();

			return collisionResult.collider != null;
		}
Ejemplo n.º 2
0
        /// <summary>
        /// checks to see if this Collider with motion applied (delta movement vector) collides with any collider. If it does, true will be
        /// returned and result will be populated with collision data. Motion will be set to the maximum distance the Collider can travel
        /// before colliding.
        /// </summary>
        /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
        /// <param name="motion">Motion.</param>
        /// <param name="result">Result.</param>
        public bool collidesWithAny(ref Vector2 motion, out CollisionResult result)
        {
            result = new CollisionResult();

            // fetch anything that we might collide with at our new position
            var colliderBounds = bounds;

            colliderBounds.x += motion.X;
            colliderBounds.y += motion.Y;
            var neighbors = Physics.boxcastBroadphaseExcludingSelf(this, ref colliderBounds, collidesWithLayers);

            // alter the shapes position so that it is in the place it would be after movement so we can check for overlaps
            var oldPosition = shape.position;

            shape.position += motion;

            var didCollide = false;

            foreach (var neighbor in neighbors)
            {
                // skip triggers
                if (neighbor.isTrigger)
                {
                    continue;
                }

                if (collidesWith(neighbor, out result))
                {
                    // hit. back off our motion and our Shape.position
                    motion         -= result.minimumTranslationVector;
                    shape.position -= result.minimumTranslationVector;
                    didCollide      = true;
                }
            }

            // return the shapes position to where it was before the check
            shape.position = oldPosition;

            return(didCollide);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Checks for any collisions a colliser will have following a motion vector and modifies the vector to account for them.
        /// </summary>
        /// <param name="collider"></param>
        /// <param name="motion"></param>
        /// <param name="collisionResult"></param>
        /// <returns>Whether or not there was a collision</returns>
        private bool CheckRaycast(Collider collider, ref Vector2 motion, ref CollisionResult collisionResult)
        {
            var cPosition = collider.AbsolutePosition;

            if (cPosition == new Vector2(float.NaN, float.NaN))
            {
                return(false);
            }
            var cDestination = collider.AbsolutePosition + motion;
            var rayHit       = Physics.Linecast(cPosition, cDestination);

            if (rayHit.Collider != null)
            {
                collisionResult.MinimumTranslationVector = motion - (rayHit.Point - cPosition);
                motion = (rayHit.Point - cPosition);
                collisionResult.Collider = rayHit.Collider;
                collisionResult.Normal   = rayHit.Normal;
                collisionResult.Point    = rayHit.Point;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// checks to see if this Collider collides with any other Colliders in the Scene. The first Collider it intersects will have its collision
        /// data returned in the CollisionResult.
        /// </summary>
        /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
        /// <param name="result">Result.</param>
        public bool collidesWithAny(out CollisionResult result)
        {
            result = new CollisionResult();

            // fetch anything that we might collide with at our new position
            var neighbors = Physics.boxcastBroadphaseExcludingSelf(this, collidesWithLayers);

            foreach (var neighbor in neighbors)
            {
                // skip triggers
                if (neighbor.isTrigger)
                {
                    continue;
                }

                if (collidesWith(neighbor, out result))
                {
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// checks to see if this Collider collides with collider. If it does, true will be returned and result will be populated
 /// with collision data
 /// </summary>
 /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
 /// <param name="collider">Collider.</param>
 /// <param name="result">Result.</param>
 public bool collidesWith(Collider collider, out CollisionResult result)
 {
     return(shape.collidesWithShape(collider.shape, out result));
 }
Ejemplo n.º 6
0
        /// <summary>
        /// moves the entity taking collisions into account
        /// </summary>
        /// <returns><c>true</c>, if move actor was newed, <c>false</c> otherwise.</returns>
        /// <param name="motion">Motion.</param>
        /// <param name="collisionResult">Collision result.</param>
        public bool move(Vector2 motion, out CollisionResult collisionResult)
        {
            collisionResult = new CollisionResult();

            // no collider? just move and forget about it
            if (entity.colliders.Count == 0 || _triggerHelper == null)
            {
                entity.transform.position += motion;
                return(false);
            }

            // remove ourself from the physics system until after we are done moving
            entity.colliders.unregisterAllCollidersWithPhysicsSystem();

            // 1. move all non-trigger Colliders and get closest collision
            var colliders = entity.getColliders();

            for (var i = 0; i < colliders.Count; i++)
            {
                var collider = colliders[i];

                // skip triggers for now. we will revisit them after we move.
                if (collider.isTrigger)
                {
                    continue;
                }

                // fetch anything that we might collide with at our new position
                var bounds = collider.bounds;
                bounds.x += motion.X;
                bounds.y += motion.Y;
                var neighbors = Physics.boxcastBroadphase(ref bounds, collider.collidesWithLayers);

                foreach (var neighbor in neighbors)
                {
                    // skip triggers for now. we will revisit them after we move.
                    if (neighbor.isTrigger)
                    {
                        continue;
                    }

                    if (collider.collidesWith(neighbor, motion, out collisionResult))
                    {
                        // hit. back off our motion
                        motion -= collisionResult.minimumTranslationVector;
                    }
                }
            }
            ListPool <Collider> .free(colliders);

            // 2. move entity to its new position if we have a collision else move the full amount. motion is updated when a collision occurs
            entity.transform.position += motion;

            // 3. do an overlap check of all Colliders that are triggers with all broadphase colliders, triggers or not.
            //    Any overlaps result in trigger events.
            _triggerHelper.update();

            // let Physics know about our new position
            entity.colliders.registerAllCollidersWithPhysicsSystem();

            return(collisionResult.collider != null);
        }
Ejemplo n.º 7
0
		/// <summary>
		/// checks to see if this Collider with motion applied (delta movement vector) collides with any collider. If it does, true will be
		/// returned and result will be populated with collision data. Motion will be set to the maximum distance the Collider can travel
		/// before colliding.
		/// </summary>
		/// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
		/// <param name="motion">Motion.</param>
		/// <param name="result">Result.</param>
		public bool collidesWithAny( ref Vector2 motion, out CollisionResult result )
		{
			result = new CollisionResult();

			// fetch anything that we might collide with at our new position
			var colliderBounds = bounds;
			colliderBounds.x += motion.X;
			colliderBounds.y += motion.Y;
			var neighbors = Physics.boxcastBroadphaseExcludingSelf( this, ref colliderBounds, collidesWithLayers );

			// alter the shapes position so that it is in the place it would be after movement so we can check for overlaps
			var oldPosition = shape.position;
			shape.position += motion;

			var didCollide = false;
			foreach( var neighbor in neighbors )
			{
				// skip triggers
				if( neighbor.isTrigger )
					continue;

				if( collidesWith( neighbor, out result ) )
				{
					// hit. back off our motion and our Shape.position
					motion -= result.minimumTranslationVector;
					shape.position -= result.minimumTranslationVector;
					didCollide = true;
				}
			}

			// return the shapes position to where it was before the check
			shape.position = oldPosition;

			return didCollide;
		}
Ejemplo n.º 8
0
		/// <summary>
		/// checks to see if this Collider collides with any other Colliders in the Scene. The first Collider it intersects will have its collision
		/// data returned in the CollisionResult.
		/// </summary>
		/// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
		/// <param name="result">Result.</param>
		public bool collidesWithAny( out CollisionResult result )
		{
			result = new CollisionResult();

			// fetch anything that we might collide with at our new position
			var neighbors = Physics.boxcastBroadphaseExcludingSelf( this, collidesWithLayers );

			foreach( var neighbor in neighbors )
			{
				// skip triggers
				if( neighbor.isTrigger )
					continue;

				if( collidesWith( neighbor, out result ) )
					return true;
			}

			return false;
		}
Ejemplo n.º 9
0
		/// <summary>
		/// checks to see if this Collider with motion applied (delta movement vector) collides with collider. If it does, true will be
		/// returned and result will be populated with collision data.
		/// </summary>
		/// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
		/// <param name="collider">Collider.</param>
		/// <param name="motion">Motion.</param>
		/// <param name="result">Result.</param>
		public bool collidesWith( Collider collider, Vector2 motion, out CollisionResult result )
		{
			// alter the shapes position so that it is in the place it would be after movement so we can check for overlaps
			var oldPosition = shape.position;
			shape.position += motion;

			var didCollide = shape.collidesWithShape( collider.shape, out result );
			if( didCollide )
				result.collider = collider;

			// return the shapes position to where it was before the check
			shape.position = oldPosition;

			return didCollide;
		}
Ejemplo n.º 10
0
		/// <summary>
		/// checks to see if this Collider collides with collider. If it does, true will be returned and result will be populated
		/// with collision data
		/// </summary>
		/// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
		/// <param name="collider">Collider.</param>
		/// <param name="result">Result.</param>
		public bool collidesWith( Collider collider, out CollisionResult result )
		{
			if( shape.collidesWithShape( collider.shape, out result ) )
			{
				result.collider = collider;
				return true;
			}
			return false;
		}
Ejemplo n.º 11
0
        /// <summary>
        /// caculates the movement modifying the motion vector to take into account any collisions that will
        /// occur when moving
        /// </summary>
        /// <returns><c>true</c>, if movement was calculated, <c>false</c> otherwise.</returns>
        /// <param name="motion">Motion.</param>
        /// <param name="collisionResult">Collision result.</param>
        public bool CalculateMovement(ref Vector2 motion, out CollisionResult collisionResult)
        {
            collisionResult = new CollisionResult();

            // no collider? just move and forget about it
            if (Entity.GetComponent <Collider>() == null || _triggerHelper == null)
            {
                return(false);
            }

            // 1. move all non-trigger Colliders and get closest collision
            var colliders = Entity.GetComponents <Collider>();

            for (var i = 0; i < colliders.Count; i++)
            {
                var collider = colliders[i];

                // skip triggers for now. we will revisit them after we move.
                if (collider.IsTrigger)
                {
                    continue;
                }


                // check for any collisions along the line to the destination
                bool colliding = collider.CollidesWithAny(out var _);
                CheckRaycast(collider, ref motion, ref collisionResult);


                // fetch anything that we might collide with at our new position
                var bounds = collider.Bounds;
                bounds.X += motion.X;
                bounds.Y += motion.Y;
                var neighbors =
                    Physics.BoxcastBroadphaseExcludingSelf(collider, ref bounds, collider.CollidesWithLayers);

                foreach (var neighbor in neighbors)
                {
                    // skip triggers for now. we will revisit them after we move.
                    if (neighbor.IsTrigger)
                    {
                        continue;
                    }

                    if (collider.CollidesWith(neighbor, motion, out CollisionResult _InternalcollisionResult))
                    {
                        // hit. back off our motion
                        motion -= _InternalcollisionResult.MinimumTranslationVector;

                        // If we hit multiple objects, only take on the first for simplicity sake.
                        if (_InternalcollisionResult.Collider != null)
                        {
                            collisionResult = _InternalcollisionResult;
                        }
                    }
                }


                // auxilery check just in case
                if (!colliding && CheckRaycast(collider, ref motion, ref collisionResult))
                {
                    motion = new Vector2();
                }
            }

            ListPool <Collider> .Free(colliders);

            return(collisionResult.Collider != null);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// moves the entity taking collisions into account
        /// </summary>
        /// <returns><c>true</c>, if move actor was newed, <c>false</c> otherwise.</returns>
        /// <param name="motion">Motion.</param>
        /// <param name="collisionResult">Collision result.</param>
        public bool move( Vector2 motion, out CollisionResult collisionResult )
        {
            collisionResult = new CollisionResult();

            // no collider? just move and forget about it
            if( entity.colliders.Count == 0 )
            {
                entity.transform.position += motion;
                return false;
            }

            // remove ourself from the physics system until after we are done moving
            entity.colliders.unregisterAllCollidersWithPhysicsSystem();

            // 1. move all non-trigger entity.colliders and get closest collision
            for( var i = 0; i < entity.colliders.Count; i++ )
            {
                var collider = entity.colliders[i];

                // skip triggers for now. we will revisit them after we move.
                if( collider.isTrigger )
                    continue;

                // fetch anything that we might collide with at our new position
                var bounds = collider.bounds;
                bounds.x += motion.X;
                bounds.y += motion.Y;
                var neighbors = Physics.boxcastBroadphase( ref bounds, collider.collidesWithLayers );

                foreach( var neighbor in neighbors )
                {
                    // skip triggers for now. we will revisit them after we move.
                    if( neighbor.isTrigger )
                        continue;

                    if( collider.collidesWith( neighbor, motion, out collisionResult ) )
                    {
                        // hit. back off our motion
                        motion -= collisionResult.minimumTranslationVector;
                    }
                }
            }

            // 2. move entity to its new position if we have a collision else move the full amount. motion is updated when a collision occurs
            entity.transform.position += motion;

            // 3. do an overlap check of all entity.colliders that are triggers with all broadphase colliders, triggers or not.
            //    Any overlaps result in trigger events.
            for( var i = 0; i < entity.colliders.Count; i++ )
            {
                var collider = entity.colliders[i];

                // fetch anything that we might collide with us at our new position
                var neighbors = Physics.boxcastBroadphase( collider.bounds, collider.collidesWithLayers );
                foreach( var neighbor in neighbors )
                {
                    // we need at least one of the colliders to be a trigger
                    if( !collider.isTrigger && !neighbor.isTrigger )
                        continue;

                    if( collider.overlaps( neighbor ) )
                    {
                        var pair = new Pair<Collider>( collider, neighbor );

                        // if we already have this pair in one of our sets (the previous or current trigger intersections) dont call the enter event
                        var shouldReportTriggerEvent = !_activeTriggerIntersections.Contains( pair ) && !_previousTriggerIntersections.Contains( pair );
                        if( shouldReportTriggerEvent )
                            notifyTriggerListeners( pair, true );

                        _activeTriggerIntersections.Add( pair );
                    } // overlaps
                } // end foreach
            }

            // let Physics know about our new position
            entity.colliders.registerAllCollidersWithPhysicsSystem();

            checkForExitedColliders();

            return collisionResult.collider != null;
        }
Ejemplo n.º 13
0
        /// <summary>
        /// moves the entity taking collisions into account
        /// </summary>
        /// <returns><c>true</c>, if move actor was newed, <c>false</c> otherwise.</returns>
        /// <param name="motion">Motion.</param>
        /// <param name="collisionResult">Collision result.</param>
        public bool move(Vector2 motion, out CollisionResult collisionResult)
        {
            collisionResult = new CollisionResult();

            // no collider? just move and forget about it
            if (entity.colliders.Count == 0)
            {
                entity.transform.position += motion;
                return(false);
            }

            // remove ourself from the physics system until after we are done moving
            entity.colliders.unregisterAllCollidersWithPhysicsSystem();

            // 1. move all non-trigger entity.colliders and get closest collision
            for (var i = 0; i < entity.colliders.Count; i++)
            {
                var collider = entity.colliders[i];

                // skip triggers for now. we will revisit them after we move.
                if (collider.isTrigger)
                {
                    continue;
                }

                // fetch anything that we might collide with at our new position
                var bounds = collider.bounds;
                bounds.x += motion.X;
                bounds.y += motion.Y;
                var neighbors = Physics.boxcastBroadphase(ref bounds, collider.collidesWithLayers);

                foreach (var neighbor in neighbors)
                {
                    // skip triggers for now. we will revisit them after we move.
                    if (neighbor.isTrigger)
                    {
                        continue;
                    }

                    CollisionResult tempCollisionResult;
                    if (collider.collidesWith(neighbor, motion, out tempCollisionResult))
                    {
                        // hit. compare with the previous hit (if we have one) and choose the one that is closest (smallest MTV)
                        if (collisionResult.collider == null ||
                            collisionResult.minimumTranslationVector.LengthSquared() > tempCollisionResult.minimumTranslationVector.LengthSquared())
                        {
                            collisionResult = tempCollisionResult;
                        }
                    }
                }
            }

            // 2. move entity to its new position if we have a collision else move the full amount
            if (collisionResult.collider != null)
            {
                entity.transform.position += motion - collisionResult.minimumTranslationVector;
            }
            else
            {
                entity.transform.position += motion;
            }

            // 3. do an overlap check of all entity.colliders that are triggers with all broadphase colliders, triggers or not.
            //    Any overlaps result in trigger events.
            for (var i = 0; i < entity.colliders.Count; i++)
            {
                var collider = entity.colliders[i];

                // fetch anything that we might collide with us at our new position
                var neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers);
                foreach (var neighbor in neighbors)
                {
                    // we need at least one of the colliders to be a trigger
                    if (!collider.isTrigger && !neighbor.isTrigger)
                    {
                        continue;
                    }

                    if (collider.overlaps(neighbor))
                    {
                        var pair = new Pair <Collider>(collider, neighbor);

                        // if we already have this pair in one of our sets (the previous or current trigger intersections) dont call the enter event
                        var shouldReportTriggerEvent = !_activeTriggerIntersections.Contains(pair) && !_previousTriggerIntersections.Contains(pair);
                        if (shouldReportTriggerEvent)
                        {
                            notifityTriggerListeners(pair, true);
                        }

                        _activeTriggerIntersections.Add(pair);
                    }             // overlaps
                }                 // end foreach
            }

            // let Physics know about our new position
            entity.colliders.registerAllCollidersWithPhysicsSystem();

            checkForExitedColliders();

            return(collisionResult.collider != null);
        }
Ejemplo n.º 14
0
 /// <summary>
 /// checks to see if this Collider collides with collider. If it does, true will be returned and result will be populated
 /// with collision data
 /// </summary>
 /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns>
 /// <param name="collider">Collider.</param>
 /// <param name="result">Result.</param>
 public bool collidesWith( Collider collider, out CollisionResult result )
 {
     return shape.collidesWithShape( collider.shape, out result );
 }