Layer类
在前面的示例中并没有使用背景,而且程序中的物体也很单一,但是实际的游戏不可能这样。一般来讲,游戏都会有背景,有的甚至用几层背景来表示画面的层次感。在游戏开发中可以通过作图完成对背景的处理,不过在 MIDP v2.0 中可以通过 Layer 对象轻松处理游戏背景、物体的移动和实现动画。
图层是可以在游戏画布中单独绘制并能够移动的一些对象,一般来说,游戏都会有超过一个的图层。例如,背景图层用来绘制游戏的背景,场景图层用来显示当前的场景,物体图层用来显示当前场景中移动的物体。例如,用游戏的一个场景来举例,游戏的背景图是星空,占据整个屏幕;然后在上面覆盖建筑物图层,这一图层没有覆盖整个屏幕,而且是透明的,没有覆盖和透明的区域上就会显示出背景;然后最上面才是物体图层显示移动的主角和障碍物。在MIDP 中TiledLayer类用来显示背景和场景,Sprite类用来显示移动的物体,这两个类都是直接从Layer 类中派生的。
在MIDP 中并没有限制图层的数量,不过在开发游戏时必须考虑到设备的处理能力对实际的图层数量做出限制。
类的定义为:public abstract class Layer extends Object ,是一个虚类。
public abstract class Layer extends Object
java.lang.Object
+-javax.microedition.lcdui.game.Layer
Layer 类是一个虚类并不能直接使用,因此在MIDP 中还定义 Layer 类的派生类 TiledLayer类和 Sprite 类处理背景图层和移动的物体。Layer 类中提供的方法如表 7.2 所示。
7.3.1.1.1 表 7.2 Layer 类所定义的方法
方法名称 |
方法原型与作用 |
getHeight |
public int getHeight( )
得到图层的高度 |
getWidth |
public int getWidth( )
得到图层的宽度 |
move |
public void move(int dx, int dy)
移动图层,参数dx和dy分别表明在X轴和Y轴上移动的距离。如果dx 距离小于零,则表示向左或向上移动;如果dy 距离大于零,则表示向右或向下移动 |
续表
方法名称 |
方法原型与作用 |
getX |
public int getX( )
得到图层的起始点X 坐标 |
getY |
public int getY( )
得到图层的起始点Y 坐标 |
setPosition |
public void setPosition(int x, int y)
将图层移动到参数(x, y) 指定的坐标处 |
setVisible |
public void setVisible(boolean visible)
设置图层是否可见 |
isVisible |
public boolean isVisible( )
检测图层是否可见 |
paint |
public abstract void paint(Graphics g)
绘制图层,只有对于可见的图层才会被实际绘制。一般来说,不需要直接调用图层对象的 paint 方法,而是由LayerManager 对象调用这个方法 |
由于Layer 是无法直接使用的,因此在处理背景时需要用到 TiledLayer (分块图层)类。TiledLayer 类能够按照单元的方式组织整个大的背景图层。类的定义为:
public class TiledLayer extends Layer
java.lang.Object
+-javax.microedition.lcdui.game.Layer
+-javax.microedition.lcdui.game.TiledLayer
在 TiledLayer 类中有两个概念:单元和图像分块。
单元是指将整个图层分为相同大小的区域,假设游戏屏幕尺寸为:130×60,每个单元的面积为10×10,那么可以把屏幕分为13×6个单元。
图像分块是指将一幅大的图像按照单元大小分为多个块,对于屏幕的每个单元都可以用一个图像进行填充。
TiledLayer 对象主要作用是管理图像分块和屏幕单元的填充。
l 首先一个TiledLayer 对象中包含了多个分块的图像。
l 其次当前图层会被分为多个大小相等的单元,每个单元可以使用对象本身包含的一个图像分块填充。
图7.2演示了如何将一幅大的图像分割为为多个分块。从图7.2 中可以了解到一幅大的图像被分为序号从1(不是从零开始,序号零被用来表示空图像)开始的多个分块。原始图像按照从左到右,从上到下的顺序计算新的分块序号,此外每个分块不一定需要设计为正方形(图7.2 中序号4与序号5中的浅灰色部分为透明颜色)。
如图7.2 所示,所有图像分块的序号都是正数,表示的是静态图像分块。此外序号为0的分块也是合法的,表示空图像,相当于一个全透明的图像。与序号为正数的分块不同之处在于,序号为 0 的分块由系统提供不需要用户提供。
7.4.1.1.1 图7.2 图层中所用到的图像分块的构成
本节只介绍利用单一图层进行显示的知识,使用多个图层的知识将在7.5节介绍。如果要创建显示一个图层需要以下步骤。
(1) 装入图像。
(2) 创建一个 TiledLayer 对象。
(3) 把图像装入TiledLayer 对象,并设定图层的大小和每个分块的尺寸。TiledLayer 对象会根据图像的尺寸计算分块的数量,并且通过每个分块的尺寸和单元格的数 量计算图层的面积,实际这个过程是在创建TiledLayer 对象时完成。
(4) 把图像分块按需要填入单元格,以后如果需要修改某个单元格的图像,则可以重新设置。
(5) 调用TiledLayer 对象的paint 方法进行绘图。
(6) 调用Canvas对象的flushGraphics 方法刷新屏幕。
除前面提到的静态图像分块和空图像分块外,还有一种分块类型,就是序号为负数的分块,在MIDP 中表示动画分块。在图层中使用动画分块的好处在于,如果修改动画分块内的图像,那么整个图层上相同序号的动画分块填充的单元格都会同时改变。
与静态分块不同,动画分块是需要额外创建的,创建的第一个动画分块的序号为 –1,第二个为 –2。在创建动画分块时,需要指定一个静态分块图像作为初始图像,为了实现动画效果可以在变换画面时用另一个静态分块图像替换动态分块中的现有图像。例如,先创建一个动画分块,假设序号为 –1。初始图像为图7.2 中最下面一组分块的序号1分块,然后依次用其他序号的分块图像替代序号为–1 的动态分块中的图像。这样被序号为 –1 的分块所填充的所有单元格都能显示出动态效果。
TiledLayer 类的方法如表 7.3 所示。
7.4.1.1.2 表7.3 TiledLayer 类所包含的方法
方法名称 |
方法原型与作用 |
TiledLayer |
public TiledLayer(int columns, int rows, Image image, int tileWidth, int tileHeight)
构造方法,参数columns和rows分别表明图层中的单元格列数和行数,参数 image 为包含所有分块的图像,参数 tileWidth和tileHeight分别表明每个分块的宽度和高度。图层的面积是单元格的数量乘以每个分块图像的面积。图层实际的宽度为 columns × (tileWidth × tileHeight) ,高度为rows × (tileWidth × tileHeight) |
setCell |
public void setCell(int col, int row, int tileIndex)
将图层中指定位置(col,row )单元格设置为序号为参数tileIndex 指定的分块图像。tileIndex 必须为0 或者是正数。如果为0 表示该单元格不填充 |
fillCells |
public void fillCells(int col, int row, int numCols, int numRows, int tileIndex)
将图层中指定的单元格区域,位置为( col, row)、面积为( numCols, numRows) 用序号为tileIndex分块图像填充。fillCells与setCell 方法不同之处在于,能够一次设置多个相同的单元格 |
getCellWidth |
public int getCellWidth( )
得到单元格宽度,也就是构造对象时 tileWidth 的值 |
getCellHeight |
public int getCellHeight( )
得到单元格高度,也就是构造对象时 tileHeight 的值 |
getColumns |
public int getColumns( )
得到图层中单元格的列数 |
getRows |
public int getRows( )
得到图层中单元格的行数 |
setStaticTileSet |
public void setStaticTileSet(Image image, int tileWidth, int tileHeight)
重新创建分块图像。在执行此操作后对象所包含的原有分块会被删除,而且图层的面积会根据新的分块大小重新计算 |
CreateAnimatedTile |
public int createAnimatedTile(int staticTileIndex)
创建一个动画分块,初始化时把序号为staticTileIndex 的分块图像作为这个动画分块的图像。返回值为创建的动画单元格序号,第一个创建动画单元格为 -1,第二个为 –2 |
setAnimatedTile |
public void setAnimatedTile(int animatedTileIndex, int staticTileIndex)
将序号为animatedTileIndex 的动画分块的图像用序号为 staticTileIndex 的分块图像代替 |
getAnimatedTile |
public int getAnimatedTile(int animatedTileIndex)
得到序号为animatedTileIndex 的动画分块实际的图像分块序号 |
下面先举一个比较简单的例子讲解单一图层的用法,在这个示例中将会直接使用图层进行绘图(使用LayerManager 对象管理多个图层的知识将在7.5 节介绍)。此处要演示的效果是:在图层上将某几个单元格创建为动画单元格并循环显示动画效果。
程序中所使用的图像如图7.3 所示,每个分块面积为30×30像素。序号4用来填充地面;序号5用来填充屏幕的空白区;序号1和序号2以动画的方式显示一个跳动的小球;序号3和序号6用来显示星星,在这里会创建一个动态分块 –1 ,并且用序号3和序号6的图像来轮流替换动态分块中的图像。
7.4.1.1.3 图7.3 用来创建图层的图像分块