public MapCollisionType MoveContactMap(ref Vector2 position, Vector2 vector, Rectangle rectangle, Map map)
        {
            // TODO: Optimize this method.
            if (vector.X != 0 && vector.Y != 0)
            {
                return(MoveContactMap(ref position, vector * Vector2.UnitY, rectangle, map) |
                       MoveContactMap(ref position, vector * Vector2.UnitX, rectangle, map));
            }

            Rectangle        prevRect      = GetAbsoluteAABB(position, rectangle);
            Rectangle        nextRect      = GetAbsoluteAABB(position + vector, rectangle);
            MapCollisionType collisionType = MapCollisionType.None;

            position += vector;

            foreach (TileData tileData in map.GetTilesInRegion(new Rectangle(nextRect.X, nextRect.Y, nextRect.Width - 1, nextRect.Height - 1)))
            {
                Tile      tile     = map.SourceTiles[tileData.SourceID];
                Rectangle cellRect = tileData.Target;

                /*
                 * This must be done because TileData.Target always returns a
                 * rectangle with the center coordinates of the tile, instead
                 * of the top left corner.
                 */
                cellRect.Offset(-cellRect.Width / 2, -cellRect.Height / 2);

                if (vector.X != 0)
                {
                    if ((bool)tile.Properties["left"].AsBoolean && prevRect.Right <= cellRect.Left && nextRect.Right > cellRect.Left)
                    {
                        position.X     = cellRect.Left - rectangle.Width + rectangle.X;
                        collisionType |= MapCollisionType.Right;
                    }
                    else if ((bool)tile.Properties["right"].AsBoolean && prevRect.Left >= cellRect.Right && nextRect.Left < cellRect.Right)
                    {
                        position.X     = cellRect.Right + rectangle.X;
                        collisionType |= MapCollisionType.Left;
                    }
                }
                if (vector.Y != 0)
                {
                    if ((bool)tile.Properties["top"].AsBoolean && prevRect.Bottom <= cellRect.Top && nextRect.Bottom > cellRect.Top)
                    {
                        position.Y     = cellRect.Top - rectangle.Height + rectangle.Y;
                        collisionType |= MapCollisionType.Down;
                    }
                    else if ((bool)tile.Properties["bottom"].AsBoolean && prevRect.Top >= cellRect.Bottom && nextRect.Top < cellRect.Bottom)
                    {
                        position.Y     = cellRect.Bottom + rectangle.Y;
                        collisionType |= MapCollisionType.Up;
                    }
                }
            }

            return(collisionType);
        }
        public override void Process(Entity entity)
        {
            PositionComponent position = entity.GetComponent <PositionComponent>();
            SpeedComponent    speed    = entity.GetComponent <SpeedComponent>();
            AABBComponent     aabb     = entity.GetComponent <AABBComponent>();

            Vector2          new_position = speed.PreviousPosition;
            MapCollisionType type         = MoveContactMap(
                ref new_position,
                position.Position - speed.PreviousPosition,
                aabb.Rectangle,
                EntitySystem.BlackBoard.GetEntry <Map>("Map"));

            position.Position = new_position;

            EventSenderComponent eventSender = entity.GetComponent <EventSenderComponent>();

            if (eventSender != null)
            {
                eventSender.Trigger <MapCollisionEventType>(entity, new MapCollisionEventType(type));
            }
        }
 public MapCollisionEventType(MapCollisionType type)
 {
     this.type = type;
 }