/// <summary>Clears placed blocks and starts timer for the next block.</summary>
 private void resetBlock()
 {
     newBlockTimer = 0;
     tetrisBlockCurrent = null;
 }
 /// <summary>Copies the block data to the field data uppon placement.</summary>
 /// <param name="block">The block to place.</param>
 public void placeBlock(TetrisBlock block)
 {
     for(int y = 0; y < 4; y++)
     {
         for(int x = 0; x < 4; x++)
         {
             if (block.checkGridStruct(y, x) &&
                 block.OffsetX + x >= 0 &&
                 block.OffsetX + x < width &&
                 block.OffsetY + y < height)
             {
                 // within the field
                 fieldStruc[y + block.OffsetY][x + block.OffsetX] = true;
                 if (isColor) { fieldCol[y + block.OffsetY][x + block.OffsetX] = block.blockColor; }
             }
         }
     }
 }
        /// <summary>Updates the game.</summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // base updates
            gameState = reserveGameState;
            input.Update(gameTime);

            switch (gameState)
            {
                case GameStates.Menu:

                    // menu buttons
                    foreach(Button button in menuButtons)
                    {
                        if (button.isClicked(input))
                        {
                            switch (button.Action)
                            {
                                case MenuActions.Mono:
                                    // start monochrome mode
                                    reserveGameState = GameStates.Playing;
                                    isColor = false;
                                    break;
                                case MenuActions.Color:
                                    // start color mode
                                    reserveGameState = GameStates.Playing;
                                    isColor = true;
                                    break;
                                case MenuActions.Info:
                                    // open info screen
                                    reserveGameState = GameStates.Info;
                                    break;
                                case MenuActions.Quit:
                                    // quir the game
                                    Exit();
                                    break;
                            }
                        }
                    }

                    if (reserveGameState == GameStates.Playing)
                    {
                        // set up for playing the selected mode

                        // create the field
                        field = new PlayingField(fieldWidth, fieldHeight, blockSprites, isColor);

                        // create the blocks
                        tetrisBlockCurrent = TetrisBlock.createBlock(blockSprites, field, isColor);
                        tetrisBlockNext = TetrisBlock.createBlock(blockSprites, field, isColor);
                        tetrisBlockCurrent.placeBlock();
                        tetrisBlockCurrent.setMoveTimer(moveTimerLim);

                        // score viewer
                        scoreViewerCurrent = isColor ? scoreViewerColor : scoreViewerMono;
                        numbersCurrent = isColor ? numbersColor : numbersMono;
                        scoreSplicer();
                        speedLvlSplicer();
                    }

                    break;

                case GameStates.Info:
                    // button for going back to the menu
                    if (backButton.isClicked(input)) { reserveGameState = GameStates.Menu; }
                    break;

                case GameStates.Playing:

                    // make new blocks
                    if (tetrisBlockCurrent == null)
                    {
                        if (newBlockTimer >= newBlockTimerLim)
                        {
                            tetrisBlockCurrent = tetrisBlockNext;
                            tetrisBlockNext = TetrisBlock.createBlock(blockSprites, field, isColor);
                            if (!tetrisBlockCurrent.placeBlock())
                            {
                                // could not place the block
                                // GAME OVER
                                reserveGameState = GameStates.GameOver;
                                break;
                            }
                            tetrisBlockCurrent.setMoveTimer(moveTimerLim);
                        }
                        else
                        { newBlockTimer += gameTime.ElapsedGameTime.Milliseconds; }
                    }

                    if (tetrisBlockCurrent != null)
                    {
                        // make the tetris block handle it's user inputs and movement
                        couldGoDown = tetrisBlockCurrent.handleMovement(gameTime, input);

                        if (!couldGoDown)
                        {
                            // reached bottom or hit existing block
                            blockHitSound.Play();
                            field.placeBlock(tetrisBlockCurrent);
                            scorePoints(field.checkClearedRows(tetrisBlockCurrent.OffsetY));
                            if (field.reachedTop())
                            {
                                // the top of the field could not be cleared
                                // GAME OVER
                                reserveGameState = GameStates.GameOver;
                                gameOverString1 = "You made it to speed level " + (Math.Min(finishedRows, (moveTimerLimBase - moveTimerLimMin) / 2)).ToString();
                                gameOverString2 = "and earned " + score.ToString() + " points!";
                            }
                            resetBlock();
                        }
                    }

                    break;

                case GameStates.GameOver:
                    // TODO: GAME OVER text and score view

                    // buttons
                    if (menuButton.isClicked(input))
                    {
                        // back to menu
                        reserveGameState = GameStates.Menu;

                        // reset for next playthrough
                        score = 0;
                        finishedRows = 0;
                        moveTimerLim = moveTimerLimBase;
                    }
                    if (menuButtons[3].isClicked(input)) { Exit(); } // quit game

                    break;
            }

            // you can always exit the game
            if (input.KeyPressed(Keys.Escape)) { Exit(); }

            base.Update(gameTime);
        }
 /// <summary>Checks if the block can move in a given direction.</summary>
 /// <param name="blockToMove">The block that should be checked.</param>
 /// <param name="direction">The direction of the displacement. 0 = down, 1 = left, 2 = right, default = stay</param>
 public bool canBlockMove(TetrisBlock blockToMove, Movement direction = Movement.Stay)
 {
     return canBlockMove(blockToMove.FieldStruct, blockToMove.OffsetX, blockToMove.OffsetY, direction);
 }