Pocket PC 版俄罗斯方块






4.64/5 (8投票s)
砖块游戏的 .NET Compact Framework 版本。
引言
我展示了两个适用于 Pocket PC 的著名砖块游戏的简单版本。在本文中,我将介绍用于开发游戏的一些技术,并提供源代码。我希望读者喜欢它,因为对我来说这是一种真正的享受。
第一个版本是经典版本,彩色方块从顶部落下。在第二个版本中,方块由气球组成,用户必须在气球上升时将它们正确地放置在屏幕顶部的行中。
我应该说,我主要是受到 Jonas Follesø 在他的文章 Pocket 1945 - C# .NET CF 射击游戏 中的出色工作的激励。该文章于 2004 年上传到 The Code Project,至今仍令人印象深刻(并且将在未来许多年内继续令人印象深刻)。因此,在阅读了“Pocket 1945”文章后,我决定自己编写一个游戏,最终借鉴了 Jonas 在他的游戏中使用的一些概念。
背景
第一个砖块游戏是由 Alexey Pajitnov 于 1985 年在莫斯科的苏联科学院 Dorodnicyn 计算中心工作时编写的(谢谢,维基百科)。该游戏几乎移植到所有已知平台,甚至用人类而不是传统的彩色方块来玩(参见 视频)。
游戏
基本上,“方块!”是一个永无止境的 4 段拼图。共有 7 种类型的块(我在游戏中称之为“I”、“J”、“L”、“O”、“S”、“T”和“Z”),并且每次只有一个块从游戏板的顶部落下。四格骨牌的类型是随机产生的。每次玩家在棋盘上填满一行时,该行将被删除,并且上方的方块会塌陷,从而为更多的块腾出空间。
每次完成一行,玩家将获得 10 分,并乘以游戏等级数。每当玩家完成 10 行时,就会达到一个新的等级。
应用程序设计
该解决方案包含两个项目:Bricks4Pocket 和 Bricks4Pocket.Core。第一个项目主要包含 UI 组件,而第二个项目包含繁重的功能。我认为该项目中的一些类值得在这里提及。
我决定在游戏中使用简化的 MVP(模型-视图-演示器)模式。通过这样做,我可以确保 UI 组件仅被动地响应演示器组件引发的事件,从而加强关注点分离。
代码
该游戏有两个主要实体:形状(继承自 BaseShape
的类)和棋盘(BricksBoard
类)。两者都继承自 BaseBricksArray
抽象类,该类实现砖块(Brick
类)的二维数组。
protected IBrick[,] shapeArray = null;
游戏的核心是 BricksBoard
类。它包含一个 10 x 16 的砖块数组,以及游戏逻辑功能,例如根据箭头按钮移动和旋转一块,测试一块是否仍然可以移动,确定是否有必须删除的完整行,以及确定游戏何时结束。
游戏开始后,立即调用 GetRandomShape
,并创建一个随机类型和随机颜色的形状。
private IShape GetRandomShape()
{
IShape newShape = null;
Random randomClass = new Random();
int randomCode = randomClass.Next((int)ShapeCodes.Stick,
(int)ShapeCodes.Z + 1);
.
.
.
在每次移动尝试之前,BricksBoard
类将调用 TestPieceOnPosition
方法,以确保形状不会离开棋盘并且不会与棋盘中的其他砖块发生碰撞。
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;
}
如果可以根据移动尝试放置该块,则调用方法 PutPieceOnPosition
以便将砖块从形状转移到棋盘。
如果可能,BaseShape
类的 MoveLeft
和 MoveRight
方法只是将形状的砖块向左或向右移动。
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;
}
Rotate90
和 Rotate270
方法分别实现形状的顺时针和逆时针旋转。这是通过在尝试将形状放在棋盘上之前,将砖块从形状的列转置到行来实现的。
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];
}
}
.
.
.
}
对于密钥处理功能,我只是从 Jonas Follesø 的文章中复制了 Input
类。此外,我创建了一个封装 Input
类的 InputBuffer
类。 InputBuffer
类能够处理缓冲的击键,并且还允许视图订阅该实用程序类。我通过在 InputBuffer
类和订阅者视图中实现观察者模式来实现此目的
public void AddObserver(IInputObserver observer)
{
observers.Add(observer);
}
历史
- 2008-04-24:首次发布。
- 2008-05-01:代码和文章重命名;输入问题已解决;添加了新游戏“气球!”。