public static void initialize(EngineStateGameplay esg, PlayerController pc, Zone startZone)
        {
            GameplayState = esg;
            playerController = pc;
            ActiveZone = startZone;

            ActiveZone.add(pc);
        }
        /// <summary>
        /// Factory method to create CharacterControllers
        /// </summary>
        /// <param name="ci">Information about character apperance and stats</param>
        /// <param name="startpos">Where in the Area the character should be placed</param>
        /// <param name="playerControlled">True if the character should be a PC, false if NPC</param>
        /// <returns>Constructed CharacterController</returns>
        public static CharacterController construct(CharacterInfo ci, Vector2 startpos, bool playerControlled)
        {
            CharacterController cc;
            ColliderType type;
            if (playerControlled)
            {
                cc = new PlayerController(ci, startpos);
                type = ColliderType.Samus;
            }
            else
            {
                throw new Exception("CharacterController:construct unimplemented code reached");
            }

            return cc;
        }
        /// <summary>
        /// Performs door-based operations to move Samus into the adjacent zone.
        /// </summary>
        /// <param name="samus"></param>
        public void handleZoneTransition(PlayerController samus)
        {
            Point globalCoord = m_owningZone.getGlobalScreenFromLocalScreen(m_zoneScreenCoord);

            // Find target door (door in target zone which aligns with this door)
            Zone targetZone = WorldManager.GetZone(DirectionUtils.Move(globalCoord, Side));
            Point targetScreenInZoneCoord =
                targetZone.getLocalScreenFromGlobalScreen(globalCoord);
            Rectangle targetScreenArea =
                targetZone.getScreenRectangle(targetScreenInZoneCoord);
            List<Collider> colliders = targetZone.CollisionDetector.query(new DoubleRect(ref targetScreenArea));
            Collider targetDoorCollider =
                colliders.Find(i => {return (i.m_owner is DoorController && ((DoorController)i.m_owner).Side == this.Side.Opposite); });
            DoorController targetDoor = (DoorController)targetDoorCollider.m_owner;

            // Trigger closing animation on target door
            targetDoor.close();

            // Calculate Samus' new position in target zone
            DoubleRect samusBounds = samus.getCollider().Bounds;
            Vector2 dropPos = new Vector2();
            switch (Side.Opposite.EnumValue)
            {
                case DirectionEnum.Left:
                    dropPos.X = (float)(targetDoorCollider.Bounds.X + targetDoorCollider.Bounds.Width + 1 + samusBounds.Width / 2);
                    dropPos.Y = (float)(targetDoorCollider.Bounds.Y + targetDoorCollider.Bounds.Height - 1);
                    break;
                case DirectionEnum.Right:
                    dropPos.X = (float)(targetDoorCollider.Bounds.X - 1 - samusBounds.Width / 2);
                    dropPos.Y = (float)(targetDoorCollider.Bounds.Y + targetDoorCollider.Bounds.Height - 1);
                    break;
                case DirectionEnum.Up:
                    dropPos.X = (float)(targetDoorCollider.Bounds.X + targetDoorCollider.Bounds.Width / 2);
                    dropPos.Y = (float)(targetDoorCollider.Bounds.Y + targetDoorCollider.Bounds.Height + 1 + samusBounds.Height);
                    break;
                case DirectionEnum.Down:
                    dropPos.X = (float)(targetDoorCollider.Bounds.X + targetDoorCollider.Bounds.Width / 2);
                    dropPos.Y = (float)(targetDoorCollider.Bounds.Y - 1 - samusBounds.Height);
                    break;
            }

            // And create a new zone transition state with this information
            EngineManager.pushState(new EngineStateZoneTransition(
                EngineManager.Engine,
                this,
                targetDoor,
                targetZone,
                dropPos));

            setCollisionModeClosed();
        }