模型类是指对本游戏中出现的实物进行封装操作后而成的类。本游戏中有两种模型类:通用模型类和关卡类。接下来,我们分别介绍这两种类。
本游戏会包含多种类型的模型,这些模型都具有一些共同特征,例如有坐标和图片,将这些共同特征封装成一个模型抽象类作为公共父类,可以减少其他模型的代码量。RigidBody类就是这样一个模型抽象类,下面从四个方面介绍该类。
RigidBody类有三个属性,分别是模型在游戏面板中的横坐标x和纵坐标y,以及模型使用的图片对象image,代码如下:
RigidBody类提供了两种构造方法。其中,第一种构造方法仅初始化图片,代码如下:
第二种构造方法仅初始化横纵坐标,并且该构造方法会被箱子类所使用,代码如下:
虽然RigidBody类已经提供了初始化图片的构造方法,但在游戏过程中模型的图片可能会发生变化。因此除了提供图片的getter方法,还需要提供setter方法,以确保模型的图片可以灵活地被读取和替换。代码如下:
在本游戏中,需要判断某个模型对象是否已经被包含在关卡中。由于本游戏使用ArrayList来保存关卡中对应的模型对象,因此要使用ArrayList的contains()方法来判断是否包含某个模型的话,就必须重写RigidBody类的equals()方法来指定比较规则。
本游戏判断两个模型对象是否是同一个元素时,除了要看两个模型对象所属模型类是否一致,还要看它们的坐标是否重合。因此,在equals()方法中,类型和横纵坐标被作为判断标准。只要类型相同且坐标重合的模型对象,本游戏就会将其视为同一个元素,例如两个处在同一个位置的墙块会被认为是同一个元素。重写后的equals()方法代码如下:
墙块在本游戏中会阻挡玩家和箱子移动。Wall类是本游戏的墙块类。墙块使用的图片是由图片工具类GameImageUtil.wallImage提供的灰色方块,其效果如图1.2所示。墙块类直接使用父类构造方法来为图片赋值。
图1.2 本游戏中的墙块效果图
墙块类代码如下:
目的地在本游戏中标示箱子需要摆放的目标位置,当所有箱子都被摆放在目的地之后,本游戏会进入下一个关卡。Destination类是本游戏的目的地类。目的地使用的图片是由图片工具类GameImageUtil.destinationImage提供的绿色圆圈,其效果如图1.3所示。目的地类直接使用父类构造方法来为图片赋值。
图1.3 本游戏中的目的地效果图
目的地类代码如下:
玩家类是由用户控制的“玩家”角色,该角色可以在上、下、左、右四个方向上自由移动,并且具有推动箱子的能力。Player类是本游戏的玩家类。玩家类使用的图片是由图片工具类GameImageUtil.playerImage提供的蓝色方块,其效果如图1.4所示。玩家类直接使用父类构造方法来为图片赋值。
图1.4 本游戏中的玩家效果图
玩家类代码如下:
箱子是本游戏中可被“玩家”推着移动的元素,在所有箱子都被推至目的地后,本游戏会进入下一个关卡。Box类是本游戏的箱子类。为了让用户容易区分箱子的到达状态,图片工具类提供两种箱子图片:未到达目的地的黄色箱子GameImageUtil.boxImage1,效果如图1.5所示;已到达目的地红色箱子GameImageUtil.boxImage2,效果如图1.6所示。
图1.5 箱子未达到目的地的效果图
图1.6 箱子已到达目的地的效果图
为了让箱子能够灵活地更换图片,Box类提供了arrived属性,用于记录箱子是否已经到达目的地。此外,Box类还提供了arrive()方法(该方法在箱子到达目的地时被触发)和leave()方法(该方法在箱子离开目的地时被触发)。这两个方法被触发后,箱子的状态和图片可以被更换。
箱子类的代码如下:
Map类是本游戏的关卡类,该类用来封装和加工关卡中的所有元素。关卡中出现的所有元素都是RigidBody模型类的子类,因此它们都被记录在一个RigidBody[][]二维数组中。关卡在类初始化的时候会单独把玩家对象和箱子对象从二维数组中抽出来,并对它们单独进行保存,这样方便本游戏随时修改这两种元素的坐标。下面将从4方面介绍关卡类。
关卡类有三个属性,分别用于记录三种数据:matrix[][]用于记录关卡中的所有元素,包含墙块、目的地和空白区域;player用于记录玩家对象及其位置;boxes用于记录关卡中所有的箱子对象及其位置。代码如下:
构造方法的参数是一个二维数组,用于保存关卡中的所有元素。这个二维数组由关卡工具类从关卡文件中读取出来。关卡类在构造时要对这个二维数组进行加工,加工的代码位于init()关卡初始化方法中。构造方法的代码如下:
因为传入的、用于保存关卡中所有元素的数组是包含玩家和箱子的,所以为了方便操作玩家和箱子的坐标,在创建关卡的同时,我们会将这两种类型的对象提取出来。init()方法是初始化关卡的方法,该方法会找出关卡数组中玩家和箱子的位置,并单独记录这些位置,同时清空原数组中玩家和箱子的对象。方法的代码如下:
关卡类中的每一个属性都提供了对应的getter()方法。获取关卡中的所有元素的代码如下:
获取关卡中的玩家对象代码如下:
获取关卡中的箱子列表的代码如下: