|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionI 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. BackgroundThe 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 GameBasically, 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 DesignThe 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 CodeThe game has two main entities: the shape ( protected IBrick[,] shapeArray = null;
The heart of the game is the As soon as the game starts, the 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 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 The 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 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 public void AddObserver(IInputObserver observer)
{
observers.Add(observer);
}
History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||