Exemple #1
0
        protected bool CheckForOverlap(Tetromino sim)
        {
            // This try catch block is here as a dirty hack!
            // This dirty hack returns true (overlap) if the simulated piece is out of bounds.
            // In my defense, this function was previously called "CheckForBounds"
            try
            {
                // Create a new simulated field with a simulated piece to check for overlaps
                char[,] simulatedField = UpdateSimulation(sim);

                // For each point in the simulated field...
                for (int i = 0; i < h; i++)
                {
                    for (int j = 0; j < w; j++)
                    {
                        // ...check only for the active blocks(non - frozen, non - empty)
                        if (simulatedField[j, i] != 'e' && simulatedField[j, i] != 'f')
                        {
                            // If any active block in the simulated field overlaps with a frozen block in the real field, then we have found a overlap.
                            if (field[j, i] == 'f')
                            {
                                return(true);
                            }
                        }
                    }
                }
                // If we find no overlaps between the simulated and the real field, return false, no overlaps.
                return(false);
            }
            catch (Exception)
            {
                return(true);
            }
        }
Exemple #2
0
        // Collision and Bounds Checking
        protected char[,] UpdateSimulation(Tetromino sim)
        {
            // Takes a tetromino as input and generates a simulated matrix that overlaps the tetromino on the game matrix.
            char[,] simulatedField = new char[w, h];

            // Copy the game matrix as the simulated one.
            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    simulatedField[j, i] = field[j, i];
                }
            }

            // Put the tetromino in the simulated matrix.
            for (int i = 0; i < sim.Orientations[sim.Phase].Matrix.GetLength(0); i++)
            {
                for (int j = 0; j < sim.Orientations[sim.Phase].Matrix.GetLength(1); j++)
                {
                    if (sim.Orientations[sim.Phase].Matrix[i, j] != 'e')
                    {
                        simulatedField[sim.X + j, sim.Y + i] = sim.Orientations[sim.Phase].Matrix[i, j];
                    }
                }
            }

            return(simulatedField);
        }
Exemple #3
0
        protected char[,] GenerateTetrominoInfoArray(Tetromino renderTetromino)
        {
            // This function generates 4x4 arrays of tetrominos.
            // It is used to display the next and saved tetrominos.
            // It is 4x4 to be universal and accomidate any tetromino.

            // Initialize the matrix with 'h'idden characters.
            char[,] temp = new char[4, 4] {
                { 'h', 'h', 'h', 'h' },
                { 'h', 'h', 'h', 'h' },
                { 'h', 'h', 'h', 'h' },
                { 'h', 'h', 'h', 'h' }
            };

            // These loops copy over the matrix of the saved or next tetromnio over to the 4x4 matrix.
            // The if statement ensures that we only copy the parts we need, basically, ignore the empty spaces.
            for (int i = 0; i < renderTetromino.Orientations[renderTetromino.Phase].Matrix.GetLength(0); i++)
            {
                for (int j = 0; j < renderTetromino.Orientations[renderTetromino.Phase].Matrix.GetLength(1); j++)
                {
                    if (renderTetromino.Orientations[renderTetromino.Phase].Matrix[i, j] != 'e')
                    {
                        temp[i, j] = renderTetromino.Orientations[renderTetromino.Phase].Matrix[i, j];
                    }
                }
            }

            // We return the matrix to be displayed.
            return(temp);
        }
Exemple #4
0
 public Quadris(ConsoleHardwareConfig config)
     : base(config)
 {
     World = new Composition(new byte[FieldHeight * FieldWidth / 8], FieldWidth, FieldHeight);
     ResetPlayfield();
     Tetromino = new Tetromino(this);
     RenderFrame();
     TimeToFall       = false;
     _timeToFallTimer = new Timer(OnTimerTick, null, TimeSpan.Zero, TimeSpan.FromTicks(TetrominoFallInterval));
     DisplayDelay     = 0;
 }
Exemple #5
0
        public static Tetromino Copy(Tetromino source)
        {
            Tetromino copy = new Tetromino();

            copy.phase = source.phase;
            copy.x     = source.x;
            copy.y     = source.y;

            foreach (var item in source.orientations)
            {
                copy.orientations.Add(item);
            }
            return(copy);
        }
Exemple #6
0
        public void Land(Tetromino piece)
        {
            int t = 0;

            if (piece is I)
            {
                t = 1;
            }
            if (piece is J)
            {
                t = 2;
            }
            if (piece is L)
            {
                t = 3;
            }
            if (piece is O)
            {
                t = 4;
            }
            if (piece is S)
            {
                t = 5;
            }
            if (piece is T)
            {
                t = 6;
            }
            if (piece is Z)
            {
                t = 7;
            }

            for (int py = 0; py < Constants.PieceTiles; ++py)
            {
                for (int px = 0; px < Constants.PieceTiles; ++px)
                {
                    if (piece.Tiles[py, px] == 0)
                    {
                        continue;
                    }

                    int wellX = ((int)piece.X - Constants.PieceTiles / 2) + px;
                    int wellY = ((int)piece.Y - Constants.PieceTiles / 2) + py;

                    wellTiles[wellY * Constants.WellWidth + wellX] = t;
                }
            }
        }
Exemple #7
0
        private void SpawnPiece(bool first = false)
        {
            // Reset keys
            newpiece = true;
            keyDownTime[Keys.Left]  = 0;
            keyDownTime[Keys.Right] = 0;
            keyDownTime[Keys.Down]  = 0;

            // Set current piece
            piece   = (first) ? GenerateRandomPiece() : preview;
            piece.X = Constants.WellWidth / 2;
            piece.Y = 0;

            // Calculate vertical clearance space
            for (int y = 0; y <= Constants.PieceTiles / 2; ++y)
            {
                // if sum of row > 0
                int sum = 0;
                for (int x = 0; x < Constants.PieceTiles; ++x)
                {
                    sum += piece.Tiles[y, x];
                    if (sum > 0)
                    {
                        break;
                    }
                }

                if (sum > 0)
                {
                    piece.Y += Math.Abs((Constants.PieceTiles / 2) - y);
                    break;
                }
            }

            // Fail state occurs when there is no space to spawn next piece
            if (well.Collision(piece, 0, 0))
            {
                gameState = GameState.GameOver;
                SaveHighScores();
            }

            // Generate next piece
            preview   = GenerateRandomPiece();
            preview.X = Constants.WellWidth + 5;
            preview.Y = 5;
        }
Exemple #8
0
 protected void SaveTetromino()
 {
     // Saves the currentTetromino and spawns a new one.
     // If there is one already saved, swaps the saved one and the current one.
     if (savedTetromino == null)
     {
         savedTetromino = Tetromino.Copy(currentTetromino);
         SpawnNewTetromino();
     }
     else
     {
         Tetromino temp = Tetromino.Copy(currentTetromino);
         currentTetromino   = Tetromino.Copy(savedTetromino);
         savedTetromino     = Tetromino.Copy(temp);
         currentTetromino.X = 4;
         currentTetromino.Y = 0;
         //currentTetromino.Phase = 0;
     }
 }
Exemple #9
0
        public bool Collision(Tetromino piece, int offsetX = 0, int offsetY = 0)
        {
            // Loop over the 5x5 tiles of a piece on the board (i1,j1 = position in well; i2,j2 = position in piece tile grid)
            for (int py = 0; py < Constants.PieceTiles; ++py)
            {
                for (int px = 0; px < Constants.PieceTiles; ++px)
                {
                    if (piece.Tiles[py, px] == 0)
                    {
                        continue;
                    }

                    int wellX = ((int)piece.X + offsetX - Constants.PieceTiles / 2) + px;
                    int wellY = ((int)piece.Y + offsetY - Constants.PieceTiles / 2) + py;

                    // Check if the piece is inside horizontal bounds of the well
                    if (wellX < 0 || wellX > Constants.WellWidth - 1)
                    {
                        return(true);
                    }

                    // Check if the piece is inside vertical bounds of the well
                    if (wellY > Constants.WellHeight - 1)
                    {
                        return(true);
                    }

                    // Check if piece has collided with a previously stored tile
                    if (wellY >= 0 && wellTiles[wellY * Constants.WellWidth + wellX] != 0)
                    {
                        return(true);
                    }
                }
            }

            // No collision
            return(false);
        }
Exemple #10
0
        protected void Rotate(int direction)
        {
            int oldX           = currentTetromino.X;     // Save old X position, in case the simulated Tetromino is overlaping a frozen piece.
            int newX           = currentTetromino.X;     // Shifted X position, in case the new orientation is out of bounds.
            int oldOrientation = currentTetromino.Phase; // Save old orientation, in case the new one is overlaping a frozen piece.
            int newOrientation = currentTetromino.Phase; // New orientation

            // Simulated Tetromino, to see if after rotation, the current tetromino is overlaping or out of bounds.
            Tetromino sim = Tetromino.Copy(currentTetromino);

            //If direction is 1, it's clockwise, if it's -1 it's counter clock wise, so we do bounds checking.
            newOrientation = newOrientation + direction;
            if (newOrientation > currentTetromino.PhaseCount - 1) // -1 because if there are 4 orientations, the last one will have position 3 in the List.
            {
                newOrientation = 0;
            }
            else if (newOrientation < 0)
            {
                newOrientation = currentTetromino.PhaseCount - 1;
            }

            //If the oriented piece is out of bounds, push it back.
            if (newX > w - 1 - currentTetromino.Orientations[newOrientation].Padding)
            {
                newX = w - 1 - currentTetromino.Orientations[newOrientation].Padding;
            }

            //Assign our simulated Tetromino it's new position and orientation.
            sim.X     = newX;
            sim.Phase = newOrientation;

            //Check if the simulated piece overlaps a frozen piece, if it's not overlaping, make the current piece, same as the simulated one.
            if (CheckForOverlap(sim) == false)
            {
                currentTetromino.X     = newX;
                currentTetromino.Phase = newOrientation;
            }
        }
Exemple #11
0
        protected void RandomNextTetromino()
        {
            // "Randomly" generates nextTetromino.
            Random rng = new Random();

            switch (rng.Next(6))
            {
            case 0: { nextTetromino = Tetromino.Copy(sc); break; }

            case 1: { nextTetromino = Tetromino.Copy(si); break; }

            case 2: { nextTetromino = Tetromino.Copy(sz); break; }

            case 3: { nextTetromino = Tetromino.Copy(sn); break; }

            case 4: { nextTetromino = Tetromino.Copy(st); break; }

            case 5: { nextTetromino = Tetromino.Copy(sl); break; }

            case 6: { nextTetromino = Tetromino.Copy(sj); break; }

            default: { break; }
            }
        }
Exemple #12
0
        private void UpdateInput(KeyboardState keyState, GameTime gameTime)
        {
            if (keyState.IsKeyDown(Keys.Escape))
            {
                gameState = GameState.Menu;
                Reset();
                return;
            }

            if (keyState.IsKeyDown(Keys.Left))
            {
                if (!prevKeyState.IsKeyDown(Keys.Left))
                {
                    newpiece = false;
                    keyDownTime[Keys.Left]  = 0;
                    keyDownTime[Keys.Right] = 0;

                    if (!well.Collision(piece, -1, 0))
                    {
                        piece.X--;
                    }
                }
                else if (!newpiece)
                {
                    // key was down on last tick as well
                    if (++keyDownTime[Keys.Left] % Math.Max(4, 20 - keyDownTime[Keys.Left] / 2) == 0)
                    {
                        if (!well.Collision(piece, -1, 0))
                        {
                            piece.X--;
                        }
                    }
                }
            }
            else if (keyState.IsKeyDown(Keys.Right))
            {
                if (!prevKeyState.IsKeyDown(Keys.Right))
                {
                    newpiece = false;
                    keyDownTime[Keys.Left]  = 0;
                    keyDownTime[Keys.Right] = 0;

                    if (!well.Collision(piece, 1, 0))
                    {
                        piece.X++;
                    }
                }
                else if (!newpiece)
                {
                    if (++keyDownTime[Keys.Right] % Math.Max(4, 20 - keyDownTime[Keys.Right] / 2) == 0)
                    {
                        if (!well.Collision(piece, 1, 0))
                        {
                            piece.X++;
                        }
                    }
                }
            }

            // Soft drop
            else if (keyState.IsKeyDown(Keys.Down))
            {
                if (!prevKeyState.IsKeyDown(Keys.Down))
                {
                    newpiece = false;
                    keyDownTime[Keys.Down] = 0;

                    if (!well.Collision(piece, 0, 1))
                    {
                        piece.Y++;
                    }
                    else
                    {
                        gravityTime = gravityTimer;
                    }
                }
                else if (!newpiece)
                {
                    if (++keyDownTime[Keys.Down] % Math.Max(4, 20 - keyDownTime[Keys.Down] / 2) == 0)
                    {
                        if (!well.Collision(piece, 0, 1))
                        {
                            piece.Y++;
                        }
                        else
                        {
                            gravityTime = gravityTimer;
                        }
                    }
                }
            }

            if (keyState.IsKeyDown(Keys.Z) && !prevKeyState.IsKeyDown(Keys.Z))
            {
                Tetromino rotated = piece.Copy();
                rotated.Tiles = piece.Rotate();

                // attempt rotation as-is
                if (!well.Collision(rotated))
                {
                    piece.Tiles = rotated.Tiles;
                }
                // attempt wall-kick-right before rotation
                else if (!well.Collision(rotated, 1, 0))
                {
                    piece.X++;
                    piece.Tiles = rotated.Tiles;
                }
                // attempt wall-kick-left before rotation
                else if (!well.Collision(rotated, -1, 0))
                {
                    piece.X--;
                    piece.Tiles = rotated.Tiles;
                }
            }

            // Hard drop
            if (keyState.IsKeyDown(Keys.X) && !prevKeyState.IsKeyDown(Keys.X))
            {
                while (!well.Collision(piece))
                {
                    piece.Y++;
                }

                piece.Y--;
                gravityTime = gravityTimer;
            }
        }
Exemple #13
0
        public override void Loop()
        {
            var leftStick = Hardware.JoystickLeft.XDirection;

            if (leftStick != _previousLeftDirection)
            {
                switch (leftStick)
                {
                case AnalogJoystick.Direction.Negative:
                    Tetromino.MoveLeft();
                    break;

                case AnalogJoystick.Direction.Positive:
                    Tetromino.MoveRight();
                    break;
                }
                _previousLeftDirection = leftStick;
            }
            var rightStick = Hardware.JoystickRight.XDirection;

            if (rightStick != _previousRightDirection)
            {
                switch (rightStick)
                {
                case AnalogJoystick.Direction.Negative:
                    Tetromino.RotateLeft();
                    break;

                case AnalogJoystick.Direction.Positive:
                    Tetromino.RotateRight();
                    break;
                }
                _previousRightDirection = rightStick;
            }
            var stickDown = Hardware.JoystickLeft.YDirection == AnalogJoystick.Direction.Positive;

            if (TimeToFall || (stickDown && !_rightJoystickPreviouslyDown))
            {
                TimeToFall = false;
                if (!Tetromino.MoveDown())
                {
                    // The tetromino hit the bottom
                    // We need to copy the tetromino onto the playfield
                    CopyTetrominoOntoPlayfield();
                    // Did it have enough space to render entirely?
                    if (Tetromino.Y < 0)
                    {
                        // Nope -> Game over
                        RenderFrame();
                        MakeExplosionSound();
                        Stop();
                    }
                    else
                    {
                        MakeHitSound();
                        // Check for and remove full lines
                        RemoveFullLines();
                        // Spawn a new tetromino
                        Tetromino = new Tetromino(this);
                        // Accelerate the game
                        _currentTimeToFallTicks = (long)(_currentTimeToFallTicks * 100 / AccelarationRate);
                        _timeToFallTimer.Change(TimeSpan.Zero, TimeSpan.FromTicks(_currentTimeToFallTicks));
                    }
                }
            }
            _rightJoystickPreviouslyDown = stickDown;
            RenderFrame();
        }
Exemple #14
0
 protected void SpawnNewTetromino()
 {
     // Makes currentTetromino to be the Next one and generates a new nextTetromino.
     currentTetromino = Tetromino.Copy(nextTetromino);
     RandomNextTetromino();
 }