WEB开发网
开发学院WEB开发Jsp 一步一步学习midp2。0游戏编程(三) 阅读

一步一步学习midp2。0游戏编程(三)

 2008-01-05 08:50:35 来源:WEB开发网   
核心提示:一步一步学习midp2,0游戏编程(五)SPRite(精灵类)Sprite是用个用来显示图像的类 (每次一个). 该类和TiledLayer的区别是,一步一步学习midp2。0游戏编程(三),Sprite是由一个图像(可以有好几帧,但是一次只有一个显示)组成 (当然Sprite还有其他的额外特性,在我的例子中我没有检测

一步一步学习midp2。0游戏编程(五)

SPRite(精灵类)

Sprite是用个用来显示图像的类 (每次一个). 该类和TiledLayer的区别是。Sprite是由一个图像(可以有好几帧,但是一次只有一个显示)组成 (当然Sprite还有其他的额外特性,不过每次只能只用一个图像而不是一次使用多个图像来填充屏幕是它的最主要特征.) 因而Sprite 被用来定义一些小的有动作的游戏对象(比如飞船和小行星对撞), TiledLayer 更被常用来构造生动的背景.

Sprite另一个让人激动的特性是:虽然它一次只能显示一个图像,但是我们可以为它定义一系列的图像,以便在不同的环境下构造不同的动画. 在我的例子中,牛仔有三帧图像描绘它的走路,一帧描绘牛仔的跳. 这些将要赋值给Sprite的图像需要被存在一个png文件中.这些帧被存在一个文件中的好处是你可以从治理多个Image对象的麻烦中解脱出来。下面是牛仔类的图片:

  一步一步学习midp2。0游戏编程(三)(图一)
这个是滚草的动画:

一步一步学习midp2。0游戏编程(三)(图二)
在某个特定的时刻决定显示哪一帧帧是非常直观的. 第一, 假如你的图像文件包括多个帧, 在构造Sprite 类的时候你需要指定精灵的高度和宽度(象素值). 图像的高度和宽度必须是精灵高宽的整数倍.换句话说,你要能正好让电脑把你的图像按照精灵的大小划分成几个类. 通过上面的例子你也看到了,至于这些帧是横着拍还是竖着排抑或横竖都有排成一个方阵都无所谓. 接着就可以指定帧数了, 左上放是编号0,然后从左到右,从上到下依次排列。你可以使用setFrame(int sequenceIndex) 选择哪一帧被显示,是要把它的编号作为参数传递就成了.

Sprite还可以让你使用方法setFrameSequence(int[] sequence)定义一个帧的序列.比如我可以为牛仔定义这么一个序列 { 1, 2, 3, 2 }而为滚草定义 { 0, 1, 2 } 序列. 使用nextFrame(),就可以让你的Sprite 动画前进了。(后退的话使用prevFrame()).对于象滚草这样使用了全部帧的情况的确很方便,不过对于象牛仔这样有的帧没有使用的情况就稍微有点复杂了。这是因为一个序列一旦被设置, setFrame(int sequenceIndex) 方法中的参数对应的帧数变成了序列数组中对应的参数而不是图片本身参数的顺序。比如我把牛仔的序列设置为 { 1, 2, 3, 2 },假如我调用setFrame(0)的话,序号为1的那帧被显示, setFrame(3)将会显示2. 因而假如让人物跳起的动画对应的第0帧就没有办法引用了.所以当我需要牛仔跳起时,我需要设置序列为null,然后再调用setFrame(0),接着再把序列设置成 { 1, 2, 3, 2 }. 你可以参考下面代码中的jump() 和 advance(int tickCount, boolean left).

当帧改变时,为了改变精灵的外观,你可对它去旋转或者镜像的操作. 牛仔和滚草都可以向左或者向右运动,所以我需要对图像进行镜像变换以得到相反方向的动作. 当你开始变换成,你需要保留住精灵的引用象素. 这是因为假如你变换你的精灵的时候, 引用象素是一个不变的象素. 你可以设想,你的精灵图像是一个矩形,当它进行变换以后,仍然是原来位置上的那个矩形。这是不一定的。为了说明.我们来设想一个例子,有一个向左站的人,他的引用象素在脚趾上对他进行90度旋转以后, 你会发现他向前倒在地上了.很明显是引用象素发生了作用 (似乎一个图钉).假如你希望变换后仍然占有相同的矩形话,你需要首先调用 defineReferencePixel(int x, int y) 把你的精灵的引用象素设置成矩形的中心, 就想我在下面代码的构造方法中干的那样. 要注重 defineReferencePixel(int x, int y)中的坐标 是相对于精灵的左上角,然而setRefPixelPosition(int x, int y)使用的是整个屏幕的坐标系统. 更准确的说,被送到 setRefPixelPosition(int x, int y)中的坐标用的是精灵将被直接绘制到的Canvas的坐标系统, 但是假如精灵通过 LayerManager进行绘制, 那么使用的就是LayerManager的坐标系统了. (这些坐标的关系在在 LayerManager那部分已经讲解过了) 要非凡注重的是,假如你对一个精灵图像进行了多重变化的话,后面的变化是相对原始状态而不是当前状态. 换句话说,假如你调用了两次 setTransform(TRANS_MIRROR)和调用一次的效果是一样的,而不是想你想象的那样再变换回去. 假如你想让你的变型还原,调用setTransform(TRANS_NONE). 在 Cowboy.advance(int tickCount, boolean left) 中有具体演示.

Layer(包括Sprites TiledLayers) 类的另外一个灵光人激动的特性就是可以让你把你的对象放置到一个对象之间相互关联的体系中而不是一个彼此没有联系的绝对体系. 假如你想让你的精灵Sprite 移动3个象素而不管它现在所处的环境的话, 你可以调用move(int x, int y) ,其中x,y分别代表这两个方向上的偏移量, 而不像 setRefPixelPosition(int x, int y)那样使用绝对坐标来定义精灵的新的位置. collidesWith()也是非常有用.他可以检测一个精灵是否和另外一个精灵或者TiledLayers 或者一个Image发生碰撞. 非凡是假如你把pixelLevel参数设置成true的话,他会检测是不是两个不透明发生碰撞,而假如仅仅这两者的透明发生碰撞就被忽略。

在 "Tumbleweed" 游戏中, 让所有的Sprites播放后,我会检查牛仔是不是和滚草发生了碰撞. (具体检测在 Cowboy.checkCollision(Tumbleweed tumbleweed)方法中,JumpManager.advance(int gameTicks)会调用它)。我会检查牛仔所有滚草之间的碰撞,除了那些不可见的滚草,因为它们肯定会返回false. 在我的例子中,为了省点力气 你可以只检测那些有可能发生碰撞的物体而不是所有的物体两两之间都要检测。你可以注重到,在我的例子中我没有检测滚草之间的碰撞以及背景草皮的碰撞,因为那些碰撞和游戏的逻辑不太相关。假如你在检查一个象素级别的碰撞,你得确认你的图片有透明背景. (透明是很重要的,它让你可以在绘制图片的时候不必把那个那个丑陋的带有背景颜色的矩形也画出来)至于 怎么正确的创建图片参见附录 B.


Tags:学习 midp 游戏

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接