Ejemplo n.º 1
0
 public Movement()
 {
     Hits = new Hit[0];
 }
Ejemplo n.º 2
0
        private static Hit ResolveNarrow(Vector2 origin, Vector2 destination, RectangleF other)
        {
            // if starts inside, push it outside at the neareast place
            if (other.Contains(origin))
            {
                var outside = PushOutside(origin, other);
                return(new Hit()
                {
                    Amount = 0,
                    Position = outside.Item1,
                    Normal = outside.Item2,
                });
            }

            var velocity = (destination - origin);

            Vector2 invEntry, invExit, entry, exit;

            if (velocity.X > 0)
            {
                invEntry.X = other.Left - origin.X;
                invExit.X  = other.Right - origin.X;
            }
            else
            {
                invEntry.X = other.Right - origin.X;
                invExit.X  = other.Left - origin.X;
            }

            if (velocity.Y > 0)
            {
                invEntry.Y = other.Top - origin.Y;
                invExit.Y  = other.Bottom - origin.Y;
            }
            else
            {
                invEntry.Y = other.Bottom - origin.Y;
                invExit.Y  = other.Top - origin.Y;
            }

            if (Math.Abs(velocity.X) < Constants.Threshold)
            {
                entry.X = float.MinValue;
                exit.X  = float.MaxValue;
            }
            else
            {
                entry.X = invEntry.X / velocity.X;
                exit.X  = invExit.X / velocity.X;
            }

            if (Math.Abs(velocity.Y) < Constants.Threshold)
            {
                entry.Y = float.MinValue;
                exit.Y  = float.MaxValue;
            }
            else
            {
                entry.Y = invEntry.Y / velocity.Y;
                exit.Y  = invExit.Y / velocity.Y;
            }

            if (entry.Y > 1.0f)
            {
                entry.Y = float.MinValue;
            }
            if (entry.X > 1.0f)
            {
                entry.X = float.MinValue;
            }

            var entryTime = Math.Max(entry.X, entry.Y);
            var exitTime  = Math.Min(exit.X, exit.Y);

            if (
                (entryTime > exitTime || entry.X < 0.0f && entry.Y < 0.0f) ||
                (entry.X < 0.0f && (origin.X < other.Left || origin.X > other.Right)) ||
                entry.Y < 0.0f && (origin.Y < other.Top || origin.Y > other.Bottom))
            {
                return(null);
            }

            var result = new Hit()
            {
                Amount   = entryTime,
                Position = origin + velocity * entryTime,
                Normal   = GetNormal(invEntry, invExit, entry),
            };

            return(result);
        }
Ejemplo n.º 3
0
        private static Hit ResolveNarrow(RectangleF origin, RectangleF destination, RectangleF other)
        {
            // if starts inside, push it outside at the neareast place
            if (other.Contains(origin) || other.Intersects(origin))
            {
                var outside = PushOutside(origin, other);
                return(new Hit()
                {
                    Amount = 0,
                    Position = outside.Item1.Location,
                    Normal = outside.Item2,
                });
            }

            var velocity = (destination.Location - origin.Location);

            //the smallest vector from the origin rect to the hit rect
            Vector2 invEntry;
            // the longest vector from the origin rect to the hit rect
            Vector2 invExit;
            //the time until collision
            Vector2 entry;
            //the time until completly passing the hit rect
            Vector2 exit;

            /*
             * invEntry.X = Math.Min(other.Left - origin.Right, other.Right - origin.Left);
             * invEntry.Y = Math.Min(other.Top - origin.Bottom, other.Bottom - origin.Top);
             * invExit.X = Math.Max(other.Left - origin.Right, other.Right - origin.Left);
             * invExit.Y = Math.Max(other.Top - origin.Bottom, other.Bottom - origin.Top);
             */
            if (velocity.X > 0)
            {
                invEntry.X = other.Left - origin.Right;
                invExit.X  = other.Right - origin.Left;
            }
            else
            {
                invEntry.X = other.Right - origin.Left;
                invExit.X  = other.Left - origin.Right;
            }

            if (velocity.Y > 0)
            {
                invEntry.Y = other.Top - origin.Bottom;
                invExit.Y  = other.Bottom - origin.Top;
            }
            else
            {
                invEntry.Y = other.Bottom - origin.Top;
                invExit.Y  = other.Top - origin.Bottom;
            }

            // calc the time in the current velocity until theres a collision in the
            // x axis and untill the rect passes the collided object in the x axis
            if (Math.Abs(velocity.X) < Constants.Threshold)
            {
                entry.X = float.MinValue;
                exit.X  = float.MaxValue;
            }
            else
            {
                entry.X = invEntry.X / velocity.X;
                exit.X  = invExit.X / velocity.X;
            }

            // calc the time in the current velocity until theres a collision in the
            // y axis and untill the rect passes the collided object in the y axis
            if (Math.Abs(velocity.Y) < Constants.Threshold)
            {
                entry.Y = float.MinValue;
                exit.Y  = float.MaxValue;
            }
            else
            {
                entry.Y = invEntry.Y / velocity.Y;
                exit.Y  = invExit.Y / velocity.Y;
            }

            //if the entry is smalle than one in x then the x axis will not collide after applying the velocity so there is no chace
            // the object wont colide or is already intersecting in the x axis, same for the y.
            if (entry.Y > 1.0f)
            {
                entry.Y = float.MinValue;
            }
            if (entry.X > 1.0f)
            {
                entry.X = float.MinValue;
            }

            // get rid for the min value by taking the max value of the x or the y,
            // min value indicates that theres no collision or already coliding,
            // if the exit x and y is maxvalue then theres no collision for sure
            //
            // the time untill the collision starts
            var entryTime = Math.Max(entry.X, entry.Y);
            // time until the collision ends
            var exitTime = Math.Min(exit.X, exit.Y);


            // if the time untill impact in y is less than 0 and the
            if (
                (entryTime > exitTime || entry.X < 0.0f && entry.Y < 0.0f) ||
                (entry.X < 0.0f && (origin.Right < other.Left || origin.Left > other.Right)) ||
                entry.Y < 0.0f && (origin.Bottom < other.Top || origin.Top > other.Bottom))
            {
                return(null);
            }


            Vector2 normal = GetNormal(invEntry, invExit, entry);

            if (normal.Y == 1)
            {
                Console.WriteLine("collide top");
            }
            Vector2 distance = velocity * entryTime;
            Vector2 position = origin.Location + distance;

            if (velocity.X > Constants.Threshold)
            {
                distance.X += origin.Width;
            }
            if (velocity.Y > Constants.Threshold)
            {
                distance.Y += origin.Height;
            }


            var result = new Hit()
            {
                Amount   = entryTime,
                Position = position,
                Normal   = normal,
            };

            result.distance = invEntry;


            return(result);
        }