下降块游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/falling-blocks-game-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 9 分钟阅读 - 4155 个词 阅读量 0下降块游戏(译文)
原文地址:https://www.codeproject.com/Articles/27553/Falling-Blocks-Game
原文作者:Lipman Roi
译文由本站 robot-v1.0 翻译
前言
Creating the game
创造游戏
介绍(Introduction)
我一直在研究一些设计模式(I’ve been looking into some design patterns on) DoFactory(DoFactory) 作为一个好的实践,我决定编写一个使用Factory模式的Tetris游戏.(and as a good practice, I decided to write a Tetris game that uses the Factory pattern.) 我不会详细介绍该模式,但建议您阅读一下.(I’m not going to get into details about the pattern, but I would recommend reading about it.) “抽象工厂设计模式.(“Abstract Factory Design Pattern.) 定义:(Definition:) 提供一个用于创建相关或相关对象族的接口,而无需指定它们的具体类."(Provide an interface for creating families of related or dependent objects without specifying their concrete classes.") 您可以阅读有关模式(You can read about the pattern) 这里(here) .(.) 我认为你们在一生中都曾玩过最著名的方块游戏"俄罗斯方块”,因此没有理由解释游戏规则.(I assume you have all played the most famous falling blocks game ‘Tetris’ at some point in your life, so there’s no reason to explain the rules of the game.)
开始(Starting Off)
当我开始编写游戏时,我实际上并不知道从哪里开始.出于目标的考虑,我决定不考虑任何开放源代码的代码块或有关此主题的任何教程.我想用困难的方式弄清楚事情.(When I started writing the game, I didn’t actually know where to start. As an objective, I decided not to look at any open source falling blocks code or any tutorial on the subject. I wanted to figure out things the hard way.)
所以我认为一个好的起点是最简单的形状-立方体-四乘四的正方形.但在此之前,我们必须创建一个(So I thought a good place to start would be the simplest shape there is - the cube - a four by four square. But just before that, we’ll have to create an) abstract
类命名(class named) Shape
所有实际形状都将继承.(which all the actual shapes will inherit from.)
只是一个形状(Just a Shape)
让我们快速浏览一下(Let’s have a quick look at the) shape
的代码:(’s code:)
abstract class Shape
{
// holds the current shape turn state shapes can rotate up to 4 times.
protected int turnState;
public int TurnState { get {return turnState;} set {turnState = value;}}
/*
* Returns the new cords of the shape after rotation.
*/
public abstract Point[] Turn(int top, int left);
/*
* Returns the current shape cords depends on the top left position
* of the shape and its turnState.
*/
public abstract Point[] GetCoordinates(int top, int left);
}
如你看到的,(As you can see,) shape
可以旋转(每次90度),我们可以移动(s will be able to turn (90 degrees each time) and we can move the) shape
通过获取所需左上角位置的坐标.我们将跟踪(by retrieving its coordinates for a desired top left position. We will keep track of the) shape
左上角的坐标,这将使情况更加概括.(’s top left coordinate, this will keep things generalized.)
所以有了(So with the) Shape
上课的地方和想法(class in place and the idea that every) shape
我们将创建将继承自它的内容,让我们继续前进(we’ll create will inherit from it, let’s move on to our) square
类.(class.)
不要成为正方形(Don’t Be a Square)
class Square : Shape
{
public Square()
{
}
public override Point[] Turn(int top, int left)
{
return GetCoordinates(top, left);
}
public override Point[] GetCoordinates(int top, int left)
{
Point[] cords = new Point[4];
cords[0] = new Point(left, top);
cords[1] = new Point(left + 1, top);
cords[2] = new Point(left, top + 1);
cords[3] = new Point(left + 1, top + 1);
return cords;
}
}
简单啊.的(Simple auh. The) square
不需要转弯,因此其左上角坐标始终在同一位置.(doesn’t need to turn so its top left coordinate is always at the same place.)
形状及其坐标(Shapes and their Coordinates)
的(The) square
标为1的是我们的左上角位置,我们一直在跟踪该位置.(labelled 1 is our top left position which we keep track after.)
让我澄清一下(Let me clarify the)
GetCoordinates
方法.(method.)
假设我们想将正方形下移一排.我们将要做的是(Let’s say we’d like to move our square one row down. What we will do is call the) GetCoordinates
Y值增加1,X值记住,我们跟踪左上角的坐标.因此,通过将Y增加1,我们将(with Y increased by 1 and X remember we keep track after the top left coordinate. So by increasing Y by 1, we moved the) square
向下一行:(one row down:)
cords[0] = new Point(left, top) //is our new top left position
基于这一点,我们构建了其余的(Based on this point, we construct the rest of the) square
.(.)
我们仍然必须检查我们刚才的举动是否合法,但稍后会解决此问题.(We still have to check if the move we just made is legit but will address this problem later on.)
一旦我们了解了这个关键概念(Once we understand this key concept of) shape
的表现和运动,创造新的(s representation and movement, creating new) shape
s很容易.(s is easy.)
旋转一个(Rotating a) shape
只是弄清楚如何(is just a matter of figuring out how the) shape
应该在旋转后进行布局,并且我们的左上坐标应该在哪里,然后剩下的就是重建(should be laid out after rotation and where our top left coordinate should go, then all that’s left is reconstructing the) shape
基于此新的左上角坐标.(based on this new top left coordinate.)
我不太确定什么是正确的方法(I wasn’t so sure about what’s the right way to turn each)
shape
,所以我想出了自己的办法.(, so I’ve come up with my own way.)
我一直在谈论坐标已有一段时间了.让我们看看他们实际去了哪里.(I’ve been babbling about coordinates for a while now. Let’s see where they actually go.)
游戏的棋盘类(The Game’s Board Class)
将游戏视为具有宽度和高度的二维布尔网格,填充的空间将标记为(Think of the game as a two dimensional Boolean grid that has width and height, a filled space will be marked as) true
,可用空间将设置为(, free space will be set to) false
.(.)
棋盘类通过以下方式管理游戏的棋盘:(The board class manages the game’s board by:)
- 检查是否可以重新定位给定的形状(Checking if it’s possible to reposition a given shape)
- 将形状重新绘制到屏幕上(Redrawing the shape to the screen)
- 更新游戏棋盘矩阵的布尔值(Updating the boolean values of the game board matrix)
- 检查是否已填充任何行(Checking if any rows have been filled)
将所有这些责任放在一个地方似乎是合乎逻辑的.本课程有很多内容,因此我仅指出一些我认为有趣的内容.(It seems logical to put all this responsibility in one place. There’s much to this class so I’ll point out only few things that I find interesting.)
出现的一个问题是,我们如何知道某个形状的移动(向右,向左,向下,旋转)是否可能?(One question that came up is how do we know if a certain shape’s move (right, left, down, rotate) is possible?)
当然,我们可以对每个形状进行复杂的检查,但这会花费很长时间.幸运的是,有一种更快的方法可以做到这一点.(Sure we can implement a complex check for each shape, but this would take too long. Fortunately there’s a quicker way to do this.)
让我们来看看董事会的班级(Let’s have a look at the board’s class)
Move
方法:(method:)
public bool Move(Point[] currentPos, Point[] desiredPos)
{
if (!LegitMove(currentPos, desiredPos))
return false;
// Remove shape from the board
Pen pen = new Pen(backgroundColor, 3);
DrawShape(currentPos, pen);
// Redraw
RePosition(desiredPos);
pen = new Pen(Color.Blue, 3);
DrawShape(desiredPos, pen);
return true;
}
该方法获取当前形状位置坐标和所需坐标(形状要移动到的位置).(The method gets the current shape position coordinates and the desired coordinates (where the shape wishes to move).)
我们在(What we do within the) LegitMove
方法是创建游戏棋盘的副本,并从中"切出"当前形状,以免占用任何空间,然后尝试将形状粘贴到新位置.如果我们成功做到这一点,则此举是合法的,我们将用我们制作的副本覆盖游戏板.否则我们无法将形状移到新位置并返回(method is create a copy of the game’s board and “Cut out” the current shape from it so it won’t take any space, then we try to paste the shape to its new position. If we succeed doing so, the move is legit and we overwrite the game’s board with the copy we’ve made. Otherwise we can’t move the shape to its new location and return) false
表示未对原始游戏的棋盘进行任何更改.(indicating no changes have been made to the original game’s board.)
这为我们提供了一种检查所有可想像的简单机制(This gives us a simple mechanism for checking all imaginable) shape
只要我们有办法获得电流(s moves as long as we have a way to get the current) shape
的位置(其在板上的坐标)及其新的所需位置.(s position (its coordinates on the board) and its new desired position.)
放在一起(Putting It All Together)
那么事情实际上是如何运作的呢?让我们快速浏览一下游戏” Flow".(So how do things actually work? Let’s quickly go over the game “Flow”.)
游戏要求(The game asks the) shape
一个工厂(factory for a) shape
.下一节将提供有关此类的更多信息.(. More information about this class in the next section.)
就我们而言,我们不在乎实际(As far as we are concerned, we don’t care what the actual) shape
是.我们所知道的是,我们有一个(is. All we know is that we’ve got a) shape
我们可以与之互动.(and we can interact with it.)
接下来,我们尝试将(Next we try to position the) shape
在顶部中间的板上.如果我们未能做到这一点,那么我们就假定棋盘已满,这意味着游戏结束了.(on the board at the top middle. If we failed to do that, we assume the board is filled up to the top and that means the game is over.)
否则,我们将设置一个计时器来移动(Otherwise we set a timer that will move our) shape
在每个刻度内向下一行.(down one row within each tick.)
如果(If the) shape
成功下移了一行,我们什么也没做.(moved down one row successfully, we do nothing.)
否则,如果(Otherwise if the) shape
不能向下移动一行,那是因为它撞到了另一排(couldn’t move one row down, then that’s because it hit some other) shape
或达到了游戏的底线.我们将必须检查玩家是否设法填满整行,因此我们进行检查并在需要时更新棋盘(清除填满的行,将行重新放置在清除的行上方).(or it reached the game’s bottom board. We will have to check if the player had managed to fill a whole row(s), so we perform the check and update the board if needed (Clear filled rows, reposition rows above the cleared rows).)
就目前而言(That’s about it for the current) shape
.所以得到一个新的(. So get a new) shape
从我们的工厂重复.(from our factory and repeat.)
在整个过程中,用户可以操纵电流(During this whole process, the user can manipulate the current) shape
通过旋转,向左,向右和向下移动,并针对每个"重新定位",检查是否可以移动.(by rotating, moving left, right and down, and for each “reposition”, we check if the move is possible.)
工厂艰难的一天(Hard Day at the Factory)
class ShapesFactory
{
Random rand;
enum shapes { Square, Stick, L, MirroredL, Plus, Z, MirroredZ };
public ShapesFactory()
{
rand = new Random();
}
public Shape GetShape()
{
int shape = rand.Next(7);
switch (shape)
{
case (int)shapes.Square:
return new Square();
break;
case (int)shapes.Stick:
return new Stick();
break;
.
.
.
case (int)shapes.MirroredZ:
return new MirroredZ();
break;
default:
return new Square();
}
}
此类负责创建新的(This class is responsible for creating new) shape
基于随机数.(s based on a random number.)
工厂有其产品(L,立方体,Z等),并且当游戏需要(The factory has its products (L, cube, Z, etc.) and when the game requires a) shape
,工厂交货.(, the factory delivers.)
最后的话(Last Words)
游戏缺少某些"关键"功能,例如游戏规则,让用户知道下一步该怎么做(The game is missing some “key” features such as game boarders, letting the user know what the next) shape
将被显示并保持得分.(is going to be, displayed and keep score.)
但是游戏的主要核心在那里,那是我的实际目标.图形也不是很好,但是我不是设计师.(But the main core of the game is there and that was my actual goal. Also the graphics aren’t that good, but I’m not a designer.)
我喜欢写这个游戏,花了我一段时间才弄清楚应该如何工作,但是一旦我建立了检查机制,(I enjoyed writing this game, it took me a while to figure out how things should work, but once I got the check mechanism in place and the) Shape
类(class) abstract
方法,添加新(methods, adding new) shape
s令人惊讶地迅速.(s was surprisingly swift.)
关于包装.我希望我已经指出了有关此游戏如何工作的一些关键观点.如果您有任何意见或疑问,请随时给我写信.(That about wraps it. I hope I’ve pointed out some key view points on how this game works. In case you’ve got any comments or questions, please feel free to write to me.)
历史(History)
- 6(6)日(th)2008年7月:初始职位(July, 2008: Initial post)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# .NET3.5 Windows .NET WinXP Dev 新闻 翻译