使用Game API函数制作二维动作游戏(二)

原创 2003年06月10日 10:50:00

本文所举示例的代码包括一个使用了这个canvas的MIDlet。你可以尝试着运行SimpleGameMIDlet这个小程序,看看它是怎样工作的。你将会看到一个像正在做健身操的海星的东西(或许它正在寻找自己失掉的腿)。

                <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

 

游戏场景就像是洋葱(有层次)

典型的二维动作游戏常包含一个背景和若干动画人物。尽管你可以自己来描绘出这种场景,不过Game API函数使你能够用图层来建立场景。你可以做一个城市的背景图层,另外再做一个含有一辆小汽车的图层。将小汽车图层放在背景上,你就创造出了一个完整的场景。把小汽车放在一个单独的图层中,可以很容易的熟练操控它,而不受背景和其他图层的影响。

 

Game API函数使用以下四个类为图层提供灵活的支持

 

l        Layer类是所有图层类对象的抽象基类。它定义了一个图层的基本属性,包括位置,尺寸,和此图层是否可见。Layer类的每个子类必须定义一个paint()方法,用来把这个图层表现在一个图象上,这个图象将会被描画到屏幕表面上。两个确切的子类TiledLayer和Sprite应该能满足你的二维游戏的需要了。

l        TiledLayer类用来建立背景图像。你可以用一个小的源图像贴的集合来高效的制作大的图像。

l        Sprite类是一个动画层。你提供源帧就可以对整个动画进行完全的控制。Sprite类也提供镜像,并可对源帧作90度旋转。

l        LayerManager类是一个非常有用的类,用来保存你的场景中的所有图层的动作轨迹。LayerManager类 paint()方法的一个简单调用就足以控制所包含的所有图层。

 

使用TiledLayer类

尽管包含一些不是显而易见的微妙不同,TiledLayer类还是很容易理解。这个类的基本思想就是,用一个源图像提供一组图像贴片,这些贴片可以组合成一幅大的场景。例如,下面的图像是64*48像素的。

 

这个图像被分成了12块16*16的图像贴片。TiledLayer类分配给每个图像贴片编号,左上角的图片规定为1,以此类推。上面源图像的各个贴片如下编号:

用代码创建一个TiledLayer类是非常简单的。你需要确定行数和列数,源图像以及这个源图像里每个贴片的像素大小。下面的代码片断告诉你如何装载图像和创建TiledLayer类。

    Image image = Image.createImage("/board.png");

    TiledLayer tiledLayer = new TiledLayer(10, 10, image, 16, 16);

在例子中,新的TiledLayer类有10行,10列。这些来自image的图像贴片大小是16*16像素。

有趣的部分还是用这些图像贴片来创建一幕场景。利用setCell()方法可以把一个图像贴片分配到一个数组元胞里。你需要提供这个数组元胞所在行列数以及图像贴片的编号。例如,你可以通过调用setCelll(2,1,5)方法把编号为5的图像贴片分配到第2行中的第3个数组元胞里。如果你觉得这些参数看起来不对,请注意,图像贴片编号是从1开始计数,而行和列的编号是从0开始的。参数缺省情况下,新的TiledLayer类对象中的所有数组元胞的图像贴片标号为0,这就意味着它们是空的。

 

下面的代码片断向你说明一种使用整数数组来填充TiledLayer类对象。在实际图像中,TiledLayer类可以从资源文件里定义,这就使得定义背景时可以有更多的灵活性,并能提供新的背景和级别来增强游戏的可玩性。

为了把这个TiledLayer类对象显示在屏幕上,你需要调用一个Graphics对象的paint()方法。

TiledLayer类还支持动画图像帖子,这样就使得通过一系列贴片来移动元胞集合很容易了。若想得到更详细的说明,参看TiledLayer类相关的API文档。

 

使用Sprite类实现人物动画

Game API函数里提供的另一个具体的Layer类是Sprite类。一方面,Sprite类是TileLayer类的概念化的逆转.TiledLayer类使用源图像贴片的调色板来创建一幅大场景,而Sprite类则使用一系列源图像帧来产生动画。

 

你创建一个Sprite类所需要的只是源图像和每个帧的尺寸。在TiledLayer类里,源图像被分为相同大小的图像贴片;在Sprite类里,子图像被称为帧。在下面的例子里,源图像tank.png用来创建帧大小为32*32像素的Sprite类对象。

源图像里面的每一帧都有一个编号,从0开始,以此累加。(在这里不要糊涂,记住图像贴片的编号才是从1开始的)Sprite类有一个帧序列,它决定了帧显示的顺序。一个新Sprite类对象的缺省帧序列简单地依照可用帧,从0开始累加。

使用Sprite类的nextFrame()方法和prevFrame()方法,可以把帧在帧序列中向前或向后移动。这些方法把帧序列的头尾连接起来了。例如,如果Sprite类对象已经把位于帧序列末尾的帧显示出来了,若在调用nextFrame()方法将会显示帧序列的头帧。

调用setFrameSequence()方法,可以通过整型数组所指定的序列来确定不同于缺省时的帧序列。

你还可以调用setFrame()方法跳至当前帧序列中的某一帧。你不能跳至特定的帧编号处,只能跳至帧序列的特定点。

利用从Layer类继承下来的paint()方法时,只有在Sprite类在下一个时间段内被表现的时候,帧的变化才真正实现。

Sprite类还可以变换源帧。可以把帧旋转90度,或做镜像变换,或两者皆有。在Sprite类里的常数枚举了这些可能性。Sprite类的当前变换方式可以通过向setTransform()方法传递这些常数之一进行设定。下面的例子是当前帧绕垂直中心做镜像变换,并旋转90度:

sprite.setTransform(Sprite.TRANS_MIRROR_ROT90);

应用了变换方式,从而使得Sprite类的参考像素并没有移动。缺省下,Sprite类的参考像素位于Sprite类坐标系里的(0,0)点处,即左上角。当应用了变换方式,参考像素的位置也变换了。Sprite类的位置被调整了,从而参考像素仍然在原位置上。

你可以通过调用defineReferencePixel()方法来改变参考像素点的位置。对于大多数类型的动画,你可以把参考像素点定义在sprite的中心上。

最后,Sprite类提供几个collidesWith()方法来检测与其他Sprites,ItledLayers,或Images类对象的碰撞。你可以使用检测矩形(快但粗糙)或者像素级别(慢但精确)来检测碰撞。这些方法的微妙不同是难以描述的;若详细资料,可参看API 文档。

MuTank例子

MuTank例子向你说明TiledLayer,Sprite和LayerManager类的用法。

最重要的类是包含大部分代码的MicroTankCanvas类和封装了坦克行为的MicroTankSprite类。

MicroTankSprite类制作了大量的变换方式。它使用了一个只含3帧的源图像来显示指向16种方向的坦克。Turn()和forward()两个公用方法使得坦克很容易控制。

MicroTankCanvas类是GameCanvas类的子类,它在run()方法里包含一个你应该很熟悉的动画循环体.Tick()方法用来检测坦克是否碰到隔板上了。如果碰到了,就调用MicroTankCanvas类的undo()方法使它最近一次的运动倒退。Input()方法简单地检测按键是否被按下,并同时调整坦克的方向或位置。Render()方法使用一个LayerManager类对象来对绘画进行处理。LayerManager类包含两个图层,坦克图层和隔板图层。

从游戏循环体中调用的Debug()方法,用来比较通过游戏循环体所用时间和期望的循环时间(80毫秒),并在屏幕上显示时间的百分比。它仅仅是用作调试诊断目的的,在游戏被发送给用户之前将会被删除。

游戏循环体的计时比前面的SimpleGameCanvas类更加复杂。为了更精确的每80毫秒就重复一次游戏循环体,MicroTankCanvas类对tick(),input()和render()方法所花费时间进行测量。然后停下来花费完80毫秒中的剩余时间,以使得通过每次循环所用的总共时间尽可能的接近于80毫秒。

 

总结

MIDP 2.0的Game API函数提供了一个简化二维动作游戏开发的构架。首先,GameCanvas提供了使得游戏循环体紧凑的绘画和输入方法。其次,图层的架构使得创建复杂的场景成为可能。TiledLayer从源图像簇的调色盘中组合了一个大背景或场景。Sprite适合于动画人物,并能检测到在游戏中与其他对象的碰撞。LayerManager把所有的图层粘合在一起。MuTank例子提供了一组基本的工作代码,用来说明Game API函数的使用。

 

译者附言:翻译的目的在于开阔视野,培养无线应用程序开发人员的兴趣和爱好,从而有于国内无线互联网的发展。译者希望这篇文章会给广大爱好者与开发者的学习和研发提供帮助。由于译者专业技术水平和英语水平有限,难免有不当之处,请各位朋友多多指教。原文出处http://wireless.java.sun.com/midp/articles/game/

使用Game API函数制作二维动作游戏(一)

使用Game API函数制作二维动作游戏 翻译者:阿麦  hua原作者:Jonathan Knudsen MIDP 2.0里面包括一个用来简化编写二维游戏的API函数。这个API函数是非常简凑的,只包...
  • GotoWireless
  • GotoWireless
  • 2003年06月06日 09:34
  • 540

用GameAPI函数制作二维动作游戏

MIDP 2.0里面包括一个用来简化编写二维游戏的API函数。这个API函数是非常简凑的,只包括javax.microedition.lcdui.game包里的五个类。这五个类主要提供了两个重要的功能...
  • garyye
  • garyye
  • 2009年08月10日 11:44
  • 289

[译]使用Game API创建2D动作游戏(二)

  • zgqtxwd
  • zgqtxwd
  • 2008年04月25日 19:49
  • 80

[译]使用Game API创建2D动作游戏(二)

(接上文) 游戏场景就像洋葱头 典型的2D动作游戏包括一个背景和一些活动的人物.尽管你可以自己来画这样的场景,但Game API能让你用layers 来创建场景. 你可以用一个layer来做城市的背景...
  • clapton
  • clapton
  • 2004年07月22日 11:03
  • 1646

jump game I // II

/* 贪心算法 jump game 给出一列数组,非负,数组每个元素表示可以跳跃的最大步数 第一个元素是初始化位置,编写一个函数判断是否成立(跳出数组) 分析: 对于数组A,共有n层,每次...
  • liuyang079
  • liuyang079
  • 2016年04月08日 16:30
  • 168

二三维联动开源框架:ol3-cesium

OL3-Cesium是OpenLayers和Cesium的集成库,使用openlayers3创建自己的地图,同时使用Cesium实现在地球上的三维可视化。...
  • xk_zhang
  • xk_zhang
  • 2016年07月24日 00:20
  • 4807

二维离散序列的奇偶性-以sobel算子为例

前言:该篇文章的内容是解释冈萨雷斯《数字图像处理》第三版中例4.10,目的是了解二维离散序列的奇偶性。...
  • u013698770
  • u013698770
  • 2015年07月16日 17:39
  • 768

Unreal Open Day 2017 参会总结——ACT(动作)游戏制作经验分享

国产游戏 失落之魂 (英文名 Lost Soul Aside ) 是由杨冰先生独自一人花费3年左右的时间开发的一款动作游戏,目前还处于并不完整的demo阶段。前不久杨冰先生在网上上传了一个宣传视频,网...
  • u012999985
  • u012999985
  • 2017年05月01日 17:06
  • 2993

利用meshgrid函数绘制二维高斯函数曲面

meshgrid函数用于根据给定的横纵坐标点生成坐标网格,以便计算二元函数的取值。 设二维高斯函数表达式为: 程序如下: u=[-10:0.1:10]; v=[-10:0.1:10]; ...
  • zhuoyue08
  • zhuoyue08
  • 2011年11月21日 00:59
  • 11383

cocos2d-x 如何制作一个类马里奥的横版平台动作游戏 1 献给所有对动作游戏有爱的朋友

大家一定很想知道超级马里奥,洛克人这样优秀的横版动作游戏是怎么制作的吧? 本文翻译自国外著名IOS源码教学商业网站raywenderlich 的IOS Game Start Kits三件套之一的Pl...
  • qiou2719
  • qiou2719
  • 2015年01月04日 17:22
  • 2066
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Game API函数制作二维动作游戏(二)
举报原因:
原因补充:

(最多只允许输入30个字)