Lib9开发指南
本文的主要目的是介绍如何使用Lib9引擎,几乎覆盖了Lib9应用开发方面的所有概念,方便使用者全面了解Lib9,特别是要知道Lib9的核心思想:程序就是一个状态机,程序的每一部分就是一个状态,这些不同的状态相互协作就组成了完整的应用程序,使用Lib9开发应用,特别是游戏是这么简单的事情
1:应用程序基础
l 程序结构:状态机
Lib9程序就是一个地地道道的j2me程序,只是Lib9程序使用了自己特有的方式来组织程序:状态机,也就是说Lib9程序就是一个状态机,程序的每个部分就是一个状态,程序的运行始终处于某一个状态中,所以说编写Lib9程序其实就是具体实现程序的每个状态!
l 帧驱动方式
程序的驱动方式往往有两种,开发应用常常采用事件驱动的方式,比如:用户点击鼠标那么就发生了OnClick事件,那么在OnClick事件中就可以加入相应的事件处理代码来进行处理,还有一种帧驱动的方式,这种方式经常在游戏开发中被采用,而Lib9也采用了这种驱动方式,所谓帧驱动就是每秒钟更新(更新逻辑和画面)的次数,也称为fps,lib9程序是否运行流畅就是由fps来决定的,默认fps为15
l 关键类
Lib9
Lib9作为该引擎中最重要的类,它负责了程序的主线程,提供了按键系统的支持,以及为每个状态(程序的部件)的运行提供了场所,充当了状态机的角色等基础性的工作,在具体使用Lib9的时候,继承Lib9的类往往也实现L9IState接口称为一个状态,这个状态往往就是程序的入口状态,或者称之为起始状态,请看下面的代码(摘自示例Demo(ChangeState)):
public class L9ChangeState extends Lib9 implements L9IState {
public L9ChangeState(MIDlet app) {
//初始化Lib9引擎
super(app);
//将自己作为程序的入口状态
changeState(this);
}
}
从以上代码可看出L9ChangeState本身实现了L9IState接口,表示也是一个状态,同时在构造函数中调用了changeState(this)语句将自己作为了程序的入口状态,Lib9程序往往按照上面的模式来使用,具体请参考示例Demo(ChangeState)
L9IState
State作为Lib9整个状态机中里一个具体的状态,比如:菜单状态给用户提供了选择菜单项的功能,对话框状态用来显示一个对话框等,Lib9通过提供一个接口L9IState来表示状态,用户在使用时只要实现了所有的接口方法也就具体的变成了一个状态类了,以下是L9IState接口的定义
/**
* 负责状态的初始化
*/
public abstract void Init();
/**
* 负责状态的逻辑或AI
*/
public abstract void Update();
/**
* 负责状态的画面绘制
*/
public abstract void Paint();
从接口的定义来看,一共包括三个方法,也就是Init、Update和Paint,这个就是Lib9中IUP架构,在Init方法中执行初始化工作,Update方法中执行程序逻辑或AI,在Paint方法中绘制程序画面,在这里,其实作者最开始在定义状态IUP的时候一直很犹豫,到底使用抽象类呢还是接口,两者各有利弊,采用抽象类可以预先实现一些功能,比如:防止多次初始化,在使用中也常常需要用到这个功能,但是如果采用抽象类的话,因为单继承的原因势必会阻碍具体状态的编写,犹豫来犹豫去最后还是决定使用接口的方式来提供定义,这样用户在使用的时候还可以通过继承的方式在已经定义好的状态上扩展或修改,这样更加丰富状态代码的编写,最后在具体使用Lib9的案例中证实了使用接口的方式优于使用抽象类
2:数据存储
l 本地存储
在典型的桌面应用程序中,操作系统往往通过提供了文件系统来支持应用的存储数据,而Lib9由于是基于Java的,所以没有这个特权,但是在J2me中却提供了Rms来支持本地的存储,Lib9中通过L9Store类来提供了对数据的存储功能,L9Store让数据的存储和读取变得更加简单,存储数据就向普通的流操作一样
//创建一个存储,存储模式为写
L9Store store = new L9Store("_dbstore", L9Store.K_Store_Mode_Write);
//存储布尔类型
store.writeBoolean(true);
//存储整形
store.writeInt(45);
//存储字符串
store.writeString("测试L9Store联网写存储");
//存储结束后别忘记了保存
store.Save();
读取存储和写入存储一样简单,按照写入的顺序依次进行就可以了,只是在创建读取存储的时候需要让模式修改为“存储读模式”
//创建一个存储,存储模式为读
L9Store store = new L9Store("_dbstore", L9Store.K_Store_Mode_Read);
l 联网存储
随着网络的日益普及,现在的应用往往都是联网的,很多应用往往是通过网络来存储和读取数据,而L9Store同样对此提供了支持,和本地存储的操作方法完全一样,需要注意的是在创建存储的时候选择联网的读或写模式,当然了,因为联网是阻塞式操作,在L9Store内部开启了新线程来进行处理,联网的写存储还可以在后台进行而不用管它,而读操作在读之前需要调用isReady()方法来判断数据是否已经准备好了,只有准备好了的数据才可以进行读取
/*注意这里还应该判断l9Store是否为空,因为联网操作是阻塞操作开启了新线程,所以虽然在init中new了,但是并不一定就实际返回了该对象*/
if (store != null && store.isReady()) {
boolean bSave = store.readBoolean();
if (bSave) {
//默认将使用utf-8编码
String name = store.readString();
String score = "分数:" + store.readInt();
}
}
3:联网
L9Http类实现了Lib9引擎对联网的支持,L9Http采用了是http方式进行联网,通过post方法传递数据,在L9Http类内部采用了线程的方式来处理(因为联网是阻塞式操作),在联网的另外一端则是一个用来处理post数据的动态网页(比如:asp.net、jsp、php等),具体的使用请参考示例程序Http
提示:
L9Store联网存储在内部也是使用的L9Http来实现的
4:L9Sprite精灵
Lib9通过L9Sprite实现了模块、帧、动画的显示与播放、同时还提供了对地图的支持(通过Lib9Eidtor 编辑工具的配合)
l 多张图片多套调色板
模块可以从多张图片、每张图片可以有多套调色板中来提供,同时在组成帧的模块还可以进行一些X翻转、Y翻转、旋转90度的处理
l 帧中嵌套帧
组成帧的模块除了可以通过X翻转、Y翻转、旋转90度的处理外,还支持调色板使得帧的表现更加丰富多彩,另外在帧中也可以重复的嵌套帧,这样在编辑新帧的时候可以利用已经编辑好的帧以减少重复劳动
l 动画
编辑好的帧通过一定的顺序就可以组合成动画了,组成动画的帧可以通过设置帧的time属性来达到重复播放帧的目的,这样就不用重复添加多帧
l 地图
L9Sprite可以为L9Map对象提供地图数据,地图往往由2部分组成:地图背景和地图对象
地图背景:地图背景其实就是帧,只是这些帧的模块大小固定,然后按照一定的顺序排列起来就构成了地图背景,构成地图帧的模块在游戏中常常称为tile,地图背景称为tileset
地图对象:在地图上可以放置任何的模块、帧、动画等,这些地图对象可以分层次进行绘制,每个对象都一个z属性,z越大表示越显示在上面
5:如何开发和使用组件
一个Lib9应用实际上就是一个状态机,在运行中应用始终处于某个状态中,所以为Lib9开发第三方组件实际上就是开发具体的一个状态,具体操作方法是实现L9IState接口的3个方法,关于如何开发组件,请参考示例Demo(List),这个Demo主要是演示了如何开发一个列表组件,功能就是以列表的方式显示字符串数组,用户可以上下移动,按5键选择所选项并返回上一个状态,在上一个状态可通过getListIndex方法得到用户所选择的项,使用示例请参考如下代码:
if (isKeyPressed(K_KEY_NUM5 | K_KEY_FIRE)) {
pushState();//将现在的程序状态入栈
list = new ListState(this);
list.setList("示例列表", new String[] {
"第一个示例", "显示图片和播放动画", "如何使用图片字体"
}, 180, 200);
//设置列表项的默认选择项
list.setListIndex(0);
//将状态切换到列表组件
changeState(list);
return;
}
以上代码摘自示例Demo(List),具体了解请参考示例Demo(List)
Note:在使用组件的时候记得不要让其先将当前状态入栈(调用pushState方法),防止从组件中返回时状态悬空了!
6:Lib9Editor编辑器
在使用资源的应用中,怎么来组织资源特别是图片和地图资源,常常需要用到编辑器来处理,而Lib9Editor就是Lib9配套的编辑器,L9Sprite有多强的功能那么Lib9Editor编辑器就有多强大,要想用好Lib9,而不熟悉Lib9Editor那是不可能的
7:示例Demo
上面讲述了在使用Lib9时所涉及到的一些概念和使用方法,但是再多的言语也不如实际的例子来得实在,所以Lib9特别的准备了一些示例Demo,每个Demo都是独立的可运行程序,在Demo代码中也带有详细的注释以帮助读者熟悉Lib9的使用,所有示例Demo都可以在网站http://www.lib9.net中下载到,其中要特别是注意ChangeState示例
l FirstDemo
这个作为Lib9的第一个例子,功能很简单,就是显示一个消息对话框,功能简单,程序代码也简单
l ImageAndAnimation
这个例子主要是说明在Lib9中如何显示图片和播放动画,例子中带有“宠物主角.edt”资源文件,通过Lib9Editor编辑器打开资源文件后再“文件”–》“导出”就可以生成示例代码中使用的资源了
l ImageFont
这个例子的目的在于展示如何使用图片字体,在游戏中为了画面的美观常常需要使用图片字体,这个也算是ImageAndAnimation示例的一个衍生的例子吧
l Map
在游戏、特别是RPG游戏中常常需要用到地图,而Lib9通过L9Map则提供了对地图的支持
l MultiLang
现在越来越全球化的今天,现在的应用当然也要跟着发展的步伐哦,所以也免不了要制作多语言,这个就是介绍如何使用多语言的一个示例
l Http
网络现在越来越发达,现在的应用已经很少不使用网络的了,而这个例子就是介绍怎么在Lib9中使用网络的(其实在关于数据存储的L9Store类中的联网存储也用到了网络)
l List(开发第三方组件)
这个例子是讲述如何开发第三方组件的,在Lib9中第三方组件也是一个具体的状态,和程序本身部分的状态是一样的,这要归功于Lib9特殊的架构,使得开发程序的状态和开发第三组件变成了一样的事情了,通过大量的第三方组件就使得Lib9程序的开发变得更加的简单,而开发的应用又可以很强大,由于在Lib9中开发组件是这么的简单,我们可以幻想到某个时候,如果第三方组件足够的多,那么Lib9程序就可以只需要简单的组装就可以完成了,那是多么美妙的事情哦,O(∩_∩)O~
l ChangeState(状态切换)
前面的Demo为了教学的目的,都非常简单,而这个示例的目的就是讲解如何通过多个状态来组装应用程序,真实的应用程序往往肯定不止一个状态,所以这个例子显得非常重要
8:Lib9其余部分
关于Lib9引擎不是简单的一篇开发指南就能够全部讲述完的,很多的还需要在实践中慢慢的发现和总结,而作者觉得还有一些比较重要的东西也要告诉大家,那就是下面的几个类
l L9Datetime
这个主要是关于处理日期时间的,比如:关于两个日期之间的差,可以根据需要来取得差的年、月、天数、小时数、分钟数等
l L9Str
有关字符串的处理,比如:字符串的替换、分隔、分行、分页页、绘制方式等,其中在图片字体的示例中就演示了如何绘制图片字体
l L9Util
这个类包含有一些常用的工具方法,比如:压缩与解压、字节数组的合并与分隔、按照需要取随机数等
好了,到此Lib9开发指南就基本介绍完了,更多关于Lib9的请登录Lib9官方网站 http://www.lib9.net