用面向对象方法进行俄罗斯方块游戏设计(持续更新中)

游戏介绍:

顾名思义,俄罗斯方块自然是俄罗斯人发明的。这位伟人叫做阿列克谢·帕基特诺夫(Alexey Pazhitnov)。这款游戏操作简单,老少皆宜,也是一个不错的练手项目。

首先给几个经典的游戏界面先(当然,我们的目的是做出类似的效果)

游戏界面1:

用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第1张图片

游戏界面2:

用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第2张图片

游戏界面3:

用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第3张图片

游戏界面4:

用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第4张图片

游戏的基本操作很简单:

←:左移
→:右移
↑:旋转
↓:加速下降

当然,最好是可以自行设置快捷键,比方说用WSAD来代替。

游戏场景:

打开游戏,选择游戏难度,按开始键进行游戏。在游戏正上方会随机生成一个种类的方块,同时还会显示下一个方块的样子。用左右方向键控制方块的方向,用向上方向键旋转方块,用向下方向键加速下降。方块遇到墙壁或者撞到静止的方块不能穿透。底下方块如果填满一行,则进行消除。一次消除得越多,则得分越多。当方块到底后,会将之前已经预显示的方块放置到窗体正上方再下落。这样循环往复,直到静止的方块堆到顶,游戏结束。

思考:


首先,需要找出可以抽象出的类。从游戏的场景先找出一些对象:

对象:

  • 游戏画面(包含所有方块的区域)
  • 玩家
  • 预显示方块
  • 运动中的方块
  • 底下静止的方块堆
  • 分数

行为:

  • 旋转
  • 消除
  • 记分
  • 生成随机方块

俄罗斯方块的另一个名称是“砌墙”,我觉得这样更加形象生动。因此可以将上面的对象转换成:

  • 房子--游戏画面
  • 建筑工人--玩家
  • 砖头--运动中的方块
  • 墙--静止的方块堆

因此,初步的类图就出来了,如下:
用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第5张图片

哈哈,现在我们终于有了一些基本的类了:

  • House
  • Wall
  • Brick
  • HouseWorker

现在我们就看看这些对象之间的关系。砖头和墙的唯一关系就是当砖头触底的时候,就会成为墙的一部分。因此Wall需要有一个接收砖头Brick的操作,我们称之为砌墙BuildWall(brick). 而Wall和Brick都是依附于房子House的,因此这两个类(Wall,Brick)是House的一个部分,并且墙的宽度不能超过房子的宽度,而砖头只能在房子里左、右、下,旋转的移动。

首先来看一下这些移动方法(MoveLeft,MoveRight,MoveDown,Rotate)应该加入到哪个类中。

最直接的是放到Brick类中,因为我们是移动砖头,看看有什么问题呢?对了,Brick在左移和右移时,需要知道是否碰壁了。因此,在这些方法中需要知道房子的宽度,同时要知道是不是到底碰到墙了。这样Wall要包含Brick,而Brick也要包含Wall和House。嘿嘿,似乎有点问题~~~~~~

直觉,放到Wall方法中是相当没有道理的,那就放到House中。由House来控制Brick的移动和旋转,似乎不错,比较完美了。

再接下想想,有好多种不同样子的砖头,除了样子不同以外,操作都是类似的。那Brick就变成抽象类了,其他种类的砖头从Brick中继承。

(写累了,先到这里...)

继续....

问题来了......砖头有很多种,每一种都可以旋转成其他样式的砖头(除了四四方方那个大方块怎么转都是一样外)。那具体的砖头类有多少种呢?

第一种做法:

把每次旋转后的不同样式的砖头当成另一个Class,这样的好处是,可以在Class中标记下次旋转后变成那种类型的Class。不足之处是需要扩展4倍的Class(汗~~~~~~)。爱偷懒的就用这种:)

第二种做法:

只生成基本的旋转类型,其他类型的位置通过旋转方法获得,这种方法的好处是Class会比较少,推荐这种做法。

接下来开始找行为了,之前已经确定了一些行为,如下 (可能还有些不合理,之后会再重构):

  • House:
  • Wall: BuildWall(Brick)
  • Brick: MoveLeft,MoveRight,MoveDown,Rotate()
  • HouseWorker:

回到之前移动砖头的问题,砖头在左移和右移的过程中,可能会撞到墙壁,因此需要有是否撞墙的行为判断:IsAgainstWall。为了更好的表达出撞的是哪边的墙,我们再把这个行为拆分:IsAgainstLeftWall(), IsAgianstRightWall()。同时,在MoveDown的过程中,我们还需要检测是否碰到墙了。因此也要增加一个行为:IsAgainstDownWall()。到底后,如果某一行已经填满,还要有一个消去一行墙的行为:RemoveWall()。同时,到底后,原来的砖头就变成墙了,需要再生成新的砖头:CreateNewBrick()。

当然,如果越堆越高,到顶了,砌墙就结束了,所以还要有一个是否到顶的行为:IsAgainstHead().至于建筑工人,当然是有开始/结束砌墙的行为了。


好事情,行为(方法)越来越多了.....我们先将这些行为堆积到Class中(还是以自觉为主,随便放^_^).

  • House: CreateNewBrick(),IsAgainstHead()
  • Wall: BuildWall(Brick), RemoveWall()
  • Brick: MoveLeft(),MoveRight(),MoveDown(),Rotate(),IsAgainstLeftWall(),IsAgainstRightWall(),IsAgainstDownWall()
  • HouseWorker: StartBuildWall(),StopBuildWall()

这下子我们的类图又丰富了:

用面向对象方法进行俄罗斯方块游戏设计(持续更新中)_第6张图片

你可能感兴趣的:(软件开发/架构)