Presentation is loading. Please wait.

Presentation is loading. Please wait.

移动应用开发技能.

Similar presentations


Presentation on theme: "移动应用开发技能."— Presentation transcript:

1 移动应用开发技能

2 背景介绍 1、用于应用开发的两大技术体系: (1)基于Sun公司领导的Java体系; (2)基于Microsoft公司领导的.NET体系;
(1)J2SE:开发桌面应用程序和Applet; (2)J2EE:开发基于Web的应用程序; (3)J2ME:开发无线应用程序; IE …… J2SE J2ME

3 课程目标 通过案例教学实现如下两个项目: 通过案例剖析,学习能够自行开发J2ME应用! 移动公交车查询系统 手机游戏-迷失森林 高级UI
高级事件处理 移动设备访问网络 查询算法 手机游戏-迷失森林 低级UI 低级事件处理 游戏中的人工智能 RMS记录管理系统 通过案例剖析,学习能够自行开发J2ME应用! 1-1

4 第一讲 J2ME概述 学习目标: 重点和难点: 了解J2ME的发展历史 了解J2ME与J2EE和J2SE的联系和区别 理解J2ME的体系结构
掌握KVM 掌握CLDC和CDC,以及它们之间的联系和区别 理解MIDP 掌握J2ME的开发环境 重点和难点: J2ME的体系结构 1-2

5 J2ME的发展历史 Sun Microsystems 将 J2ME 定义为“一种以广泛的消费性产品为目标的高度优化的 Java 运行时环境,包括寻呼机、移动电话、可视电话、数字机顶盒和汽车导航系统”。 Sun公司与业界领先厂商Motorola、Nokia、Nextel、Openwave、Siemens和Symbian等结成联盟,推出一个新的Java无线开发商倡议。 全球许多电信运营商,如Cingular Interactive、Far EasTone、J-Phone、KDDI、Omnitel、One2One、SmarTone、Sprint PCS、Telefonica和Vodafone等,都将配置或试用基于Java技术的服务与器件。 1-3

6 J2ME、J2EE、J2SE的比较 J2SE (The JavaTM 2 Platform, Standard Edition)
J2EE (The JavaTM 2 Platform,Enterprise Edition) 是目前比较流行的多层企业应用技术。 J2ME (The JavaTM 2 Platform,Micro Edition) 是当前使用比较多的基于移动设备开发技术。 1-4

7 J2ME、J2EE、J2SE的比较 1-5

8 J2ME的体系结构 J2ME应用程序的体系结构主要分为四个部分:操作系统、Java虚拟机、CLDC/CDC和MIDP应用程序。 1-6

9 KVM虚拟机 KVM的名字反映了这些设备的存储量是以千比特倍数来度量的。KVM虚拟机适用于拥有16/32比特的RISC/CISC微处理器或控制器,总的存储器只有160K左右,其中128k用来存放虚拟机和各种库的设备。 KVM不支持以下的功能: 不支持浮点数; 不支持线程组(Thread Groups)和守护线程(Daemon Threads); 不支持映射(Reflection); 有限的错误处理机制。 1-7

10 CLDC/CDC CLDC(Connected Limited Device Configuration)有限连接设备配置为低端消费电子产品的运行提供了最小的库集和APIs,它是所有低端消费电子产品必须支持的。因此这些APIs在所有的设备上都是可以运行的。CDC(Connected Device Configuration)连接设备配置是CLDC的超集,它包含CLDC中的所有APIs,同时它还有自己APIs,它为高端的消费电子产品提供运行环境。 CLDC中包含: java.io. java.lang java.util javax.microedition.io 1-8

11 MIDP 在CLDC中,没有用户界面的包,因为在CLDC中不包含具体设备的信息,而不同的设备就要设计不同的简档来满足这些设备的要求。其中MIDP就是一种最常见的简档。MIDP构架与CLDC之上,它具有以下特征: 最小屏幕尺寸为96×54象素; 显示深度为1bit; 128KB不变内存用于MIDP组件; 8KB不变内存用于持久数据存储; 32KB可变内存用于运行时虚拟机。 在MIDP中定义一些APIs,包含: javax.microedition.lcdui; javax.microedtion.midlet; javax.microedition.rms。 1-9

12 J2ME中不同简档之间的比较 目前有两种比较流行的简档,一种就是本文介绍的MIDP,一种是KJava,这两种简档各有优点。MIDP不依赖任何设备生产厂商,它是一种普遍的工业标准,基于MIDP简档开发的程序可以在任何设备上运行。KJava中的APIs主要是Sun公司特别制定的,KJava主要运行在Palm OS上,KJava有点象J2SE中的AWT,它并不是J2ME中的标准包,并且它的主包是com.sun.kjava。 1-10

13 安装开发环境 在进行J2ME程序需要开发的时候,使用的开发工具分为两类: 软件部分 硬件部分 通用开发工具——适合所有手机的通用工具;
专用开发工具——适合某种型号的手机的开发工具,例如Nokia。 软件部分 Microsoft Windows XP jakarta-tomcat exe j2sdk1.4.2_08-win.exe j2me_wireless_toolkit-2_1.exe 硬件部分 1G硬盘空间(推荐3G以上) 128M内存(推荐256M以上) PIII CPU(推荐PIV) 1-11

14 HelloWorld程序 创建 运行 1-12

15 小结 首先介绍了J2ME的历史,并它与J2EE和J2SE进行比较。本章重点讲述的是J2ME的体系结构,它包含KVM、CLDC/CDC和MIDP三部分。由于J2ME开发的是移动设备终端,它们的CPU和内存都受到一定的限制,因此KVM的功能也没有JVM强大,它是JVM的子集。CLDC是Sun公司推出的所有厂商都要遵循的APIs,MIDP是很多移动设备厂商共同制定的APIs,使得在遵循CLDC和MIDP规范的应用程序都能够在这些厂商的移动设备上运行,提高了可移植性。 1-13

16 复习题 J2ME的定位 J2ME的体系结构 CLDC中的包 MIDP中的包 2-1

17 第二讲 MIDP生命周期 学习目标: 重点和难点 掌握如何建立MIDlet应用程序 理解MIDlet包 掌握MIDlet生命周期
2-2

18 MIDlet概述 MIDlet简介 移动信息设备简表 (MIDP) 适合类似于蜂窝电话和寻呼机这样的设备。MIDP,就象 KJava一样,同样也建立在 CLDC 之上。MIDP简表提供一种标准的运行时环境,允许在终端用户设备上动态地配置新的应用程序和服务。 MIDlet是一个Java类,它扩展了javax.microedition-.midlet.MIDlet抽象类。实现startApp()、pauseApp()和destroyApp()方法,这三个方法构成了MIDlet应用程序的生命周期。 复习抽象类相关知识。 2-3

19 建立MIDlet应用程序 步骤1:选择“KToolbar”,进入开发环境。 步骤2:建立工程。 步骤3:设置配置。 步骤4:添加代码。
src:保存MIDlet 和所有共享类的源代码。 res:保存MIDlet 所需的所有资源,如图标。 lib:保存对应MIDlet 所需的第三方库的JAR 或ZIP 文件。 bin:保存JAR、JAD 和清单文件。 2-4

20 HelloWorld程序 import javax.microedition.midlet.*;
import javax.microedition.lcdui.*; public class HelloWorld extends MIDlet implements CommandListener { private Command exitCMD = null; private Display dis = null; private TextBox textBox = null; public HelloWorld() { exitCMD = new Command("退出", Command.EXIT, 2); textBox = new TextBox(null,"HelloWorld!",256,0); textBox.addCommand( exitCMD ); textBox.setCommandListener( this ); } 2-5

21 HelloWorld程序 dis = Display.getDisplay( this );
public void startApp() { dis = Display.getDisplay( this ); dis.setCurrent( textBox ); } public void pauseApp() { public void destroyApp( boolean bool ) { public void commandAction( Command cmd, Displayable dis ) { if ( cmd == exitCMD ) { destroyApp( false ); notifyDestroyed(); 2-6

22 MIDlet生命周期 暂停状态(Paused)
当MIDlet应用程序处在初始化时或者处在静止状态时,MIDlet处在暂停状态。处在暂停状态的MIDlet不会占用或者使用任何共享资源。在以下情况时会出现暂停状态: 加载MIDlet 时,最初是处于暂停状态,这是程序通过默认的构造方法来调用。此时如果程序抛出异常,MIDlet将会有暂停状态马上转入销毁状态,销毁应用程序; 当应用程序在活动状态时成功调用pauseApp()方法时,MIDlet将会有运行状态马上转入暂停状态; 2-7

23 MIDlet生命周期 运行状态(Active)
当应用程序在活动状态时成功调用notifyPaused()方法时,MIDlet将会有运行状态马上转入暂停状态; 当应用程序在活动状态时,出现MidletStateChangeException异常时,MIDlet将会有运行状态马上转入暂停状态。 运行状态(Active) 当程序成功的调用startApp()方法时,程序将会进入运行状态。startApp()方法可以正常结束,在这种情况下,可能允许MIDlet 运行,也可能会通知MIDP 平台MIDlet 不希望此时运行。为实现后者,有如下几种方法: 2-8

24 MIDlet生命周期 如果startApp()方法检测到一个使之终止执行的错误条件,但是它以后可能不再出现(即一个临时错误条件),则需要抛出一个MIDletStateChangeException异常。这将把MIDlet 移回至暂停状态,从而在以后可以再来启动; 如果startApp()方法检测到一个错误条件,而且不可能恢复(即非临时错误条件),它应当调用其notifyDestroyed()方法; 最后,MIDlet可能会抛出MIDletStateChangeExcep- tion以外的某个异常,可能是故意为之, 也可能是由于它调用的某个方法抛出了此异常, 而且startApp()方法未捕获到此异常。在这种情况下,则假定出现了一个严重错误,通过调用destroyApp()方法来销毁此MIDlet。 2-9

25 MIDlet生命周期 销毁状态(Destroyed)
当MIDlet调用了destroyedApp(false)方法或者MIDlet抛出MIDletStateChangeException异常时,MIDlet将会释放所有资源; 当MIDlet成功调用了notifyDestroyed()方法时。 2-10

26 MIDlet生命周期 2-11

27 MIDlet生命周期 notifyDestroyed()方法
notifyDestroyed()方法来通知MIDP平台该MIDlet 希望终止 。 当MIDlet 由平台销毁时,MIDlet 的destroyApp()方法随即得到调用,且参数为true,此方法完成后MIDlet 即被销毁。在这种情况下,MIDlet 没有必要调用其notifyDestroyed()方法。 若MIDlet 自己想终止,用户按下了退出按钮。这可以通过调用其notifyPaused ()方法实现。在这种情况下,平台并不调用MIDlet的destroyApp()方法。在调用notifyDestroyed()之前,大多数MIDlet会调用自己的destroyApp()方法来完成通常的整理工作。 注意:MIDlet不能通过调用System 或Runtime的exit()方法来终止。 2-12

28 MIDlet生命周期 notifyPaused()方法 resumeRequest()方法
通知平台MIDlet 希望转至暂停状态; MIDlet通常在调用notifyPaused()前会先调用pauseApp()。 resumeRequest()方法 作用正好与notifyPaused()相反;它通知平台:一个处于暂停状态的MIDlet 希望返回到活动状态。将来某个时候,平台可以通过调用其startApp()方法来重新启动此MIDlet。resumeRequest()方法通常由一个后台线程调用,或者由一个定时器调用,此定时器在MIDlet 暂停时仍处于活动状态。 2-13

29 MIDlet生命周期 2-14

30 MIDlet应用程序的框架 import javax.microedition.midlet.*;
class XXX extends MIDlet { 初始化模块; MIDlet生命周期的实现; 其他方法; 事件处理; } startApp() pauseApp() destroyApp( boolean b ) 2-15

31 小结 MIDlet包 生命周期 MIDlet应用程序的框架 2-16

32 复习题 MIDlet包 建立MIDlet应用程序 MIDlet应用程序的生命周期 生命周期中的主要方法 生命周期的转换图 2-17

33 第三讲 MIDlet套件 学习目标: 重点和难点 掌握如何建立清单文件 掌握如何获取清单文件的MIDlet属性
2-18

34 生命周期案例 import javax.microedition.midlet.*;
import javax.microedition.lcdui.*; /** * 正确使用startApp, pauseApp, and destroyApp等方法 */ public class LifeCircle extends MIDlet implementsRunnable,CommandListener { Thread thread = null; // 定义一个线程 private Command exitCMD = null; //定义销毁按钮 private Display dis = null; private TextBox textBox = null; private Command pauseCMD = null; //定义暂停按钮 private Command resumeCMD = null; //定义恢复按钮 2-19

35 生命周期案例 /** * 构造方法,初始化. */ public LifeCircle () {
exitCMD = new Command("退出", Command.EXIT, 2); pauseCMD = new Command("暂停", Command.EXIT, 2); resumeCMD = new Command("恢复", Command.EXIT, 2); textBox = new TextBox(null,"",256,0); textBox.addCommand( exitCMD ); textBox.addCommand( pauseCMD ); textBox.addCommand( resumeCMD ); textBox.setCommandListener( this ); } 2-20

36 生命周期案例 public void startApp() { dis = Display.getDisplay( this );
// 调用startApp()方法,显示TextBox组件,启动线程 public void startApp() { dis = Display.getDisplay( this ); dis.setCurrent( textBox ); thread = new Thread(this); thread.start(); } /**暂停线程 */ public void pauseApp() { thread = null; /** 销毁线程 */ public void destroyApp(boolean unconditional) { 2-21

37 生命周期案例 public void run() { //得到当前的线程
// 运行线程,在TextBox组件上显示1至9999数字。 public void run() { //得到当前的线程 Thread curr = Thread.currentThread(); long start = System.currentTimeMillis(); for (int i = 0; i < && thread == curr; i++) { textBox.setString(i+ " "); } // 当运行10000次后,线程自动停止 if (thread != curr) { return; // 销毁 destroyApp(true); notifyDestroyed(); 2-22

38 生命周期案例 if ( cmd == exitCMD ) { //触发销毁按钮事件 destroyApp( false );
public void commandAction( Command cmd, Displayable dis ) { if ( cmd == exitCMD ) { //触发销毁按钮事件 destroyApp( false ); notifyDestroyed(); } else if ( cmd == pauseCMD ) { //触发销暂停钮事件 pauseApp(); else if ( cmd == resumeCMD ) { //触发恢复按钮事件 resumeRequest(); startApp(); 2-23

39 MIDlet套件 在MIDlet套件中,应该包含以下文件: 无论清单文件还是JAD 文件都是简单的文本文件,每行的形式为:
用于运行应用程序的JAR文件; 用于描述JAR文件的清单文件(MANIFEST.MF); Java 应用描述文件(Java application descriptor,简写为JAD 文件)。 无论清单文件还是JAD 文件都是简单的文本文件,每行的形式为: 属性名: 属性值 名和值之间由一个冒号和一个可选的空格分开。与MIDlet安装相关的所有属性名都冠以前缀“MIDlet-”。 2-24

40 MANIFEST.MF MIDlet-1: LifeCircle, LifeCircle.png, LifeCircle
MIDlet-Name: LifeCircle MIDlet-Vendor: Unknown MIDlet-Version: 1.0 MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-2.0 2-25

41 JAD 文件 MIDlet-1: LifeCircle, LifeCircle.png, LifeCircle
MIDlet-Jar-Size: 1633 MIDlet-Jar-URL: LifeCircle.jar MIDlet-Name: LifeCircle MIDlet-Vendor: Unknown MIDlet-Version: 1.0 MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-2.0 2-26

42 JAD和JAR文件的关系 2-27

43 将多个MIDlet放在一个套件中 将MIDlet应用程序导入手机中 将多个MIDlet放在一个套件中 2-28

44 小结 生命周期案例 MIDlet套件 打包并将应用程序导入到手机中 2-29

45 复习题 生命周期 MIDlet套件 Jad和Jar之间的关系 导入手机 3-1

46 第四讲 移动公交车查询系统设计 学习目标: 重点和难点 掌握构建基于J2ME的移动电子商务平台 了解项目的需求分析 了解项目的概要设计
了解GPRS的工作原理 了解Servlet的工作原理 重点和难点 构建基于J2ME的移动电子商务平台 3-2

47 项目来源 深大160? 造价高 不方便 技术成熟度 J2ME的出现 GPRS JAVA手机的普及 用户群 公司职员与大学生 3-3

48 项目功能需求 服务器端(Servlet) 客户端(J2ME) 数据库 支持多个用户访问 一次查询 二次查询
输入简单:城市、当前站点、目的站点 数据库 要求不高 Access 3-4

49 技术支持 J2ME GPRS Servlet Java技术特性 移动设备
GPRS是通用分组无线业务(General Packet Radio Service)的英文简称,是一种基于GSM系统的无线分组交换技术,提供端到端的、广域的无线IP连接。 Servlet Servlet是服务器端语言,它的优点是自动开启多个线程接受多个用户访问。 3-5

50 产品定位 用户市场 行业市场 地域市场 主要针对于公交路线的查询。若经修改,则可用于查询相关资料(天气预报、通信、或金融服务业等)。
适用于各行各业,例如:金融服务业、通信、政府、天气预报、教育等。 地域市场 此服务不仅在国内可以使用,只要有GPRS网络,都可以使用。 3-6

51 移动电子商务平台的架构 技术背景 J2EE (The Java 2 Platform,Enterprise Edition)是目前比较流行的多层企业应用技术。它的优点之一是能够适应不同类型的客户端,如Web浏览器、Java Applets和Java应用程序,这些客户端能够很容易地部署在笔记本电脑、台式电脑和工作站上,实现跨平台。 J2ME 移动电子商务(Mobile Commerce,M-Commerce)是电子商务在移动网络中的应用,但是M-Commerce提供了比E-Commerce更灵活、更方便、更及时的信息服务。 3-7

52 移动电子商务平台的架构 网络访问模式 WAP模式 :WAP (Wireless Application Protocol,无线应用协议)是使移动通讯设备可靠地接入互联网的国际认可标准之一。局限性:一方面是WAP设备受到CPU、RAM、ROM和处理速度的限制,只能处理有限的数据输入;另一方面,WAP承载网络是低功率的网络,带宽小于10kbit/s。 3-8

53 移动电子商务平台的架构 i-Mode(Information Mode)模式:是由日本电报电话公司(NTT)和移动通信公司DoCoMo公司于1999年2月,推出的移动互联网技术,这种技术使得用户能够通过蜂窝电话使用Internet服务。i-mode的带宽为9600/bps,同时也具有可靠性不高、稳定性不高和不可预测性等局限性。 GPRS和3G网络:具有较高的数据传送能力,Java机制和优化的HTTPS和KSSL技术保障了数据在网络上的安全性,同时,它提供直接访问网络的能力,而WAP和i-Mode模式必须要通过网关(Gateway)才能访问网络。 3-9

54 移动电子商务平台的架构 3-10

55 移动电子商务平台的架构 3-11

56 概要设计 一次查询 车次 二次查询 车次-中转站-车次 三次查询 车次-中转站-车次-中转站-车次 查询失败 对不起,查无记录 3-12

57 概要设计 3-13

58 小结 构建基于J2ME的移动电子商务平台 项目的需求分析 项目的概要设计 GPRS的工作原理 3-14

59 复习题 基于J2ME的移动电子商务平台的架构 GPRS与WAP和i-Mode的优势 需求分析 概要设计 3-15

60 第五讲 MIDlet用户界面 学习目标: 重点和难点: 掌握MIDP中用户界面的体系结构 了解LCDUI包
理解Display类和Displayable类 重点和难点: MIDP中用户界面的体系结构 Display类和Displayable类之间的关系 3-16

61 用户界面(UI)的体系结构 电视、电影等 UI: User Interface LCDUI包 一种通过组件来显示,如:输入短信
一种直接接收键盘按键,如:游戏中的上下左右键 LCDUI包 高级用户界面--Screen类 低级用户界面--Canvas类 3-17

62 用户界面(UI)的体系结构 3-18

63 Display类和Displayable类
在用户界面中,Display提供在移动设备上显示组件的功能,在每个MIDlet应用程序中只有一个Display实例,必须通过Display.getDisplay(MIDlet)方法来获得Display实例,MIDlet获得Display实例后,它将一直占有,直到MIDlet调用destroyApp(boolean)方法。 Displayable类 Displayable类的下面有Screen和Canvas两个类,Screen代表的是高级用户界面,而Canvas代表的是低级用户界面。为了查明设备上当前显示的内容,使用getCurrent()方法。 3-19

64 Display类和Displayable类
import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.*; public class DisplayMidlet extends MIDlet { private Display display; public void startApp() { display = Display.getDisplay(this); ... display.setCurrent(aForm); } 3-20

65 Screen类 Screen类是所有高级APIs的超类 每个Screen都拥有两个附加特性:标题和滚动条(Ticker)。
预定义好的组件:TextBox、List和Alert。这类组件不可以放置其他类型的组件,只能作为原子组件使用。 容器组件:Form。这类组件可以在其中添加文本、图形组件或其他相关的图形组件,如:Item项目组件。 每个Screen都拥有两个附加特性:标题和滚动条(Ticker)。 3-21

66 Screen类 滚动条 标题 3-22

67 创建Screen应用程序 创建Screen应用程序 步骤1:导入包。 步骤2:继承MIDlet,并且实现事件处理接口。
步骤3:声明、定义类和属性。 步骤4:创建构造方法。 步骤5:实现startApp()方法。 步骤6:实现pauseApp()方法和destroyApp()方法。 步骤7:实现事件处理方法commandAction( Command cmd,Displayable dis )。 3-23

68 小结 MIDP中用户界面的体系结构 LCDUI包 Display类和Displayable类 建立应用程序的步骤 3-24

69 复习题 MIDP中用户界面的体系结构 LCDUI包 Display类和Displayable类 建立应用程序的步骤 3-25

70 第六讲 用户界面(1) 学习目标: 重点和难点: 移动查询系统用户界面概述 工程中所使用的类 Form类 Item类 TextField类
第六讲 用户界面(1) 学习目标: 移动查询系统用户界面概述 工程中所使用的类 Form类 Item类 TextField类 重点和难点: 3-26

71 移动查询系统用户界面概述 在移动设备终端,由于资源等环境的限制,尽量要减少使用对象的个数。同时,为了客户能够方便快捷的操作,也需要客户端的设计要尽量的简化和傻瓜化。基于以上两点因素的考虑,在移动公交车查询系统的客户端,系统分别使用了Form类、TextField类、Alert类、Ticker类和Image类。其中Form对象中放置三个TextField对象,分别用于在客户端中的文本框中输入城市、当前站点与目标站点。Alert对象用于描述软件的版权信息。Ticker对象用于显示提示信息。Image对象负责产生png文件,并在屏幕上显示。 3-27

72 Form类 Form对象是一种可以容纳任意项目(item)组合的屏幕,包括只读和可编辑文本字段、图像、日期字段、指示器(gauge)和选项组。Item 类的任何子类都可以放到Form对象里面。Form 对象不使用布局管理器。相反,Form对象以非常类似于列表的方式组织自己的组件,通常是从上到下显示组件。 3-28

73 Item类 所有可以放到Form或Alert中的组件都是Item抽象类的子类。 3-29

74 TextField类 TextField对象是一种可以放入Form的可编辑文本组件,可以使用TextField 对象接收用户的输入。但是TextField有容量限制,容量就是对象可以存储的字符数量,可以使用getMaxSize()方法取得MIDP 实现设置的最大容量。 3-30

75 小结 移动查询系统用户界面概述 工程中所使用的类 Form类 Item类 TextField类 3-31

76 复习题 设计手机用户界面应该注意的几点问题 Form类的作用 如何在Form对象上添加组件 TextField类的作用 3-32

77 第七讲 用户界面(2) 学习目标: Image类和ImageItem类 异常处理 Alert类 重点和难点 ImageItem类 3-33

78 Image类 Image类是一种图形图像数据容器,图形文件使用的是可移植网络图形(Portable Network Graphics,简写png)。当然,png文件并不是唯一的一种图片格式,还可以是jpg和gif文件格式,但是MIDP是支持具有动画效果的图形文件。根据创建的方式,Image可以是不变的,也可以是可变的。创建不变图像时,一般都是从资源包、文件或网络中载入的,固定图像在创建之后不能再修改,放在Alert、Form或ImageItem 中的图像必须是固定的。可变图像在内存中创建,并且可以被修改。在Wireless Toolkits中,图像的位置位于res中,并且在创建图像时,要在图像名前加上一个“/”,例如: Image anImage = Image.createImage("/welcome.png"); 3-34

79 项目应用 anImage 3-35

80 创建一个图像 //声明一个图片 private Image anImage; …… try {
anImage = Image.createImage("/welcome.png"); } catch( IOException ioe ) { ioe.printStackTrace(); 3-36

81 ImageItem类 在使用Image类时,图像的位置不能够人为的进行制定,为了能够制定图像的位置,在MIDP中提供了ImageItem类。ImageItem类是一个图像布局管理器,可以控制图像放置的方位,例如:前方、左方、右方、中间和后方等。描述这些方位的是ImageItem类的静态属性 。 Public ImageItem ( String label,Image img, int layout, String altText ) 该构造方法使用指定的标签、图像、布局指示符和替换用的文本字符串创建新的固定ImageItem对象。如果显示器不能显示图像,就在放图像的位置显示altText参数指定的字符串,layout 参数是ImageItem类静态属性的组合。 3-37

82 创建一个图像布局管理器 private Image anImage; //声明一个图片布局管理器
private ImageItem anImageItem; try { anImage = Image.createImage("/welcome.png"); anImageItem = new ImageItem( null, anImage, ImageItem. LAYOUT_NEWLINE_AFTER| ImageItem. LAYOUT_CENTER, null ); } catch( IOException ioe ) { ioe.printStackTrace(); …… 3-38

83 Alert类 Alert对象让用户等待一定时间才进入下一个屏幕,是一种可以包含文本和图像的屏幕,用来提示错误信息或其他情况。警报分为永久模式和定时模式两种。 永久模式警报一直停留在屏幕上,直到用户关闭它为止,然后它将返回之前显示的屏幕或者应用程序明确指定的屏幕。setTimeout(Alert.FOREVER)方法可以让Alert对象成为永久模式警报。 定时模式警报只在屏幕上显示一段时间(通常是几秒钟),然后自动进入下一个屏幕,可以使用setTimeout(int time)方法设置警报时间。 构造方法。

84 小结 Image类和ImageItem类 异常处理 Alert类 3-40

85 复习题 Image类和ImageItem类 异常处理 Alert类 3-41

86 第八讲 事件处理 学习目标: Ticker类 Command类 CommandListener接口 事件处理的步骤 重点和难点 3-42

87 Ticker类 Ticker对象实现了在屏幕的最上方连续滚动一小段文本,同一滚动条可以为屏幕上不同的对象公用。创建滚动条之后,在需要使用的屏幕上使用setTicker()方法把滚动条添加到当前的屏幕上。注意: MIDP规范没有提供启动或停止滚动条的方法; 滚动条的字符串是连续滚动的。当字符串滚动出显示器以后,滚动条将从字符串的开头开始,最好在滚动条字符串的末尾添加一些空格,以免信息的末尾与开头连在一起; 滚动的方向和速度取决于MIDP 实现。 3-43

88 事件处理 事件处理使得用户和应用程序之间可以进行交互,好的事件处理程序对于项目的成功与否事关重要。在MIDP事件处理中,有高级事件处理机制和低级事件处理机制。高级事件处理机制相对应的是触发高级用户界面所产生的事件处理,而低级事件处理机制相对应的是触发低级用户界面所产生的事件处理。本节将重点讲述高级事件处理机制,在高级事件处理中,有CommandListener接口、ItemCommandListener接口、ItemStateListenerCommand接口和Command类组成。 所有的用户界面的回调都是系列化的,不会同时发生调用两个或以上的事件处理的。 3-44

89 Command类 一个Command对象实际上就是一个按钮,例如:“发送”按钮,它仅仅只包含自身的信息,例如:按钮的名称,按钮的优先级和按钮的类型,不包含按钮触发时所发生的事件。因此,我们可以把Command对象看成一个按钮。 Command使用以下方法来创建一个按钮: Command(String label, int commandType, int priority); 其中,label表示按钮的名称,commandType表示按钮的类型,priority表示按钮的优先级。例如: Command cmdSend = new Command("Send",Command.SCREEN,1); 3-45

90 CommandListener接口 CommandListener接口是Command对象的事件处理监听器,它只有一个抽象方法:
commandAction(Command c, Displayable d); 其中,Command对象为按钮,Displayable对象为所显示的屏幕。该方法是指在那个屏幕上的事件处理。 3-46

91 事件处理步骤 步骤1:建立一个包含事件信息的Command对象。 cmdSend = new
Command("Send",Command.SCREEN,1); 步骤2:将该Command对象添加到Form、Canvas、Alert、List或TextBox中。 inputForm.addCommand( cmdSend ); 步骤3:在MIDlet类中实现CommandListener接口。 public class MGJCCX extends MIDlet implements CommandListener { …… } 3-47

92 事件处理步骤 步骤4:在Form、Canvas、Alert、List或TextBox对象中建立事件监听器。
inputForm.setCommandListener( this ); 步骤5:实现commandAction方法,进行事件处理。 public void commandAction(Command cmd, Displayable dis) { if( cmd == cmdBack ) { display.setCurrent(inputForm); } 3-48

93 小结 Ticker类 Command类 CommandListener接口 事件处理的步骤 3-49

94 复习题 Ticker类的功能 Command类的作用 CommandListener接口中的方法 事件处理的步骤 3-50

95 第九讲 常用的高级UI类 学习目标: 重点和难点: TextBox类 List类 ChoiceGroup类
ItemStateListener事件处理 DateField类 Gauge类 StringItem类 重点和难点: 3-51

96 TextBox类 TextBox对象是一种允许用户输入和编辑文本的屏幕。TextBox和TextField的功能大致上是相同的,不同的是TextBox是独立的文本编辑屏幕;而TextField是Item抽象类的子类,它必须包含在Form对象中。 3-52

97 List类 List(列表)是一种包含可选选项元素的屏幕。List和下一节将要讲到到的ChoiceGroup 一样,实现了Choice接口,用户可以通过在选项之间移动来与列表交互。但是,交互不会生成任何事件处理,只有当在做出选择以后才会产生事件处理。在List中,有三种模式:IMPLICIT模式、EXCLUSIVE模式和MULTIPLE模式。前两种模式只能选择一项元素,第三种模式可以选择多项元素。 3-53

98 ChoiceGroup类 ChoiceGroup是Form对象中的可选元素,它与List类似,也是实现Choice接口,其中的方法和属性也基本相同。 ChoiceGroup与List不同的是: ChoiceGroup只有EXCLUSIVE和MULTIPLE两种模式,而List有三种模式; List可以单独使用,而ChoiceGroup必须是放置在Form对象之上。 3-54

99 ItemStateListener Form中Item的状态是可以改变的,例如:改变TextFiled对象中的文本内容,使用上下键来选择ChoiceGroup对象中的元素时。MIDP使用ItemStateListener来监听这些状态的变化,当事件被触发时,会调用itemStateChanged()方法来进行事件处理。在下列情况下,将会调用itemStateChanged()方法: 当改变TextFiled对象中的文本内容或修改TextFiled对象中的值时; 当用户在使用上、下和Select键时; 当在DateField中输入新的日期或时间时; 改变Gauge对象中的值时。 3-55

100 事件处理步骤 步骤1:在MIDlet类中实现ItemStateListener接口。
public class MGJCCX extends MIDlet implements CommandListener ,ItemStateListener { } 步骤2:将Item对象添加到Form中。 aForm.append( aChoiceGroup ); 步骤3:在Form对象中建立事件监听器。 aForm.setItemStateListener( this ); 3-56

101 事件处理步骤 步骤4:实现itemStateChanged()方法,进行事件处理。
public void itemStateChanged( Item item ) { if ( item == aChoiceGroup ) { aChoiceGroup.setLabel(" " + ChoiceGroup.getString( aChoiceGroup.getSelectedIndex() ) ); } 3-57

102 DateField类 DateField是一个Item对象,它是一个放置在Form对象中用来显示时间和日期的可编辑组件。当编辑DateField对象中的时间或日期时,会触发ItemStateListener事件。DateField对象有三种显示模式:DATE(日期)模式、TIME(时间)模式和DATE_TIME(日期)模式,可以使用该类的静态整型变量来决定显示模式。 3-58

103 Gauge类 Gauge对象是一个放置在Form对象中的条形图,它可以和用户进行交互,例如:调节手机声音音量、网络连接进度条和下载进度条等。
3-59

104 StringItem类 StringItem对象是Item的子类,它的内容是只读的,用户不能够编辑它的内容。但是它的内容可以被应用程序修改。
3-60

105 小结 TextBox类 List类 ChoiceGroup类 ItemStateListener事件处理 DateField类 Gauge类
StringItem类 3-61

106 第十讲 通用连接框架 学习目标: 重点和难点 掌握通用连接框架(GCF) 了解使用HTTP协议访问Web站点 GCF访问数据模型
HTTP的工作原理 重点和难点 3-62

107 通用连接框架 3-63

108 GCF访问数据模型 3-64

109 Connector类 Connector类的七种创建连接的方法。 3-65

110 HTTP的工作原理 3-66

111 HTTP请求/响应协议- 客户端请求 请求方法 头 正文
请求方法(Request Method)确定数据如何发送给远程资源,有三种请求方法可使用: GET、POST 和 HEAD。 头字段(Header Field)是根据实际的需要从客户端向服务器传递参数。 正文 正文(Body)是客户端发送给服务器的实际内容。 3-67

112 HTTP请求/响应协议- 服务器响应 状态行 头 正文
顾名思义,服务器状态行(Server Status Line)通知客户端其请求的结果。 与客户端不同,服务器可以通过头字段获取发送信息,一个服务器有可能返回多个头字段。 正文 与客户机一样,服务器正文的功能是接收客户端的信息,作出相应的处理后,将处理的结果发送给客户。 3-68

113 小结 通用连接框架(GCF) HTTP的工作原理 3-69

114 复习 HTTP的工作原理 请求/响应机制 3-70

115 第十一讲 系统网络连接 学习目标: 设计请求方法 设计头 设计正文 重点和难点 3-71

116 导入包 客户端的设计主要是针对请求方法、头、正文的设计。本项目使用HttpConnection接口来进行网络的连接过程,当然读者也可以使用其他的一些接口。客户端的设计要遵循以下几个步骤: 步骤1:导入包。 由于在网络设计过程中需要使用HttpConnection接口,因此,必须导入javax.microedition.io这个包。同时,数据在网络传输过程中需要输入流和输出流,因此也必须导入java.io包。 import java.io.*; import javax.microedition.io.*; 3-72

117 设计请求方法 步骤2:设计请求方法。 本项使用的是POST方法,因为客户端需要传递城市名、起始站点和终点站点三个参数,使用POST方法较为简单、方便。当然,如果只有一个参数时,使用GET方法可能较为方便。 Conn= (HttpConnection)Connector.open(url,Connector.READ_WRITE);//发出请求,打开网络 conn.setRequestMethod(HttpConnection.POST); 3-73

118 设计头 步骤3:设计头。 conn.setRequestProperty("IF-Modified-Since","15 Oct :47:14 GMT"); conn.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0"); conn.setRequestProperty("Content-Language","en-CA"); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 3-74

119 设计正文 步骤4:设计正文。 正文的设计是客户端网络连接过程最为复杂的部分,它主要完成网络的连接、发送数据流和接收数据流。 3-75

120 3-76

121 运行结果 3-77

122 小结 设计请求方法 设计头 设计正文 3-78

123 复习 设计请求方法 设计头 设计正文 3-79

124 第十二讲 线程的设计 学习目标: 线程交互-wait()和notify() 客户端访问网络多线程设计 重点和难点 3-80

125 问题? 程序运行的结果是处在死锁状态,错误提示为:
Warning: To avoid potential deadlock, operations that may block, such as networking, should be performed in a different thread than the commandAction() handler. 3-81

126 Synchronized同步 为什么会出现上节访问网络是的死锁结果呢?其原因是由于事件处理线程和访问网络线程都共享了共同的数据――MIDlet对象。两个线程都为获得MIDlet资源而相互争执,出现了谁也不让谁的局面,也就是线程的死锁。为解决操作的不完整性问题,在Java 语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。 3-82

127 互斥锁 3-83

128 wait()和notify() Java技术使用wait()和notify()方法解决线程之间的交互。如果线程对一个同步对象x发出一个wait()调用,该线程会暂停执行,直到另一个线程对同一个同步对象x发出一个notify()调用。 为了让线程对一个对象调用wait()或notify(),线程必须锁定那个特定的对象。也就是说,只能在它们被调用的实例的同步块内使用wait()和notify()。 3-84

129 客户端访问网络多线程设计 启动线程 3-85

130 设计线程 3-86

131 设计交互 3-87

132 设计交互 3-88

133 小结 线程交互-wait()和notify() 客户端访问网络多线程设计 3-89

134 第十三讲 服务器端设计 学习目标: 服务器响应流程 数据流处理 Servlet的部署 重点和难点: 3-90

135 服务器响应设计 设计响应头 设计响应属性 能够处理中文 设计正文 数据的接收和发送 3-91

136 服务器响应流程 步骤1:导入包 步骤2:设计响应属性,实现doGet()、doPost()和destroy()方法。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; 步骤2:设计响应属性,实现doGet()、doPost()和destroy()方法。 3-92

137 服务器响应流程 3-93

138 服务器响应流程 步骤3:设计输入流 3-94

139 服务器响应流程 步骤4:设计输出流 3-95

140 服务器响应流程 步骤5:设计异常处理 3-96

141 小结 服务器响应流程 数据流处理 Servlet的部署 3-97

142 第十四讲 常用的网络连接 学习目标: 使用HTTP协议访问网页 使用HTTP协议访问JSP 重点和难点: 3-98

143 使用HTTP协议访问网页 【案例5-4】使用HTTP协议访问网页
目的:掌握如何在MIDlet中通过HTTP连接到服务器,并从服务器上获得信息;同时掌握HTTP协议工作的原理。 程序名:HttpExample.java 功能:将指定URL的HTML文件中的标题内容取出来,显示在屏幕上,将HTML文件的标题放置在<TITLE>和</TITLE>这两个标签之间。 3-97

144 使用HTTP协议访问JSP 【案例5-5】使用HTTP协议访问JSP 目的:掌握如何在MIDlet中通过HTTP协议来访问JSP
程序名:HttpExample.java 功能:获取JSP上的用户名和密码 3-98

145 第十五讲 数据库连接 学习目标: 使用JDBC连接数据库 ACCESS数据库的配置 重点和难点: 3-99

146 JDBC的两个组成部分 在JDBC中,有两个组成部分: 数据库厂商实现的接口; 应用程序接口。 3-100

147 JDBC与数据库连接 使用JDBC和数据库连接需要遵循以下五个步骤: 步骤1:注册厂商提供的JDBC驱动。
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver" ); 步骤2:建立DBMS会话。 Connection conn = null; String url = "jdbc:odbc:china"; conn = DriverManager.getConnection(url ); 3-101

148 JDBC与数据库连接 步骤3:创建SQL查询。 Statement stmt = conn.createStatement();
步骤4:提交查询并接收查询结果。 String query = "SELECT * FROM Person WHERE Name="+"'"+name+"'"; ResultSet rs = stmt.executeQuery( query ); 步骤5:把数据结果取出来。 rs.getString(1) ); 3-102

149 JDBC与数据库连接 3-103

150 JDBC在项目中的应用 在移动公交车查询系统中,数据库使用的是ACCESS,建立了两个表,分别表示“北京”和“深圳”的公交车信息。在这两个表中有四个记录:ID表示记录的个数;Carnum表示公交车号;Station表示站点,注意在创建站点时,在每个元素前面加上一个分号:“,”;Building表示比较重点的建筑,以便查找。 3-104

151 JDBC在项目中的应用 3-105

152 小结 JDBC连接数据库 ACCESS数据库的配置 3-106

153 复习 JDBC连接数据库 ACCESS数据库的配置 3-107

154 第十六讲 查询算法 学习目标: 一次查询 二次查询 重点和难点: 3-108

155 任务需求 程序先通过手机端获得城市(City)、当前点(Start)、目的地(End)三个值,然后通过服务器端的SQL查询语句从数据库中查找是否有记录的Station值中包含了Start与End。 3-109

156 一次查询 3-110

157 一次查询 3-111

158 一次查询 主要的SQL语句如下: "Select Carnum from " + TFCity + " where Station like " + "'%," + TFStart + ",%'" + " and Station like " + "'%," + TFEnd + ",%'" 3-112

159 二次查询 程序通过手机端获得城市(City)、当前点(Start)、目的地(End)三个值,先用SQL查询语句从数据库中找到Station值中包含了Start的所有记录集合Sa,接着再一次用SQL语句找到Station值中包含了End的所有记录集合Eb,然后通过循环语句找到Sa与Eb中有相同站点Middle(即中转站)的任两条记录如X和Y,那么客户若要从当前点到目的点就可以通过这样的乘车方法实现:车次X-中转站(Middle)-车次Y。 3-113

160 二次查询 3-114

161 查找共有站点分析 第一步:先要通过SQL语句找到所有含有该站点的记录集合,然后利用while语句把它们放到字符串数组里,如End[b],将获得Station中含有End的所有记录集合并存放在字符串End[b]中。 rs = sql.executeQuery("Select Station from " + TFCity + " Where Station like " + "'%," + TFEnd + ",%'"); while (rs.next() ) { End[b] = rs.getString("Station"); b++; } 3-115

162 查找共有站点分析 第二步:要将End[b]中的记录通过StringTokenizer方法使其变成一个个的小段,其中界定符逗号则是使得原来的字符串能正确分段的原因。根据“,”为字符串Start[c]构造一个StringTokenizer sa1。 StringTokenizer sa1 = new StringTokenizer(Start[c],","); 3-116

163 查找共有站点分析 第三步:将利用Vector.addElement方法将分成的小段即一个个的站点添加到可变数组Vector中,这样我们就可以在数组中使用循环比较的方法,找到相同的元素即共有站点。以sa1中的逗号为界定符把字符串划分为小段,把各小段作为元素存入可变数组Vector Va1中,用于下面的站点之间比较。 While( sa1. hasMoreElements() ) { Va1.addElement( new String( sa1.nextToken() ) ); } 3-117

164 查找共有站点分析 第四步:利用Vector. ElementAt()方法定位到数组中的具体元素中,并用equals方法判断两个数据中是否有相同的元素,即共有的站点。 if (Va1.elementAt(i).equals(Vb1.elementAt(j)) middle = Va1.elementAt(i).toString() ; //找到共有的站点,即中转站 3-118

165 二次查询算法 3-119

166 二次查询算法 3-120

167 二次查询算法 3-121

168 运行结果 3-122

169 小结 一次查询算法 二次查询算法 3-123

170 第十七讲 手机游戏设计 学习目标: 手机游戏特征 Java开发手机游戏的优势和缺点 总体设计 概要设计 重点和难点: 4-1

171 手机游戏特征 一个成功的手机游戏大多具有以下特征: 手机游戏可行性分析: 易于学习; 可中断性; 丰富的社会交互; 利用手机技术的优点;
无违法内容。 手机游戏可行性分析: 范围性; 随意性; 娱乐性。 4-2

172 传统手机存在以下弊端 传统手机出厂时均由硬件厂商固化程序,程序不能增加、删除,有了错误也不能更新、修改,若要增加新功能必须另换一部手机。
传统手机访问互联网是通过WAP(Wireless Application Protocal),所有网络资源必须接通网络才能在线访问,非常耗时、费用亦很高。 4-3

173 Java的优势 应用程序可按需下载,而不是购买由硬件商提供的套件,可升级空间大。
Java技术提供了一个类库,它使的应用开发商可以创建更为直觉、丰富的用户界面(GUI); Java技术使网络带宽的应用更为有效,因为应用程序可以下载到器件上,并在本地运行,仅仅是在连接到服务器时才会占用网络带宽。 4-4

174 Java的缺点 Java是基于虚拟机的半解释型编译系统,其执行效率较C++等完全编译后的程序会低很多,程序如果不进行精简和优化,将可能导致运行的不流畅。开发过程中需要进行结构上的控制、变量的合理使用、算法的优化。 4-5

175 游戏策划 在设计一个游戏之前,一定要先作个调研,看看这类游戏的适用对象、投资规模和市场等因素。对于一般的手机游戏在开发之前要搞清楚以下问题:
剧本编写 规则设计 关卡设计 4-6

176 游戏策划 4-7

177 逻辑功能 外部图形导入; 场景、元素绘制; 层次显示; 人物移动; 元素碰撞处理:元素的显示与消除; 胜利、失败判断; 时间计算系统;
数据更新。 4-8

178 概要设计 -界面模块 在界面模块中,有两个类,分别是:MissForest类和MenuScreen类。在MissForest类中,有四个元素,分别是: 场景display 按钮command 信息框Alert 画布MenuScreen 4-9

179 概要设计 -界面模块 4-10

180 概要设计 -逻辑模块 在逻辑模块中使用的关键性逻辑编码如下: 图形的导入:Image.createImage 人物的行走:keyStates
地图的绘制:Tiledlayer 事件的判断:If or and 数据的连接:RecordStore 层次的显示:layerManager 4-11

181 概要设计 -逻辑模块 4-12

182 概要设计 -RMS模块 在RMS模块中使用了RecordStore类,其中使用的方法有: addRecord(); getRecord();
setRecord(); 4-13

183 小结 手机游戏特征 Java开发手机游戏的优势和缺点 总体设计 概要设计 4-14

184 第十八讲 游戏界面设计 学习目标: 建立应用程序 掌握Canvas类 掌握Graphics类 重点和难点: 4-15

185 建立应用程序 游戏也是一种MIDlet应用程序,因此它也有MIDlet生命周期,既startApp()、pauseApp()和destroyApp(boolean)三种方法。 为了直接在屏幕图形,必须使用Canvas类,该类提供了一个供MIDlet 在上面绘制的空白屏幕。但是该类是一个抽象类,扩展了Displayable,为了能够在屏幕上画图像,必须创建一个类,该类继承Canvas类,并且重载(Override)paint(Graphics g)方法。paint(Graphics g)方法的实现使用了javax.microedition.lcdui.Graphics 类的绘制功能,所有的图像绘制工作都要在paint(Graphics g)方法中实现,所要绘制的图像的形状、颜色、大小等特性都在Graphics类实现中。 4-16

186 Canvas类 高级用户界面API是面向任务的,程序员无法控制这些组件在屏幕上的显示。而低级用户界面API的控制权是赋予程序员的,程序员可以使用低级用户界面API在屏幕上画出自己想要的图形来。这种低级用户界面API特别适合于游戏的开发,因此,关于游戏的开发主要是针对低级用户界面API的开发。当然,在游戏开发过程中,也可以使用高级用户界面API,这不过这两种用户界面不可以同时存在。 为了直接在屏幕上绘制线条、文本和形状,必须使用Canvas类。 4-17

187 Graphics类 Graphics类提供了简单的2D绘图功能。它具有24位深度色彩的绘制能力,以三原色分别各占一个字节表示其颜色。程序只能在paint()函数中使用Graphics绘制。 4-18

188 坐标设置 应用程序建立后,就可以在画布上画一些字符串,并设置字符串的颜色、大小、位置和形状等信息。对于Canvas画布,坐标(0,0)表示画布的左上角,坐标(getHeight(),getWidth())表示画布的右下角,每个单位表示一个像素。x轴坐标的值从左到右增加,y轴坐标的值从上到下增加。 4-19

189 颜色设置 不同的移动设备终端具有不同的颜色方案。24位(RGB)的颜色模型分别为红色、绿色和蓝色提供了8 位的值。然而,由于不是所有设备都支持彩色,所以应用程序要求的颜色将被映射成设备支持的颜色。Graphics类在设置和取得颜色方面提供了setColor()和getColor()两个方法。setColor(int RGB)方法和setColor(int red, int green, int blue)两个方法来设置颜色。 例如: g.setColor(0x00FFFF00); 或者 g.setColor(255,255,255); 4-20

190 字体设置 应用程序不能创建字体,作为替代,应用程序可以根据属性(例如大小、外观和样式等)请求字体,然后底层实现将返回与请求字体最接近的字体。Font类代表各种字体和度量。 4-21

191 形状设置 Graphics类还提供了设置图像形状的方法,可以描述线、矩形、圆弧、字符串和图像等。画和填充是两个概念,例如:画一个矩形,可以使用drawRect(),矩形中间是空的;填充一个矩形可以使用fillRect()方法来实现。画一字符串可以使用以下语句: 4-22

192 代码 4-23

193 代码 4-24

194 小结 建立应用程序 Canvas类 Graphics类 4-25

195 复习 建立应用程序 Canvas类 Graphics类 4-26

196 第十九讲 菜单设计 学习目标: 设计动态菜单 屏幕坐标计算 重点和难点: 4-27

197 设计目标 如何画游戏菜单? 如何设计动态菜单? 4-28

198 屏幕坐标 X轴 Y 4-29

199 动态字体 4-30

200 动态字体 4-31

201 动态字体 4-32

202 小结 设计动态菜单 屏幕坐标计算 4-33

203 复习 坐标计算 动态字体显示 4-34

204 第二十讲 事件处理 学习目标: 低级事件处理 高级事件处理 重点和难点: 4-35

205 低级事件处理 问题? 事件处理 为什么点击菜单,程序没有反应? 菜单不能上下移动 ?
在MIDP中,所有的低级事件处理都是基于Canvas对象的。低级事件处理的按键要根据ITU-T标准,根据ITU-T标准,0-9数字键、*和#键是所有手机都支持的。如果要想使开发出来的游戏具有较高的可移植性,建议开发者尽量使用ITU-T标准的按键。 4-36

206 低级事件处理 在MIDP中,规定了3个方法用于低级事件处理: protected void keyPressed(int keyCode);
protected void keyReleased(int keyCode); protected void keyRepeated(int keyCode); 在MIDP API中定义了一些抽象按键表示按键的上、下、左、右和选择,它们分别为:UP、DOWN、LEFT、RIGHT和FIRE。但是有些设备上没有这样的抽象键,设备就把数字键2、4、6、8和5分别表示这些抽象键。 4-37

207 低级事件处理 如何获取按键的事件呢?Canvas类提供了两个方法: int getGameAction(int keyCode);
int getKeyCode(int gameAction); 第一个方法的功能是从按键事件映射到抽象键事件;第二个方法的功能是从抽象键事件映射到按键事件。这两个方法都可以判断按键事件,具体来说就是当按下向下键时,使用getGameAction(int keyCode)方法就可以知道是抽象键DOWN;当选择了抽象键DOWN时,通过getKeyCode(int gameAction)就可以知道按下的向下键。 4-38

208 4-39

209 高级事件处理 由于本界面还有Alert对象用于显示制作小组和游戏方法等信息,所以还要加入高级事件处理方法。具体处理原理和过程本章将不会讲解,读者可以参考第四章的高级事件处理方法。 4-40

210 高级事件处理 4-41

211 高级事件处理 4-42

212 小结 低级事件处理 高级事件处理 4-43

213 复习 低级事件处理 高级事件处理 4-44

214 第二十一讲 多线程 学习目标: 设计出可以上下移动的菜单 复习游戏界面设计中的难点和重点 重点和难点: 4-45

215 问题 问题: 在设计好菜单以后,菜单不能够进行选择,也就是在视觉上不能够进行上下移动,为什么会出现这样的问题呢? 4-46

216 解决方法 看看paint()方法,当程序调用paint()方法后,程序执行,画出一个菜单来,但是画完后,程序没有重画功能,所以屏幕会一直停留在初始状态。为了解决这样的问题,必须要引入多线程问题。 4-47

217 4-48

218 复习 界面设计(paint()方法) 颜色 字体 形状 菜单设计 动态字体 坐标计算 多线程设计 重画(repaint()方法) 4-49

219 第二十二讲 游戏设计 学习目标: 游戏项目整体设计 GameCanvas类 多线程的创建、启动和结束 重点和难点: 4-50

220 游戏项目整体设计 MIDP1.0规范 移动设备制造商和运行商为游戏的开发制定了一系列的规范,封装了一系列的包和类。在MIDP1.0的规范中,由于没有专门的游戏开发类,许多游戏在不同的制造商和运行商的移动设备上运行结果不同,甚至有些游戏在一种设备上可运行,但是到另外一种设备上却不能正常运行,降低了游戏的可移植性,这个游戏的开发带来了很多的不便。 4-51

221 class MenuScreen extends Canvas implements Runnable {
Thread menuThread; public MenuScreen() { …… menuThread = new Thread(this); menuThread.start(); } public void run() { while( true ) { repaint(); public void paint( Graphics g ) { protected void keyPressed (int code) { } } 4-52

222 游戏项目整体设计 MIDP2.0规范 MIDP2.0规范提供了一个游戏开发包:javax.microeidtion.lcdui.game包:
GameCanvas类 Layer类 Sprite类 LayerManager类 TiledLayer类 自从MIDP2.0规范发布以后,游戏开发者在遵循MIDP2.0规范的基础上开发的游戏具有较高的可移植性,同时降低了代码的大小,减少了出错几率,提高了游戏运行的效率。 4-53

223 游戏项目整体设计 MIDP2.0中的GameCanvas类自己带有独立的Buffer,与MIDP1.0相比具有以下好处:
提高游戏运行的效率。MIDP2.0运行在同一个线程中,使用Polling技术,避免对消息处理的等待,可以随时通过getKeysState()方法获取按键信息,提高相应速度。 使用双缓冲技术(Double Buffering),通过使用flushGraphics()方法,避免屏幕抖动现象。 4-54

224 建立游戏应用程序 创建一个名为MyGameCanvas.java的文件,并将其放在src目录下; 导入game包;
创建一个MyGameCanvas类,并实现Runnable接口; 定义类属性; 创建构造方法; 创建一个线程; 运行线程; 停止线程; 画图; 4-55

225 建立游戏应用程序 将该类放在游戏的主类中; 添加事件处理程序; 4-56

226 小结 游戏项目整体设计 GameCanvas类 多线程的创建、启动和结束 4-57

227 复习 GameCanvas类 多线程的创建、启动和结束 4-58

228 第二十三讲 游戏精灵设计 学习目标: 游戏精灵设计 精灵方向控制 重点和难点: 4-59

229 精灵设计 在游戏中,一般都会有些图像,例如:主人公、火焰、冰块和树木等。它们也是游戏中的对象,通常称之为精灵。
在java.microeidtion.lcdui.game包中,提供一个Sprite类来管理精灵。 4-60

230 创建Sprite对象 4-61

231 将精灵显示在屏幕上 4-62

232 控制精灵方向 向左: 4-63

233 控制精灵方向 向右: 4-64

234 控制精灵方向 向上: 4-65

235 控制精灵方向 向下: 4-66

236 小结 游戏精灵设计 精灵方向控制 4-67

237 复习 游戏精灵设计 精灵方向控制 4-68

238 第二十四讲 游戏背景绘制 学习目标: LayerManager类 TiledLayer类 创建游戏背景 重点和难点: 4-68

239 背景绘制 在有个游戏地图上有很多相同的部分,例如:道路的颜色和宽度、树木的形状和颜色等,如图10-9所示。在图中,有草地、树木、火焰、冰块和门,如何定义这个地图呢? 4-69

240 层次管理 在一个游戏中可能有不同的图像,这些图像都要放置在屏幕上,每一个图像称为一层,如何管理这些图像呢,使它们的显示互不影响?在Game包中定义了一个名叫LayerManager的类。用它来管理图像的各层, 4-70

241 背景绘制 在Game包中定义了TiledLayer类来绘制地图,TiledLayer是用来处理巨大的背景和虚拟的区域的,使用它可以生成游戏的地图,也就是背景。 游戏贴砖 贴砖下标排列的三种形式 4-71

242 背景绘制 4-72

243 背景绘制 4-73

244 建立应用程序- 步骤1:声明、定义变量 4-74

245 建立应用程序- 步骤2:设置游戏背景 4-75

246 建立应用程序-步骤3:初始化 4-76

247 建立应用程序-步骤4:画图 4-77

248 小结 LayerManager类 TiledLayer类 创建游戏背景 4-78

249 第二十五讲 游戏中的人工智能 学习目标: 方向判断 障碍物判断 重点和难点: 4-79

250 手机游戏人工智能的特点 人工智能是游戏设计的重点和难点,如何设计出一个具有较高质量的游戏,人工智能是关键因素。由于移动设备硬件条件的限制,手机游戏中的人工智能不可能像PC机游戏那样具有较高的智能性,也不可能添加复杂的学习算法或者专家系统。在手机游戏中,人工智能主要体现在条件的判断上。本节以迷失森林游戏为例,详细说明如何在设计手机游戏的人工智能。 4-80

251 迷失森林游戏人工智能特点 在本项目中,精灵移动判断是人工智能设计的难点。首先精灵不能够走出屏幕,因此必须有范围的控制,同时,还要判断是否碰到木桩,如果碰到木桩,精灵将不能越过木桩。在精灵移动的过程中,还要判断精灵是否碰到了火焰或者冰块,如果碰到它们,就要减掉或者加上生命值。 4-81

252 向左移动 向左移动时,精灵的x轴坐标不能小于0,小于0时,精灵将会超出屏幕。同时还要判断是否碰到木桩、冰块和火焰,如果碰到木桩,精灵不能移动;如果碰到冰块或火焰,精灵的生命值发生变化;如果是草地,精灵可以通过。 4-82

253 向左移动

254 小结 方向判断 障碍物判断 4-83

255 第二十六讲 RMS记录管理系统 学习目标: 创建RMS 添加、修改、删除一个记录 游戏生命值的设计 重点和难点: 4-84

256 记录存储概述 MIDP为MIDlets提供了一种永久存储和后来读出数据的数据库解决方案,被称为Record Managerment System(RMS),是一种类简单的基于记录的数据库。很显然,手机上的数据库系统不可能有PC上的强大功能。微小的存储空间也限制了它们的结构不能过于复杂。RMS是专门针对移动设备的服务的。 RMS包中包括RecordStore类。 4-85

257 记录存储操作 创建RMS : 创建一个记录存储使用的方法是:
public static RecordStore openRecordStore ( String recordStoreName, boolean createIfNecessary ) 4-86

258 步骤1:导入包。记录存储要使用javax.microedition.rms包。
创建一个记录存储的步骤: 步骤1:导入包。记录存储要使用javax.microedition.rms包。 import javax.microedition.rms.*; 步骤2:定义记录存储。 RecordStore rs = null; 步骤3:创建记录存储。 /** *创建一个名为GameDB的记录存储 */ private void createNewDB() { try { rs = RecordStore.openRecordStore( "GameDB",true ); } catch( RecordStoreNotFoundException rsnfe) { catch( RecordStoreFullException rsfe) { catch( RecordStoreException rse) { 4-87

259 修改记录 修改记录使用的是RecordStore类中的setRecord()方法。这个方法从指定的字节类型数组data的偏移量offset开始,修改numBytes个字节数据。 public void setRecord ( int recordId, byte[] newData, int offset, int numBytes ) 4-88

260 修改记录 /** *修改一条记录 */ private void setRecordToDB( int recordID, String str, int offset, int len) { try { byte data[] = str.getBytes(); rs.setRecord( recordID,data,offset,len ); } catch( RecordStoreException rse) { 4-89

261 添加记录 添加记录使用的是RecordStore类中的addRecord()方法。这个方法从指定的字节类型数组data的偏移量offset开始,添加numBytes个字节数据。 public int addRecord( byte[] data, int offset, int numBytes ) 4-90

262 添加记录 /** *添加一条记录 */ private void addRecordToDB( String str ) {
byte rec[] = str.getBytes(); try { rs.addRecord( rec,0,rec.length ); } catch( RecordStoreFullException rsfe) { catch( RecordStoreException rse) { 4-91

263 删除记录 修改记录使用的是RecordStore类中的deleteRecord ( int recorded ) 方法。
public void deleteRecord( int recorded ) /** *删除一条记录 */ private void setRecordToDB( int recorded ) { try { rs.deleteRecord( recordID ); } catch( RecordStoreException rse) { 4-92

264 生命值的设计 String temp = getRecordFromDB();
gameLifeValueInt = Integer.parseInt( temp ); gameLifeValueInt--; IntToString(); setRecordToDB( 1,gameLifeValueString,0,1); 4-93

265 小结 创建RMS 添加、修改、删除一个记录 游戏生命值的设计 4-94

266 总复习 手机游戏的特点 Game包 游戏人工智能 4-95

267 谢谢!!!


Download ppt "移动应用开发技能."

Similar presentations


Ads by Google