private void MoveDownProcess() { // TODO: Check inside this method that if not all CurrentPiece.Blocks fit on the GameBoard, don't move it down, but it's game over bool canMoveDown = _gameBoard.TryMoveCurrentPieceDown(); if (canMoveDown) { if (_isSoftDropping) { // Award points for soft dropping CurrentPiece _statistics.IncrementScoreForSoftDroppingOneLine(); } } else { // Game Over if either: // - not all CurrentPiece blocks fit on game board when trying to lock them (some of them are outside in top) // - NextPiece would collide with LockedBlocks if added bool allCurrentPieceBlocksFitOnGameBoard = _gameBoard.CurrentPiece.Blocks.All(block => _gameBoard.CurrentPiece.CoordsY + block.OffsetY >= 0); bool nextPieceCollidesWithLockedBlocks = _gameBoard.NextPieceCollidesWithLockedBlocks(); // TODO: The first situation could actually be legal (therefore, extend LockedBlocks, but don't render the first few rows in the top) if (!allCurrentPieceBlocksFitOnGameBoard || nextPieceCollidesWithLockedBlocks) { // Game Over: Stop all timers, and raise GameOver event (in order to eventually add high score) PauseGame(); _gameBoard.OnGameOver(_statistics.Score); } else { // Add CurrentPiece to LockedBlocks and remove complete rows int numberOfCompleteRows = _gameBoard.AddCurrentPieceToLockedBlocksAndRemoveCompleteRows(); // Make CurrentPiece refer to NextPiece. Then build a new NextPiece _gameBoard.UpdateCurrentPieceAndNextPiece(); // Update Level, Score, and Lines // If reaching new level, make _timerMovePieceDown tick faster (unless we are soft dropping, which uses same timer) int levelBefore = _statistics.Level; _statistics.UpdateOnCompletingRows(numberOfCompleteRows); int levelAfter = _statistics.Level; if (levelAfter > levelBefore && !_isSoftDropping) { _timerDown.Interval = DownGravityIntervalBasedOnLevel(); } _gameBoard.OnChanged(); } } }