/// <summary>
 /// Register the pea controller
 /// </summary>
 /// <param name="controller"></param>
 public void Register(PeaController controller)
 {
     _controllers.Add(controller);
 }
        /// <summary>
        /// Initializes screen
        /// </summary>
        public override void Initialize()
        {
            // Create the scene and add it
            _camera = new Camera2D(this.Game);
            _camera.Initialize();
            _fxcamera = new Camera2D(this.Game);
            _fxcamera.Initialize();

            _scene = new Scene(this.Game, _camera);
            _scene.TransitionPosition = 0;
            _scene.TransitionOnTime = TimeSpan.FromSeconds(1);
            _scene.TransitionOffTime = TimeSpan.FromSeconds(1);
            _scene.OffTransition();
            _fx = new World(Vector2.UnitY * 10);
            _fxStaticBody = new Body(_fx) { Restitution = 0, Mass = 0, BodyType = BodyType.Static, Friction = 0.5f/*, Position = 
                ConvertUnits.ToSimUnits(Vector2.UnitX * (_width - DataGrid.WidthInPixels) / 2f + Vector2.UnitY * 150)*/ };
           
            // Create controllers
            _timeController = new TimeController(this.Game);
            _pointsController = new PointsController(this.Game);
            _dataGrid = DataGrid.CreateDataGrid(this.Game, _fxStaticBody, _width / 70 - 1, _height / 49 - 4);
            _peaController = new PeaController(this.Game);
            _inputController = new InputController(this.Game);
            _achievementController = new AchievementController(this.Game);

            // Initialize controllers
            _timeController.Initialize();
            _pointsController.Initialize();
            _dataGrid.Initialize();
            _peaController.Initialize();
            _inputController.Initialize();
            _achievementController.Initialize();

            // Register controllers
            _dataGrid.Register(_peaController);

#if DEBUG && _
            
            DataBlock testBlock = _dataGrid.Add(new Point(0, 0), BlockType.Normal);
            DataBlock testBlock2 = _dataGrid.Add(new Point(0, 1), BlockType.Gel);
            DataBlock testBlock3 = _dataGrid.Add(new Point(1, 1), BlockType.Normal);
            DataBlock testBlock4 = _dataGrid.Add(new Point(2, 1), BlockType.RightRamp);
            DataBlock testBlock5 = _dataGrid.Add(new Point(3, 2), BlockType.Normal);
            DataBlock testBlock6 = _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 1), BlockType.Normal);
#endif
            // Create the peas
            DataPea pea1 = new DataPea(this.Game, _fx, _peaController);
            _pointsController.Register(pea1);
            _achievementController.Register(pea1);

            pea1.Initialize();

            this.Game.Components.Add(pea1);

            DataPea pea2 = new DataPea(this.Game, _fx, _peaController);
            DataPea pea3 = new DataPea(this.Game, _fx, _peaController);
            DataPea pea4 = new DataPea(this.Game, _fx, _peaController);
            DataPea pea5 = new DataPea(this.Game, _fx, _peaController);

            // This needs to be done BEFORE sprites of pea
            _pointsController.Register(pea2);
            _pointsController.Register(pea3);
            _pointsController.Register(pea4);
            _pointsController.Register(pea5);

            _achievementController.Register(pea2);
            _achievementController.Register(pea3);
            _achievementController.Register(pea4);
            _achievementController.Register(pea5);

            pea2.Initialize();
            pea3.Initialize();
            pea4.Initialize();
            pea5.Initialize();

            this.Game.Components.Add(pea2);
            this.Game.Components.Add(pea3);
            this.Game.Components.Add(pea4);
            this.Game.Components.Add(pea5);

            // Create layers
            _sceneryLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.9f };
            _levelLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.6f };
            _peasLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.3f };
            _hudLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.1f };

            // Create sprites
            _spriteGrid = new SpritesetGrid(_levelLayer) { Position = Vector2.UnitX * (_width - DataGrid.WidthInPixels) / 2f + Vector2.UnitY * 150 };
            SpritePea.BaseOffset = _spriteGrid.Position;
            
            _peasLayer.Add(new SpritePea(_peasLayer, pea1, _pointsController));

#if !DEBUG || !TEST
            _peasLayer.Add(new SpritePea(_peasLayer, pea2, _pointsController));
            _peasLayer.Add(new SpritePea(_peasLayer, pea3, _pointsController));
            _peasLayer.Add(new SpritePea(_peasLayer, pea4, _pointsController));
            _peasLayer.Add(new SpritePea(_peasLayer, pea5, _pointsController));
#endif

#if DEBUG && TEST
            for (int i = 0; i < DataGrid.Width; i++)
            {
                if (new int[] { 3, 4, 5, 10, 12, 14 }.Contains(i) == false)
                {
                    DataBlock b = _dataGrid.Add(new Point(i, DataGrid.Height - 1), BlockType.Normal);
                    //_spriteGrid.Add(new SpriteBlock(_levelLayer, b));

                    if (new int[] { 0 , 1, 2, 5, 8, 15 }.Contains(i))
                    {
                        b = _dataGrid.Add(new Point(i, DataGrid.Height - 2), BlockType.Normal);
                        //_spriteGrid.Add(new SpriteBlock(_levelLayer, b));
                    }

                    if (new int[] { 0, 15 }.Contains(i))
                    {
                        b = _dataGrid.Add(new Point(i, DataGrid.Height - 3), BlockType.Gel);
                        //_spriteGrid.Add(new SpriteBlock(_levelLayer, b));
                    }

                    if (new int[] { 0, 15 }.Contains(i))
                    {
                        b = _dataGrid.Add(new Point(i, DataGrid.Height - 4), BlockType.Gel);
                        //_spriteGrid.Add(new SpriteBlock(_levelLayer, b));
                    }
                }
            }


            DataBlock jump = _dataGrid.Add(new Point(3, 7), BlockType.Normal);
            //_spriteGrid.Add(new SpriteBlock(_levelLayer, jump));

            DataBlock ramp = _dataGrid.Add(new Point(1, 8), BlockType.RightRamp);
            //_spriteGrid.Add(new SpriteBlock(_levelLayer, ramp));

            //DataBlock gel = _dataGrid.Add(new Point(5, 10), BlockType.LeftRamp);
            //_spriteGrid.Add(new SpriteBlock(_levelLayer, gel));
#else
            // Some boundary blocks
            _dataGrid.Add(new Point(0, DataGrid.Height - 1), BlockType.Gel);
            _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 1), BlockType.Gel);
            _dataGrid.Add(new Point(0, DataGrid.Height - 2), BlockType.Gel);
            _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 2), BlockType.Gel);
#endif

            SpriteToolbox toolbox = new SpriteToolbox(_hudLayer)
            {
                Position = new Vector2(_width - (1280 - 1220),
                    (Single)Math.Ceiling(150 * (_height / 720f)))
            };
            SpritesetHud hud = new SpritesetHud(_hudLayer, _pointsController, _inputController.State, _width, _height);


            // Register sprites at inputControllers
            _inputController.Register(_spriteGrid);
            _inputController.Register(toolbox);
            _inputController.Register(_camera, _width, _height);

            foreach (var blockRow in _dataGrid.Grid)
                foreach (var block in blockRow)
                {
                    block.Place(block.BlockType, BlockState.Placed); // Direct placing;
                    _spriteGrid.Add(new SpriteBlock(_levelLayer, block));
                }

            // Add the layers
            _scene.Add(_sceneryLayer);
            _scene.Add(_levelLayer);
            _scene.Add(_peasLayer);
            _scene.Add(_hudLayer);
            
            // Add the content
            Sprite background = new Sprite(_sceneryLayer, "Graphics/Background");
            background.Position = new Vector2(_width / 2f, _height / 2f);
            background.Origin = new Vector2(1280f / 2f, 720f / 2f);
            background.Scale = Math.Max(_width / 1280f, _height / 720f);

            Sprite splate = new Sprite(_sceneryLayer, "Graphics/Plate");
            splate.Position = new Vector2(_width / 2f, _height / 2f);
            splate.Origin = new Vector2(1280f / 2f, 720f / 2f);
            splate.Scale = Math.Max(_width / 1280f, _height / 720f);

            _sceneryLayer.Add(background);
            _sceneryLayer.Add(splate);
            _levelLayer.Add(_spriteGrid);
            _hudLayer.Add(toolbox);
            _hudLayer.Add(hud);

            // Bottom plate physics
            var plate = FixtureFactory.AttachRectangle(ConvertUnits.ToSimUnits(_width), ConvertUnits.ToSimUnits(20), 1f,
                ConvertUnits.ToSimUnits(Vector2.UnitY * (49 * (DataGrid.Height - 3) + _spriteGrid.Position.Y + 5) + (_width / 2 - _spriteGrid.Position.X) * Vector2.UnitX), _fxStaticBody);
            plate.Restitution = 0;
            plate.Friction = 0.5f;

            // Initializes scene and so on
            base.Initialize();

            _scene.Initialize();
            _camera.Position = new Vector2(_width / 2f, _height / 2f);
            _fxcamera.Position = new Vector2(_width / 2f, _height / 2f)-  _spriteGrid.Position; // + ConvertUnits.ToSimUnits(_spriteGrid.Position);
            _camera.Jump2Target();
            _fxcamera.Jump2Target();
            
            #if DEBUG && !SILVERLIGHT
                view = new DebugViewXNA(_fx);
                view.AppendFlags(FarseerPhysics.DebugViewFlags.CenterOfMass | FarseerPhysics.DebugViewFlags.DebugPanel | FarseerPhysics.DebugViewFlags.PerformanceGraph | FarseerPhysics.DebugViewFlags.PolygonPoints);
            #endif
            // Add components
            this.Game.Components.Add(_peaController);
            this.Game.Components.Add(_timeController);
            this.Game.Components.Add(_inputController);
            this.Game.Components.Add(_pointsController);
            this.Game.Components.Add(_achievementController);
            this.Game.Components.Add(_camera);
            this.Game.Components.Add(_fxcamera);
            this.Game.Components.Add(_dataGrid);
            this.Game.Components.Add(_scene);

            // Add popups
            _achievementController.OnCompletedAchievement += new AchievementCompletedHandler(_achievementController_OnCompletedAchievement);

            // Add overlay
            _overlay = new PauseOverlay(_camera, _width, _height);
            _overlay.Exiting += new EventHandler(_overlay_Exiting);
          
            // Events
            this.Exited += new EventHandler(PeaScreen_Exited);
            this.OnEnabledChanged += new BooleanDelegate(PeaScreen_OnEnabledChanged);
            this.OnVisibleChanged += new BooleanDelegate(PeaScreen_OnVisibleChanged);

            // Add end
            _pointsController.OnReachedGoal += new Action(_pointsController_OnReachedGoal);

            this.IsEnabled = false;
            this.IsVisible = false;            
        }
        /// <summary>
        /// Creates a new pea
        /// </summary>
        /// <param name="fx">Physics world</param>
        /// <param name="game">Game to bind to</param>
        /// <param name="controller">Controller</param>
        public DataPea(Game game, World fx, PeaController controller)
            : base(game)
        {
            // Put on floor
            Revive();

            // Create physics
            _fxPea = BodyFactory.CreateCircle(fx, ConvertUnits.ToSimUnits(16), 1f,
                ConvertUnits.ToSimUnits(this.Position) + Vector2.UnitX * ConvertUnits.ToSimUnits(18) + Vector2.UnitY * ConvertUnits.ToSimUnits(18), this);
            
            _fxPea.BodyType = BodyType.Dynamic;
            _fxPea.Mass = 1f;
            _fxPea.Restitution = 0.7f;
            _fxPea.Friction = 0.5f;
            _fxPea.LinearDamping = 0.2f;
            _fxPea.OnCollision += new OnCollisionEventHandler(_fxPea_OnCollision);
            _fxPea.OnSeparation += new OnSeparationEventHandler(_fxPea_OnSeparation);
            //_fxPea.CollisionCategories = Category.Cat2;
            //_fxPea.CollidesWith = Category.All;
            Jump(null);
           
            _collisions = new HashSet<Fixture>();
            _controller = controller;
            _controller.Register(this);

            ChangeMood(Mood.Happy);
        }