Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Bricks for Pocket PC

0.00/5 (No votes)
24 Apr 2008 2  
A .NET Compact Framework version of the Bricks game.

Bricks

Introduction

I present two simple versions of the well-known brick game for Pocket PC. In this article, I'll present some techniques used to develop the game, also providing the source code. I hope the reader enjoys it, because for me it was a real treat.

The first version is the classic one, with the colored blocks falling from the top. With the second version, the pieces are composed of balloons instead of bricks, and the user has to correctly place them in lines on the top of the screen as the balloons go up.

I should say that I was motivated mainly by the fabulous work of Jonas Follesø in his article Pocket 1945 - A C# .NET CF Shooter. That article was uploaded to The Code Project in 2004, and is still impressive (and will continue to be impressive for many years). So, after reading the "Pocket 1945" article, I decided to write a game myself, and I ended up borrowing some of the concepts Jonas used in his game.

Background

The first brick game was programmed in 1985 by Alexey Pajitnov while he was working for the Dorodnicyn Computing Centre of the Academy of Science of the USSR in Moscow (thanks, Wikipedia). The game was virtually ported to every known platform, and was even played with human beings instead of the traditional colored bricks (see video).

The Game

Basically, Bricks! is a never-ending puzzle of 4-segment pieces. There are 7 types of pieces (that I call "I", "J", "L", "O", "S", "T", and "Z" in the game), and only one piece falls at a time from the top of the game board. The type of the tetromino is produced randomly. Every time the player fills a row in the board, that row is removed and the bricks above collapse, making room for more pieces to go.

Every time a row is completed, the player scores 10 points, multiplied by the number of the game level. A new level is reached every time the player completes 10 lines.

Application Design

The solution comprises of two projects: Bricks4Pocket and Bricks4Pocket.Core. The first basically contains the UI components, while the second contains the hard-work functionalities. I believe that just a few classes from the project are worth mentioning here.

I decided to use a simplified MVP (Model-View-Presenter) pattern in the game. In doing so, I could enforce the separation of concerns by assuring that the UI component would only respond passively to the events thrown by the Presenter component.

The Code

The game has two main entities: the shape (BaseShape-inherited classes) and the board (the BricksBoard class). Both inherit from the BaseBricksArray abstract class that implements a bi-dimensional array of bricks (Brick class).

protected IBrick[,] shapeArray = null;

The heart of the game is the BricksBoard class. It contains a 10 x 16 array of bricks, and also the game logic functionalities such as moving and rotating a piece according to the arrow buttons, testing whether a piece can still be moved, deciding if there are completed rows that must be removed, and deciding when the game is over.

As soon as the game starts, the GetRandomShape is invoked, and a shape of a random type and a random color is created:

private IShape GetRandomShape()
{
    IShape newShape = null;
    Random randomClass = new Random();
    int randomCode = randomClass.Next((int)ShapeCodes.Stick, 
                                      (int)ShapeCodes.Z + 1);
    .
    .
    .

Before every move attempt, the BricksBoard class will invoke the TestPieceOnPosition method, to assure that the shape will not go off board and will not collide with other bricks in the board.

public bool TestPieceOnPosition(IShape shape, int x, int y)
{
    for (int row = 0; row < shape.Height; row++)
    {
        for (int column = 0; column < shape.Width; column++)
        {
            //is the position out of range?
            if (column + x < 0)
                return false;

            if (row + y < 0)
                return false;

            if (column + x >= width)
                return false;

            if (row + y >= height)
                return false;

            //will the shape collide in the board?
            if (
                shapeArray[column + x, row + y] != null &&
                shape.ShapeArray[column, row] != null)
            {
                return false;
            }
        }
    }
    return true;
}

If the piece can be placed according to the move attempt, then the method PutPieceOnPosition is invoked in order to transfer the bricks from the shape to the board.

The MoveLeft and MoveRight methods of the BaseShape class just move the bricks of the shape to the left or to the right, if possible:

public bool MoveLeft()
{
    bool test = false;
    if (!anchored)
    {
        if (containerBoard == null)
            throw new NullContainerBoardException();

        containerBoard.RemovePieceFromCurrentPosition(this);

        test = containerBoard.TestPieceOnPosition(this, this.X - 1, this.Y);
        if (test)
        {
            containerBoard.RemovePieceFromCurrentPosition(this);
            containerBoard.PutPieceOnPosition(this, this.X - 1, this.Y);
        }
    }
    return test;
}

The Rotate90 and Rotate270 methods implement the clockwise and counterclockwise rotations for a shape, respectively. This is done by transposing the bricks from the columns to the rows of the shape, before trying to put the shape on the board:

public bool Rotate270()
{
    bool test = false;
    if (!anchored)
    {
        if (containerBoard == null)
            throw new NullContainerBoardException();
        
        containerBoard.RemovePieceFromCurrentPosition(this);
        
        IBrick[,] newShapeArray = new IBrick[height, width];
        IBrick[,] oldShapeArray = new IBrick[width, height];
        for (int row = 0; row < height; row++)
        {
            for (int column = 0; column < width; column++)
            {
                newShapeArray[row, width - column - 1] = shapeArray[column, row];
                oldShapeArray[column, row] = shapeArray[column, row];
            }
        }
        .
        .
        .
    }

For the key-handling capabilities, I merely copied the Input class from Jonas Follesø's article. Besides, I created a InputBuffer class that encapsulates the Input class. The InputBuffer class has the ability to process buffered keystrokes, and also allows that views can subscribe to the utility class. I do this by implementing the Observer Pattern in the InputBuffer class and in the subscriber view:

public void AddObserver(IInputObserver observer)
{
    observers.Add(observer);
}

History

  • 2008-04-24: Initial posting.
  • 2008-05-01: Code and article renaming; Input problem solved; New game Ballons! added.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here