5,427,303 members and growing! (15,142 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » Mobile Development » Games     Intermediate License: The Code Project Open License (CPOL)

Bricks for Pocket PC

By Marcelo Ricardo de Oliveira

A .NET Compact Framework version of the Bricks game.
C# (C# 2.0, C#), .NET CF, Dev

Posted: 24 Apr 2008
Updated: 24 Apr 2008
Views: 4,826
Bookmarked: 12 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
5 votes for this Article.
Popularity: 2.99 Rating: 4.27 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
3 votes, 60.0%
4
2 votes, 40.0%
5

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Marcelo Ricardo de Oliveira


Marcelo Ricardo de Oliveira is MCSD.NET/MCAD and is software developer at Spring Wireless Brasil (São Paulo - Brazil), a leading end-to-end mobile business solutions provider.
Occupation: Software Developer
Company: Spring Wireless
Location: Brazil Brazil

Other popular Mobile Development articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 6 of 6 (Total in Forum: 6) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralInput problemsmemberATM_Guy10:46 29 Apr '08  
GeneralRe: Input problemsmemberMarcelo Ricardo de Oliveira13:39 30 Apr '08  
GeneralGreat articlememberPeter Kohout3:59 25 Apr '08  
GeneralRe: Great articlememberMarcelo Ricardo de Oliveira8:26 25 Apr '08  
GeneralA few issues you will have to fixmemberThomas Stockwell3:38 25 Apr '08  
GeneralRe: A few issues you will have to fixmemberMarcelo Ricardo de Oliveira8:20 25 Apr '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Apr 2008
Editor: Smitha Vijayan
Copyright 2008 by Marcelo Ricardo de Oliveira
Everything else Copyright © CodeProject, 1999-2008
Web12 | Advertise on the Code Project