Ejemplo n.º 1
0
        /* Returns true if the two specified entities are colliding.  This
         * method has pixel-level accuracy.
         */
        private static bool CheckCollision(SolidEntity entity1, SolidEntity entity2)
        {
            /* Immediately grab a reference to each particle sprite image
             * (Surface), so that any sprite animation will not trip us up by
             * changing surfaces under us.
             */
            Surface surface1 = entity1.Sprite.Surface;
            Surface surface2 = entity2.Sprite.Surface;

            // Find the position of each particle image.
            Point surface1Position = new Point(Convert.ToInt32(Math.Truncate(entity1.X)), Convert.ToInt32(Math.Truncate(entity1.Y)));
            Point surface2Position = new Point(Convert.ToInt32(Math.Truncate(entity2.X)), Convert.ToInt32(Math.Truncate(entity2.Y)));

            // Find the size of each particle image.
            Size surface1Size = new Size(Convert.ToInt32(Math.Truncate(entity1.Width)), Convert.ToInt32(Math.Truncate(entity1.Height)));
            Size surface2Size = new Size(Convert.ToInt32(Math.Truncate(entity2.Width)), Convert.ToInt32(Math.Truncate(entity2.Height)));

            // Put 'em together to make rectangles.
            Rectangle surface1Rec = new Rectangle(surface1Position, surface1Size);
            Rectangle surface2Rec = new Rectangle(surface2Position, surface2Size);

            if (!surface1Rec.IntersectsWith(surface2Rec))
                /* The two entity's bounding rectangles don't even intersect.
                 * They obviously aren't colliding.
                 */
                // False: entity1 and entity2 are not colliding.
                return false;

            /* Their rectangles do intersect, so now we need to check each
             * pixel in the overlapping area.
             */

            // Find the intersecting rectangle of the two entities.
            Rectangle intersectingRectangle = new Rectangle(surface1Rec.Location, surface1Rec.Size);
            intersectingRectangle.Intersect(surface2Rec);

            Point surface1PixelPosition = new Point();
            Point surface2PixelPosition = new Point();

            /* Lock the two entity's surfaces into memory to allow direct
             * pixel manipulation with high performance.
             */
            surface1.Lock();
            surface2.Lock();

            // Check each overlapping pixel.
            for (int x = 0; x < intersectingRectangle.Width; x++)
                for (int y = 0; y < intersectingRectangle.Height; y++)
                {
                    /* Get the position within each surface of the overlapping
                     * pixel.
                     */
                    surface1PixelPosition.X = intersectingRectangle.X - surface1Rec.X + x;
                    surface1PixelPosition.Y = intersectingRectangle.Y - surface1Rec.Y + y;
                    surface2PixelPosition.X = intersectingRectangle.X - surface2Rec.X + x;
                    surface2PixelPosition.Y = intersectingRectangle.Y - surface2Rec.Y + y;

                    /* Get the color from each surface at the overlapping
                     * pixel.  Unlike the GetPixel and SetPixel operations of
                     * the .NET Image class, the GetPixel and SetPixel
                     * operations of the C# SDL Surface class allow direct
                     * pixel manipulation, and do not create their own locks
                     * (hence the locks happen outside the loop).
                     */
                    Color surface1PixelColor = surface1.GetPixel(surface1PixelPosition);
                    Color surface2PixelColor = surface2.GetPixel(surface2PixelPosition);

                    /* True if the pixel at the overlapping point in the
                     * associated surface is transparent.
                     */
                    bool surface1PixelIsTransparent = surface1.Transparent && surface1PixelColor == surface1.TransparentColor;
                    bool surface2PixelIsTransparent = surface2.Transparent && surface2PixelColor == surface2.TransparentColor;

                    /* If both pixels are non-transparent, then we have a
                     * Collision!
                     */
                    if (!surface1PixelIsTransparent && !surface2PixelIsTransparent)
                    {
                        // Unlock the two surfaces before returning.
                        surface1.Unlock();
                        surface2.Unlock();

                        // True: entity1 and entity2 are colliding.
                        return true;
                    }
                }

            // Unlock the two surfaces before returning.
            surface1.Unlock();
            surface2.Unlock();

            // False: entity1 and entity2 are not colliding.
            return false;
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Find the distance between two SolidEntity objects.
 /// </summary>
 /// <param name="entity1">The first entity.</param>
 /// <param name="entity2">The second entity.</param>
 /// <returns>
 /// The distance (in pixels) between the centers of the two objects.
 /// </returns>
 public static double GetDistance(SolidEntity entity1, SolidEntity entity2)
 {
     // Create a vector between the two entities to find the distance.
     Vector v = new Vector(entity1.Center, entity2.Center);
     return v.Length;
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Detect a collision between this entity and another.
        /// </summary>
        /// <param name="otherSolidEntity">
        /// The other entity to check for collision with this one.
        /// </param>
        /// <returns>
        /// True if the entities are colliding; false otherwise.
        /// </returns>
        public bool Collision(SolidEntity otherSolidEntity)
        {
            if (!this.Alive)
                // Dead entities don't collide, because they don't exist.
                return false;

            bool collisionStatus = SolidEntity.CheckCollision(this, otherSolidEntity);
            bool alreadyCollided = this.currentCollisions.Contains(otherSolidEntity);

            if (!collisionStatus)
            {
                // No Collision detected with the other object.

                if (alreadyCollided)
                    /* Last we checked, we were in a Collision with this other
                     * object, so lets update our Collision list to reflect the
                     * fact that we are no-longer colliding with it.
                     */
                    this.currentCollisions.Remove(otherSolidEntity);

                return false;
            }

            // Collision detected

            if (!alreadyCollided)
            {
                // A brand new Collision!

                this.currentCollisions.Add(otherSolidEntity);
                return true;
            }

            /* A previous Collision with this other object hasn't ended
             * yet.
             */

            if (this.currentCollisions[this.currentCollisions.Count - 1] == otherSolidEntity)
            {
                /* This was the exact last object we collided with (in our
                 * list of currently occurring collisions),  so we treat
                 * this like it never happened.  You saw nothing!
                 */

                return false;
            }
            else
            {
                /* Update the list to reflect that we last collided with this
                 * object.  In other words, move it to the back of the list.
                 */
                this.currentCollisions.Remove(otherSolidEntity);
                this.currentCollisions.Add(otherSolidEntity);

                return true;
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Find the angle between two SolidEntity objects.
 /// </summary>
 /// <param name="entity1">The first (origin) entity.</param>
 /// <param name="entity2">The second (destination) entity.</param>
 /// <returns>
 /// The degree of the angle between the centers of the two entities
 /// (with entity1's center as the origin).
 /// </returns>
 public static int GetDirectionDeg(SolidEntity entity1, SolidEntity entity2)
 {
     // Create a vector between the two entities to find the angle.
     Vector v = new Vector(entity1.Center, entity2.Center);
     return Convert.ToInt32(Math.Truncate(v.DirectionDeg));
 }