예제 #1
0
        //-----------------------------------------------------------------------------
        // Constructors
        //-----------------------------------------------------------------------------

        public CollisionModel(params Rectangle2I[] boxes)
        {
            this.bounds = Rectangle2I.Zero;
            this.boxes  = new List <Rectangle2I>();
            this.boxes.AddRange(boxes);
            CalcBounds();
        }
예제 #2
0
 //-----------------------------------------------------------------------------
 // Constructors
 //-----------------------------------------------------------------------------
 public CollisionModel(params Rectangle2I[] boxes)
 {
     this.bounds = Rectangle2I.Zero;
     this.boxes = new List<Rectangle2I>();
     this.boxes.AddRange(boxes);
     CalcBounds();
 }
        //-----------------------------------------------------------------------------
        // Constructor
        //-----------------------------------------------------------------------------
        public PlayerSpinSwordState()
        {
            limitTilesToDirection	= false;
            isReswingable			= false;

            lunge					= false;
            swingAnglePullBack		= 0;
            swingAngleDurations		= new int[] { 3, 2, 3, 2, 3, 2, 3, 2, 5 };
            weaponSwingAnimation	= GameData.ANIM_SWORD_SPIN;
            playerSwingAnimation	= GameData.ANIM_PLAYER_SPIN;

            // Will always spin clockwise.
            swingWindingOrders = new WindingOrder[] {
                WindingOrder.Clockwise,
                WindingOrder.Clockwise,
                WindingOrder.Clockwise,
                WindingOrder.Clockwise
            };

            swingCollisionBoxesNoLunge = new Rectangle2I[4, 9];
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 9; j++) {
                    int angle = GMath.Wrap((i * 2) - j, Angles.AngleCount);
                    swingCollisionBoxesNoLunge[i, j] = SWING_TOOL_BOXES_SPIN[angle];
                }
            }
        }
예제 #4
0
 //-----------------------------------------------------------------------------
 // Constructors
 //-----------------------------------------------------------------------------
 // Use Tile.CreateTile() instead of this constructor.
 protected Tile()
 {
     tileGridArea	= Rectangle2I.Zero;
     isAlive				= false;
     isInitialized		= false;
     location			= Point2I.Zero;
     layer				= 0;
     offset				= Point2I.Zero;
     size				= Point2I.One;
     spriteAsObject		= new SpriteAnimation();
     isSolid				= false;
     isMoving			= false;
     pushDelay			= 20;
     properties			= new Properties(this);
     tileData			= null;
     moveDirection		= Point2I.Zero;
     dropList			= null;
     hasMoved			= false;
     path				= null;
     pathTimer			= 0;
     pathMoveIndex		= 0;
     fallsInHoles		= true;
     soundMove			= GameData.SOUND_BLOCK_PUSH;
     conveyorVelocity	= Vector2F.Zero;
     surfaceTile			= null;
     collisionStyle		= CollisionStyle.Rectangular;
     graphics			= new TileGraphicsComponent(this);
 }
예제 #5
0
 public Sprite(Image image, Rectangle2I sourceRect, Point2I drawOffset)
 {
     this.image			= image;
     this.sourceRect		= sourceRect;
     this.drawOffset		= drawOffset;
     this.nextPart		= null;
 }
예제 #6
0
 //-----------------------------------------------------------------------------
 // Constructors
 //-----------------------------------------------------------------------------
 public Sprite()
 {
     this.image			= null;
     this.sourceRect		= Rectangle2I.Zero;
     this.drawOffset		= Point2I.Zero;
     this.nextPart		= null;
 }
예제 #7
0
 public CollisionModel(CollisionModel copy)
 {
     bounds = Rectangle2I.Zero;
     boxes = new List<Rectangle2I>();
     for (int i = 0; i < copy.boxes.Count; ++i)
         boxes.Add(copy.boxes[i]);
 }
예제 #8
0
 // Returns true if this rectangle intersects another.
 public bool Intersects(Rectangle2I other)
 {
     if (IsEmpty && other.IsEmpty)
     {
         return(false);
     }
     return(!(other.Left - Right >= 0 || other.Top - Bottom >= 0 ||
              Left - other.Right >= 0 || Top - other.Bottom >= 0));
 }
예제 #9
0
 // Returns true if the specified rectangle is inside this rectangle.
 public bool Contains(Rectangle2I rect)
 {
     if (IsEmpty || rect.IsEmpty)
     {
         return(false);
     }
     return((rect.Min >= Min) &&
            (rect.Max <= Max));
 }
예제 #10
0
        // Creates a new rectangle that exactly contains two other rectangles.
        public static Rectangle2I Union(Rectangle2I r1, Rectangle2I r2)
        {
            int x1 = Math.Min(r1.Left, r2.Left);
            int y1 = Math.Min(r1.Top, r2.Top);
            int x2 = Math.Max(r1.Right, r2.Right);
            int y2 = Math.Max(r1.Bottom, r2.Bottom);

            return(new Rectangle2I(x1, y1, x2 - x1, y2 - y1));
        }
예제 #11
0
 public CollisionModel(CollisionModel copy)
 {
     bounds = Rectangle2I.Zero;
     boxes  = new List <Rectangle2I>();
     for (int i = 0; i < copy.boxes.Count; ++i)
     {
         boxes.Add(copy.boxes[i]);
     }
 }
예제 #12
0
 //-----------------------------------------------------------------------------
 // Constructors
 //-----------------------------------------------------------------------------
 public EventTile()
 {
     roomControl		= null;
     eventData		= null;
     position		= Vector2F.Zero;
     size			= Point2I.One;
     properties		= new Properties();
     collisionBox	= new Rectangle2I(0, 0, 16, 16);
 }
예제 #13
0
 /** <summary> Returns true if the specified rectangle is colliding with this rectangle. </summary> */
 public bool Colliding(Rectangle2I rect)
 {
     if (IsEmpty || rect.IsEmpty)
     {
         return(false);
     }
     return((rect.Min < Max) &&
            (rect.Max > Min));
 }
예제 #14
0
        //-----------------------------------------------------------------------------
        // Static Methods
        //-----------------------------------------------------------------------------

        // Clamp is exclusive.
        public static Point2I Clamp(Point2I value, Rectangle2I bounds)
        {
            if (bounds.IsEmpty)
            {
                return(Point2I.Zero);
            }
            return(new Point2I(
                       GMath.Clamp(value.X, bounds.Min.X, bounds.Max.X - 1),
                       GMath.Clamp(value.Y, bounds.Min.Y, bounds.Max.Y - 1)));
        }
예제 #15
0
        //-----------------------------------------------------------------------------
        // Drawing
        //-----------------------------------------------------------------------------
        // Draws the HUD.
        public void Draw(Graphics2D g, bool light)
        {
            int lightDark = (light ? GameData.VARIANT_LIGHT : GameData.VARIANT_DARK);

            Rectangle2I r = new Rectangle2I(0, 0, GameSettings.SCREEN_WIDTH, 16);
            g.DrawSprite(GameData.SPR_HUD_BACKGROUND, lightDark, r);

            DrawItems(g, lightDark);
            DrawRupees(g, lightDark);
            DrawHearts(g, lightDark);
        }
예제 #16
0
 //-----------------------------------------------------------------------------
 // Constructor
 //-----------------------------------------------------------------------------
 public UnitTool()
 {
     unit				= null;
     drawAboveUnit		= false;
     animationPlayer		= new AnimationPlayer();
     collisionBox		= new Rectangle2I(-1, -1, 2, 2);
     toolType			= UnitToolType.Visual;
     isEquipped			= false;
     isPhysicsEnabled	= true;
     imageVariantID		= GameData.VARIANT_NONE;
     syncAnimationWithDirection	= true;
 }
예제 #17
0
        //-----------------------------------------------------------------------------
        // Static methods
        //-----------------------------------------------------------------------------

        // Return the intersection between two rectangles.
        // Returns the Empty rect if there is no intersection.
        public static Rectangle2I Intersect(Rectangle2I r1, Rectangle2I r2)
        {
            int x1 = Math.Max(r1.Left, r2.Left);
            int y1 = Math.Max(r1.Top, r2.Top);
            int x2 = Math.Min(r1.Right, r2.Right);
            int y2 = Math.Min(r1.Bottom, r2.Bottom);

            if (x2 > x1 && y2 > y1)
            {
                return(new Rectangle2I(x1, y1, x2 - x1, y2 - y1));
            }
            return(Rectangle2I.Zero);
        }
예제 #18
0
 public Sprite(SpriteSheet sheet, Point2I index, Point2I drawOffset)
 {
     this.image			= sheet.Image;
     this.sourceRect		= new Rectangle2I(
         sheet.Offset.X + (index.X * (sheet.CellSize.X + sheet.Spacing.X)),
         sheet.Offset.Y + (index.Y * (sheet.CellSize.Y + sheet.Spacing.Y)),
         sheet.CellSize.X,
         sheet.CellSize.Y
     );
     this.drawOffset		= new Point2I(drawOffset.X, drawOffset.Y);
     this.image			= sheet.Image;
     this.nextPart		= null;
 }
예제 #19
0
        //-----------------------------------------------------------------------------
        // Internal
        //-----------------------------------------------------------------------------

        // Calculate the bounds rectangle that contains all the boxes.
        private void CalcBounds()
        {
            if (boxes.Count == 0)
            {
                bounds = Rectangle2I.Zero;
                return;
            }
            bounds = boxes[0];
            for (int i = 1; i < boxes.Count; ++i)
            {
                bounds = Rectangle2I.Union(bounds, boxes[i]);
            }
        }
        //-----------------------------------------------------------------------------
        // Overridden Methods
        //-----------------------------------------------------------------------------
        protected override void Initialize()
        {
            base.Initialize();

            solutionReferenceArea	= new Rectangle2I(3, 4, 3, 3);
            solutionArea			= new Rectangle2I(9, 4, 3, 3);
            CreateSolutionReference();

            /*solution = new PuzzleColor[3, 3] {
                { PuzzleColor.Red, PuzzleColor.Red, PuzzleColor.Red },
                { PuzzleColor.Yellow, PuzzleColor.Red, PuzzleColor.Red },
                { PuzzleColor.Blue, PuzzleColor.Red, PuzzleColor.Red },
            };*/

            hasBeenSolvedAlready = false;
            isSolved = false;
        }
예제 #21
0
 // Remove all tiles within the given area.
 public void RemoveArea(Rectangle2I area)
 {
     BaseTileDataInstance[] tiles = GetTilesInArea(area).ToArray();
     foreach (BaseTileDataInstance tile in tiles) {
         tile.Room.Remove(tile);
     }
 }
예제 #22
0
        //-----------------------------------------------------------------------------
        // Internal Iteration
        //-----------------------------------------------------------------------------
        private IEnumerable<BaseTileDataInstance> GetTilesInArea(Rectangle2I area)
        {
            // Make sure the area is within the level bounds.
            area = Rectangle2I.Intersect(area,
                new Rectangle2I(Point2I.Zero, roomSize * dimensions));

            // Iterate the tile grid.
            for (int x = 0; x < area.Width; x++) {
                for (int y = 0; y < area.Height; y++) {
                    LevelTileCoord coord = (LevelTileCoord) (area.Point + new Point2I(x, y));
                    Room room = GetRoom(coord);
                    if (room != null) {
                        Point2I tileLocation = GetTileLocation(coord);
                        for (int i = 0; i < roomLayerCount; i++) {
                            TileDataInstance tile = room.GetTile(tileLocation, i);
                            if (tile != null && tile.Location == tileLocation)
                                yield return tile;
                        }
                    }
                }
            }

            // Determine the collection of rooms that will contain the event tiles.
            Point2I roomAreaMin = GetRoomLocation((LevelTileCoord) area.Min);
            Point2I roomAreaMax = GetRoomLocation((LevelTileCoord) area.Max);
            Rectangle2I roomArea = new Rectangle2I(roomAreaMin, roomAreaMax - roomAreaMin + Point2I.One);
            roomArea = Rectangle2I.Intersect(roomArea, new Rectangle2I(Point2I.Zero, dimensions));
            Rectangle2I pixelArea = new Rectangle2I(
                area.Point * GameSettings.TILE_SIZE,
                area.Size  * GameSettings.TILE_SIZE);

            // Iterate event tiles.
            for (int x = roomArea.Left; x < roomArea.Right; x++) {
                for (int y = roomArea.Top; y < roomArea.Bottom; y++) {
                    Room room = rooms[x, y];
                    for (int i = 0; i < room.EventData.Count; i++) {
                        EventTileDataInstance eventTile = room.EventData[i];
                        Rectangle2I tileBounds = eventTile.GetBounds();
                        tileBounds.Point += room.Location * roomSize * GameSettings.TILE_SIZE;
                        if (pixelArea.Contains(tileBounds.Point))
                            yield return eventTile;
                    }
                }
            }
        }
예제 #23
0
        // Take tiles from the level (or duplicate them) and put them into a tile grid.
        public TileGrid CreateTileGrid(Rectangle2I area, bool duplicate)
        {
            TileGrid tileGrid = new TileGrid(area.Size, roomLayerCount);
            BaseTileDataInstance[] tiles = GetTilesInArea(area).ToArray();

            foreach (BaseTileDataInstance baseTileOriginal in tiles) {
                // Duplicate the tile if specified, else remove the original.
                BaseTileDataInstance baseTile;
                if (duplicate) {
                    baseTile = baseTileOriginal.Duplicate();
                }
                else {
                    baseTile = baseTileOriginal;
                    baseTileOriginal.Room.Remove(baseTileOriginal);
                }

                // Add the tile to the tile grid.
                if (baseTile is TileDataInstance) {
                    TileDataInstance tile = (TileDataInstance) baseTile;
                    tile.Location += tile.Room.Location * roomSize;
                    tile.Location -= area.Point;
                    tileGrid.PlaceTile(tile, tile.Location, tile.Layer);

                }
                else if (baseTile is EventTileDataInstance) {
                    EventTileDataInstance eventTile = (EventTileDataInstance) baseTile;
                    eventTile.Position += eventTile.Room.Location * roomSize * GameSettings.TILE_SIZE;
                    eventTile.Position -= area.Point * GameSettings.TILE_SIZE;
                    tileGrid.AddEventTile(eventTile);
                }
            }

            return tileGrid;
        }
예제 #24
0
        // Place the tiles in a tile grid starting at the given location.
        public void PlaceTileGrid(TileGrid tileGrid, LevelTileCoord location)
        {
            // Remove tiles.
            Rectangle2I area = new Rectangle2I((Point2I) location, tileGrid.Size);
            RemoveArea(area);

            // Place tiles.
            foreach (BaseTileDataInstance baseTile in tileGrid.GetTiles()) {
                if (baseTile is TileDataInstance) {
                    TileDataInstance tile = (TileDataInstance) baseTile;
                    LevelTileCoord coord = (LevelTileCoord) ((Point2I) location + tile.Location);
                    Room room = GetRoom(coord);

                    if (room != null) {
                        tile.Location = GetTileLocation(coord);
                        room.PlaceTile(tile, tile.Location, tile.Layer);
                    }
                }
                else if (baseTile is EventTileDataInstance) {
                    EventTileDataInstance eventTile = (EventTileDataInstance) baseTile;
                    eventTile.Position += (Point2I) location * GameSettings.TILE_SIZE;
                    Point2I roomLocation = eventTile.Position / (roomSize * GameSettings.TILE_SIZE);
                    Room room = GetRoomAt(roomLocation);
                    if (room != null) {
                        eventTile.Position -= roomLocation * roomSize * GameSettings.TILE_SIZE;
                        room.AddEventTile(eventTile);
                    }
                }
            }
        }
예제 #25
0
 public AnimationFrame(int startTime, int duration, Image image, Rectangle2I sourceRect, Point2I drawOffset)
 {
     this.startTime	= startTime;
     this.duration	= duration;
     this.sprite		= new Sprite(image, sourceRect, drawOffset);
 }
예제 #26
0
 // Take tiles from the level and put them into a tile grid.
 public TileGrid CreateTileGrid(Rectangle2I area)
 {
     return CreateTileGrid(area, false);
 }
예제 #27
0
 /** <summary> Constructs a copy of the specified rectangle. </summary> */
 public Rectangle2I(Rectangle2I r)
 {
     this.Point	= r.Point;
     this.Size	= r.Size;
 }
예제 #28
0
        //-----------------------------------------------------------------------------
        // Mutators
        //-----------------------------------------------------------------------------

        // Add a new box to the collision model.
        public CollisionModel AddBox(Rectangle2I box)
        {
            boxes.Add(box);
            CalcBounds();
            return(this);
        }
예제 #29
0
 /** <summary> Returns true if the specified rectangle is colliding with this rectangle. </summary> */
 public bool Colliding(Rectangle2I rect)
 {
     if (IsEmpty || rect.IsEmpty)
         return false;
     return ((rect.Min < Max) &&
             (rect.Max > Min));
 }
예제 #30
0
 // Returns true if the specified rectangle is inside this rectangle.
 public bool Contains(Rectangle2I rect)
 {
     if (IsEmpty || rect.IsEmpty)
         return false;
     return ((rect.Min >= Min) &&
             (rect.Max <= Max));
 }
예제 #31
0
 // Creates a new rectangle that exactly contains two other rectangles.
 public static Rectangle2I Union(Rectangle2I r1, Rectangle2I r2)
 {
     int x1 = Math.Min(r1.Left,   r2.Left);
     int y1 = Math.Min(r1.Top,    r2.Top);
     int x2 = Math.Max(r1.Right,  r2.Right);
     int y2 = Math.Max(r1.Bottom, r2.Bottom);
     return new Rectangle2I(x1, y1, x2 - x1, y2 - y1);
 }
예제 #32
0
 //-----------------------------------------------------------------------------
 // Static methods
 //-----------------------------------------------------------------------------
 // Return the intersection between two rectangles.
 // Returns the Empty rect if there is no intersection.
 public static Rectangle2I Intersect(Rectangle2I r1, Rectangle2I r2)
 {
     int x1 = Math.Max(r1.Left,   r2.Left);
     int y1 = Math.Max(r1.Top,    r2.Top);
     int x2 = Math.Min(r1.Right,  r2.Right);
     int y2 = Math.Min(r1.Bottom, r2.Bottom);
     if (x2 > x1 && y2 > y1)
         return new Rectangle2I(x1, y1, x2 - x1, y2 - y1);
     return Rectangle2I.Zero;
 }
예제 #33
0
        //-----------------------------------------------------------------------------
        // Overridden methods
        //-----------------------------------------------------------------------------
        protected override void Initialize()
        {
            base.Initialize();

            string typeName = Properties.GetString("warp_type", "Tunnel");

            warpType = WarpType.Tunnel;
            if (typeName == "tunnel")
                warpType = WarpType.Tunnel;
            else if (typeName == "entrance")
                warpType = WarpType.Entrance;
            else if (typeName == "stairs")
                warpType = WarpType.Stairs;

            collisionBox	= new Rectangle2I(2, 6, 12, 12);
            warpEnabled		= !IsTouchingPlayer();
        }
예제 #34
0
 public void SetSelectionGridArea(Rectangle2I area, Level level)
 {
     PlaceSelectionGrid();
     selectionGridArea  = area;
     selectionGridLevel = level;
     SetSelectionBox(selectionGridArea.Point * GameSettings.TILE_SIZE,
                     selectionGridArea.Size  * GameSettings.TILE_SIZE);
 }
예제 #35
0
        // Draw an event tile.
        private void DrawEventTile(Graphics2D g, EventTileDataInstance eventTile, Point2I position, Color drawColor)
        {
            SpriteAnimation spr = eventTile.CurrentSprite;
            int imageVariantID = eventTile.Properties.GetInteger("image_variant");
            if (imageVariantID < 0)
                imageVariantID = eventTile.Room.Zone.ImageVariantID;

            // Select different sprites for certain events.
            if (eventTile.Type == typeof(NPCEvent)) {
                eventTile.SubStripIndex = eventTile.Properties.GetInteger("direction", 0);
            }
            else if (eventTile.Type == typeof(WarpEvent)) {
                string warpTypeStr = eventTile.Properties.GetString("warp_type", "tunnel");
                WarpType warpType = (WarpType) Enum.Parse(typeof(WarpType), warpTypeStr, true);
                if (warpType == WarpType.Entrance)
                    spr = GameData.SPR_EVENT_TILE_WARP_ENTRANCE;
                else if (warpType == WarpType.Tunnel)
                    spr = GameData.SPR_EVENT_TILE_WARP_TUNNEL;
                else if (warpType == WarpType.Stairs)
                    spr = GameData.SPR_EVENT_TILE_WARP_STAIRS;
            }

            // Draw the sprite.
            if (!spr.IsNull) {
                g.DrawAnimation(spr, imageVariantID, editorControl.Ticks, position, drawColor);
            }
            else {
                Rectangle2I r = new Rectangle2I(position, eventTile.Size * GameSettings.TILE_SIZE);
                g.FillRectangle(r, Color.Blue);
            }
        }
예제 #36
0
 public void SetSelectionGrid(TileGrid tileGrid, Point2I location, Level level)
 {
     PlaceSelectionGrid();
     selectionGridArea	= new Rectangle2I(location, tileGrid.Size);
     selectionGridLevel	= level;
     selectionGrid		= tileGrid;
     SetSelectionBox(selectionGridArea.Point * GameSettings.TILE_SIZE,
                     selectionGridArea.Size  * GameSettings.TILE_SIZE);
 }
예제 #37
0
        //-----------------------------------------------------------------------------
        // Overridden methods
        //-----------------------------------------------------------------------------
        public override void OnInitialize()
        {
            base.OnInitialize();

            direction		= Properties.GetInteger("direction", Directions.Down);
            extendLength	= 0.0f;
            isBeingPulled	= false;

            SetLength(0.0f);

            CollisionStyle		= CollisionStyle.Circular;
            IsSolid				= true;
            ClingWhenStabbed	= false;
            SolidType			= TileSolidType.HalfSolid;
            Rectangle2I collisionBox = new Rectangle2I(4, 4, 8, 8);
            collisionBox.ExtendEdge(direction, 5);
            CollisionModel = new CollisionModel(collisionBox);

            if (direction == Directions.Right)
                Graphics.PlaySprite(GameData.SPR_TILE_PULL_HANDLE_RIGHT);
            else if (direction == Directions.Up)
                Graphics.PlaySprite(GameData.SPR_TILE_PULL_HANDLE_UP);
            else if (direction == Directions.Left)
                Graphics.PlaySprite(GameData.SPR_TILE_PULL_HANDLE_LEFT);
            else if (direction == Directions.Down)
                Graphics.PlaySprite(GameData.SPR_TILE_PULL_HANDLE_DOWN);
        }
예제 #38
0
 // Return an enumerable list of tiles contained within the given tile grid area.
 public IEnumerable<Tile> GetTilesInArea(Rectangle2I area, TileLayerOrder layerOrder = TileLayerOrder.LowestToHighest)
 {
     Rectangle2I clippedArea = Rectangle2I.Intersect(area,
         new Rectangle2I(Point2I.Zero, gridDimensions));
     foreach (int i in GetLayers(layerOrder)) {
         for (int y = clippedArea.Top; y < clippedArea.Bottom; y++) {
             for (int x = clippedArea.Left; x < clippedArea.Right; x++) {
                 Tile tile = tiles[x, y, i];
                 if (tile != null) {
                     Point2I loc = tile.TileGridArea.Point;
                     if (!clippedArea.Contains(loc))
                         loc = Point2I.Clamp(loc, clippedArea);
                     if (x == loc.X && y == loc.Y)
                         yield return tile;
                 }
             }
         }
     }
 }
예제 #39
0
        // Return the highest surface tile at the given position.
        public Tile GetSurfaceTileAtPosition(Vector2F position, bool includePlatforms = false)
        {
            // Because tiles may have moved this frame, we need to check a 3x3 area.
            Point2I location = GetTileLocation(position);
            Rectangle2I area = new Rectangle2I(location, Point2I.One);
            area.Inflate(1, 1);

            foreach (Tile tile in GetTilesInArea(area, TileLayerOrder.HighestToLowest)) {
                Rectangle2F tileBounds = tile.Bounds;
                tileBounds.Point -= tile.Velocity;
                if (tileBounds.Contains(position) && (tile.IsSurface || (includePlatforms && tile.IsPlatform)))
                    return tile;
            }

            return null;
        }
예제 #40
0
 /** <summary> Constructs a copy of the specified rectangle. </summary> */
 public Rectangle2I(Rectangle2I r)
 {
     this.Point = r.Point;
     this.Size  = r.Size;
 }
예제 #41
0
        //-----------------------------------------------------------------------------
        // Overridden methods
        //-----------------------------------------------------------------------------
        protected override void Initialize()
        {
            base.Initialize();

            string typeName = Properties.GetString("warp_type", "Tunnel");
            warpType		= (WarpType) Enum.Parse(typeof(WarpType), typeName, true);
            collisionBox	= new Rectangle2I(2, 6, 12, 12);
            warpEnabled		= !IsTouchingPlayer();

            // Find the closest room edge.
            edgeDirection = -1;
            Rectangle2I roomBounds = RoomControl.RoomBounds;
            Rectangle2I myBox = new Rectangle2I((int) position.X, (int) position.Y, 16, 16);
            int minDist = -1;
            for (int dir = 0; dir < 4; dir++) {
                int dist = Math.Abs(myBox.GetEdge(dir) - roomBounds.GetEdge(dir));
                if (dist < minDist || minDist < 0) {
                    edgeDirection = dir;
                    minDist = dist;
                }
            }

            // Make sure we know if the player respawns on top of this warp point.
            RoomControl.PlayerRespawn += delegate(Player player) {
                warpEnabled = !IsTouchingPlayer();
            };

            // For entrance warp points, intercept room transitions in order to warp.
            RoomControl.RoomTransitioning += delegate(int direction) {
                if (warpType == WarpType.Entrance && direction == edgeDirection && IsTouchingPlayer()) {
                    RoomControl.CancelRoomTransition();
                    Warp(direction);
                }
            };
        }