MIDP+2.0+Game+API快速入门
API入门教程
API入门教程(非常易懂)一、API是什么?这个我本来不想说的,不过也许你知道其它人不知道,这里为了照顾一下新手,不得不说些废话,请大家谅解。
Win32 API即为Microsoft 32位平台的应用程序编程接口(Application Programming Interface)。
所有在Win32平台上运行的应用程序都可以调用这些函数。
使用Win32 API,应用程序可以充分挖掘Windows的32位操作系统的潜力。
Mircrosoft 的所有32位平台都支持统一的API,包括函数、结构、消息、宏及接口。
使用Win32 API 不但可以开发出在各种平台上都能成功运行的应用程序,而且也可以充分利用每个平台特有的功能和属性。
以上为API的相关介绍,不过有些新手看了以后可能还是不怎么明白API到底有什么用?这里请不要着急,如果你有足够耐心的话,请慢慢往下看。
二、如何使用API?估计这才是大家真正关心的,那么如何使用API呢?在了解API之前,先打开你的VB 书,翻到过程函数这章来,在搞清楚API之前应该先搞懂过程函数是怎么一回事!如果你还不知道过程的工作方式,那么请先不要急着往下看,那样容易走很多弯路。
好了,当你理解了过程函数时,也就是你可以使用API的时候了,别把API看得太难,你就像使用过程函数一样使用API就可以了。
首先,让我们看看一个简单的API,以下:Private Declare Sub Sleep Lib "kernel32" Alias "Sleep"(ByVal dwMilliseconds As Long)以上这个API的呢是起一个延时作用。
你如果是刚接触API的话可能会感到API的书写及其复杂,而且会感到很不适应。
其实这没什么的,慢慢习惯就好了。
至于API这些复杂的书写你就不用操心了,在你安装VB的时候微软已经帮我们带上了API浏览器,这些全部都可以利用API浏览器帮我们自动生成。
第六章、MIDP游戏编程
LayerManager和Layer
按键状态查询
GameCanvas引入下列方法用于查询所有按键的 状态:
public int getKeyStates() 返回值是一个整数 其中的每个二进数位对应一个游戏键码 若该二进制数位返回值为1,表示对应的游戏键 被按下 若该二进制数位返回值为0,表示对应的游戏键 未被按下
按键状态查询
LayerManager和Layer
Layermanager坐标系
(0,0)
fly.move(75,25); background.move(18,37); laymanager.setViewWindow(52,11,85,85);
GameCanvas坐标系
(0,0) X
Y
laymanager.paint(g,17,17);
说明: 只有LayerManager观察窗口内容能够绘制到 GameCanvas上,并最终被显示在屏幕上 LayerManager除观察窗口外内容无法显示在屏幕上
LayerManager和Layer
LayerManager和Layer
示例:
先创建Sprite对象实例fly,TiledLayer对象实例 background和LayerManager对象实例laymanager 获取GameCanvas的Grphics的对象实例g laymanager.append(fly); laymanager.append(backgroud); fly.move(75,25); backgroud.move(18,37); laymanager.setViewWindow(52,11,85,85); laymanager.paint(g,17,17); flushGraphics();
第四章、MIDP用户界面——高级API
用户界面库概述
底层API提供的抽象层次要低一些。
底层API主要用于需要对图象在屏幕上的具 体位置和像素进行精确控制的应用程序。 这些应用程序需要访问底层输入事件。 一些应用程序还需要访问特定的设备相关的 特性。
用户界面库概述
在MIDP 2.0中,为了便于游戏程序的设 计,专门引入了游戏包 javax.microedition.lcdui.game 提供底层API的类是Canvas和Graphics。
Display及其使用
示例:
public class myMIDlet extends MIDlet{
Display mydisplay = null; public myMIDlet(){ //构造函数 } public void startApp(){ mydisplay=Display.getDisplay(this); //其它操作 } //其它方法
Displayable对象
AMS负责程序的调度 Display负责屏幕的显示 Displayable负责屏幕的显示内容 Display将要求显示的Displayable对象显 示在屏幕上。
Displayable对象
通常多数应用程序都会使用预先定义的结 构如List,TextBox以及Alert。 这些类通常这样使用:
Display及其使用
类Display中提供的方法:
public static Display getDisplay(MIDlet m) 获取与指定MIDlet对应的Display对象 public void setCurrent(Displayable nextDisplayable); public void setCurrentItem(Item item) ; 把指定的Displayable对象显示在屏幕上
Android 2.2开发初学者快速入门十一大秘技
Android 2.2开发初学者快速入门十一大秘技2010-09-27 14:39本文为一位Android入门级开发者在经过三周学习Android收集整理的一份Android 2.2开发初学者的入门培训教程,从十一个方面把Android 2.2从配置到疑难解答都告诉给大家。
标签:Android一、环境配置和安装(Android 2.2)参考《在Eclipse下搭建Android开发环境教程》1.1 JDK1.2 SDK1.3 Eclipse 3.5 (Galileo)1.4 ADT 0.9.71.5 安装依次下载,按照文章步骤安装即可,注意安装SDK时,需要如下设置下:不然更新不下来,那个链接地址被墙了。
二、Android系统架构2.1Linux内核(Linux Kernel)◆ Android运行在linux kernel 2.6之上,但是把linux内受GNU协议约束的部分做了取代,这样在Android的程序可以用于商业目的。
◆ Linux 内核是硬件和软件层之间的抽象层。
2.2中间件◆中间件包括两部分:核心库和运行时(libraries & Android runtime)◆核心库包括,SurfaceManager 显示系统管理库,负责把2D或3D内容显示到屏幕;Media Framework 媒体库,负责支持图像,支持多种视频和音频的录制和回放;SQlite 数据库,一个功能强大的轻量级嵌入式关系数据库;WebKit 浏览器引擎等。
◆ Dalvik虚拟机:区别于Java虚拟机的是,每一个Android 应用程序都在它自己的进程中运行,都有一个属于自己的Dalvik 虚拟机,这一点可以让系统在运行时可以达到优化,程序间的影响大大降低。
Dalvik虚拟机并非运行Java字节码,而是运行自己的字节码。
2.3应用程序框架(Application Framework)◆丰富而又可扩展性的视图(Views),可以用来构建应用程序,它包括列表(lists),网格(grids),文本框(text boxes),按钮( buttons),可嵌入的web 浏览器。
第7章 MIDP游戏程序设计
案例7.1 GameCanvas类的使用 // 开始执行线程体
public void start() { isPlay = true; Thread t = new Thread(this); t.start(); } // 结束线程体的执行 public void stop() { isPlay = false; } // 线程体,一般为游戏的运行主体 public void run() { Graphics g = getGraphics(); // 获取脱机屏幕缓冲区 中的图形对象 while (isPlay == true) { drawScreen(g); // 调用绘制矩形的方法 } }
GAME_C_PRESSED
GAME_D_PRESSED
语法:public static final int GAME_C_PRESSED 代表游戏中的C键(某些设备可能不支持),值为0x0800
语法:public static final int GAME_D_PRESSED 代表游戏中的D键(某些设备可能不支持),值为0x1000
减少存储空间 灵活层中所有的图像分块(Tile)要从一个图像 Image中获取 按分块的大小遵循从左至右、从上至下的原则划 分。 每个分块分配一个唯一的索引号,从1开始。0号 分块内容为空,表示透明区域。图7.5 静态分块(Static Tiles)。setStaticTiles()重新更新 分块
在游戏中一般一帧画面的时间是固定的,需 要在这段时间内实现游戏中各个实体关系的 处理和游戏画面的绘制。 保证游戏有一个固定的帧率。 GameCanvas类简化了游戏编写方法,提 高了运行效率。
7.3 图层
图层主要用于实现游戏中各式各样的对象,如背 景,角色、道具等。它可以移动,可以实现动画, 图层之间还可以相互覆盖,相互作用,为实现游 戏中的不同主体提供了方便。 Layer是一个抽象类,必须通过它派生新类。 game子包定义了两个派生类:
学习情境4 MIDP2.0游戏开发
能力目标
学会使用GameCvanvas类的按键响应方法;
会熟练构造精灵类;
学会使用精灵实现动画的自动播放; 能熟练设置精灵出现的位置、显示帧、切换帧和绘制帧的方法。 学会使用Vector类创建子弹、移动子弹和绘制子弹; 学会自定义对象类的方法,构造一个游戏对象; 学会使用变量来模拟计数器功能,实现游戏对象以不同的频率运动; 熟练掌握使用setTransform()方法,实现精灵对象的旋转; 熟练掌握使用精灵类提供的方法进行碰撞的检测; „„
4.2.2 知识准备:了解GameCanvas类
MIDP有1.0和2.0版本之分。在MIDP2.0中,新增加了一个
javax.microedition.lcdui.game包,这个包中定义了专门用 于游戏开发的5个新类:GameCanvas、Layer、LayerManager、
Sprite和TiledLayer。这些类主要针对游戏开发的特点,提供
4.1 学习情景描述
除棋牌类游戏之外,一款手机游戏,通常在一个特定的场景 下展开,这个特定的场景,就是游戏的背景,根据需要,游戏背 景还可以滚动。在游戏背景下,通常有若干个游戏的对象。其中 本学习情境分为五个学习单元来完成。单元一,游戏主角设 可以由玩家通过按键来控制的游戏对象,称为游戏的“主角”, 计;单元二,子弹设计;单元三,NPC(非玩家控制角色)设计; 其余不能由玩家来控制的角色称为“NPC”,即非玩家控制角色, 单元四,游戏背景设计;单元五,滚屏设计。 或系统控制角色。这些游戏对象可以进行移动、跳跃、投掷、发 射子弹、攻击等各种动作。并通过对这些游戏对象和动作进行HP
缓冲区的Graphics对象。 3、调用GameCanvas类的flushGraphics()方法,可以将缓冲 区中的内容绘制到屏幕上。
J2ME 2D小游戏入门之旅
J2ME 2D小游戏入门之旅(一)游戏的框架[ 录入者:admin | 时间:2006-05-19 17:36:25 | 作者: | 来源: | 点击数:213 ][上一篇] [下一篇]favoyang转载请联系作者响应站长mingjava的号召,我也和大家一起分享一下我的经验,希望大家指教。
同时 欢迎各位高手的原创文章。
前几天看到tony在csdn上发布自己的学习作品“是男人就坚持60s”,觉得创意虽然简单但是却很耐玩,是学习手机游戏制作的入门经典,于是一时兴起,clone了一下,图片依然使用的是tony的图片,纯粹学习之用。
如果大家对这个游戏感兴趣可以与tony联系或访问他的blog。
从发展趋势上说midp2.0是趋势,最便宜的midp2.0手机如ot735i,已经1700元左右;而西门子一年前的高端机cx65,现在也只有2500左右;并且2500-3000这个价位的midp2.0手机有多种选择,西门子、se、N机都有。
我个人挺喜欢cx65,如果将来手机制造商成本不断降低,相信1500元的midp将不是梦…当然还要看应用是否丰富了。
言归正传,我们将使用midp 2.0 来开发我们的游戏,代号fly。
开发工具jbulider。
等文章全写完了,会提供src下载。
目录:一、游戏的框架二、完善周边工具类(图象、GameObject、Font)三、控制飞机的移动四、加入子弹群,实现碰撞运算五、实现爆炸效果、并加入道具导弹六、不足多多,你认为呢?七、源码一、游戏的框架我们的游戏需要一个通用的游戏框架,也方便以后的开发,但实现一个引擎是复杂的。
作为初学者如果要你考虑太多的问题,恐怕会让你偏离主线,这里只给出canvas的代码,不理解可以参看本站的另外一篇系列文章《使用MIDP2.0开发游戏》。
public class MyGameCanvas extends GameCanvasimplements Runnable, CommandListener{private static MyGameCanvas instance;Graphics g;boolean running;Thread t;Command startcmd,exitcmd,restartcmd;int keystate;boolean keyevent;boolean key_up,key_down,key_left,key_right,key_fire;private boolean allowinput;public int screenwidth;public int screenheight;boolean gameover;//define your variable here//define your variable endprotected MyGameCanvas() {super(true);g=getGraphics();running=false;t=null;addCommand(startcmd=new Command("start",Command.OK,1));addCommand(exitcmd=new Command("exit",Command.EXIT,1)); setCommandListener(this);screenwidth=getWidth();screenheight=getHeight();//put your init once code here//put your init once code end}synchronized public static MyGameCanvas getInstance() { if (instance == null) {instance = new MyGameCanvas();System.out.println("new MyGameCanvas");}return instance;}public void run(){System.out.println("MyGameCanvas run start");long st=0,et=0,diff=0;int rate=50;//16-17 frame per secondwhile(running){st=System.currentTimeMillis();gameinput();gameMain();et=System.currentTimeMillis();diff=et-st;if(diff<rate){//System.out.println("Sleep "+(rate-diff));try {Thread.sleep(rate - diff);}catch (InterruptedException ex) {}}else{//System.out.println("rush , and the frame using time: "+diff); }}System.out.println("MyGameCanvas run end");}public void start(){if(!running){running=true;t=new Thread(this);t.start();}}private void gameMain() {g.setColor(0,0,0);//clear screeng.fillRect(0,0,getWidth(),getHeight());flushGraphics();}private void gameInit() {gameover=false;allowinput=true;key_up=key_down=key_left=key_right=key_fire=false;}public void stop(){if(running){running = false;}}public void commandAction(Command c, Displayable d) {String cmdstr=c.getLabel();if(cmdstr.equals("start")){gameInit();start();removeCommand(startcmd);addCommand(restartcmd=new Command("restart",Command.OK,1)); }else if(cmdstr.equals("restart")){stop();while(t.isAlive());gameInit();start();}else if(cmdstr.equals("exit")){stop();Navigate.midlet.destroyApp(false);Navigate.midlet.notifyDestroyed();}}private void gameinput() {if(allowinput){keystate=getKeyStates();keyevent=false;if((keystate & UP_PRESSED)!=0){//upkey_up=true;keyevent=true;//deal your unstop job code here//System.out.println("up press");//deal your unstop job code end}else if((keystate & UP_PRESSED)==0){//release key if(key_up==true){key_up=false;//deal your one press-one job code here//System.out.println("up release");//deal your one press-one job code end}}if((keystate & DOWN_PRESSED)!=0){//downkey_down=true;keyevent=true;//deal your unstop job code here//System.out.println("down press");//deal your unstop job code end}else if((keystate & DOWN_PRESSED)==0){//release key if(key_down==true){key_down=false;//deal your one press-one job code here//System.out.println("down release");//deal your one press-one job code end}}if((keystate & LEFT_PRESSED)!=0){//leftkey_left=true;keyevent=true;//deal your unstop job code here//System.out.println("left press");//deal your unstop job code end}else if((keystate & LEFT_PRESSED)==0){//release key if(key_left==true){key_left=false;//deal your one press-one job code here//System.out.println("left release");//deal your one press-one job code end}}if((keystate & RIGHT_PRESSED)!=0){//rightkey_right=true;keyevent=true;//deal your unstop job code here//System.out.println("right press");//deal your unstop job code end}else if((keystate & RIGHT_PRESSED)==0){//release key if(key_right==true){key_right=false;//deal your one press-one job code here//System.out.println("right release");//deal your one press-one job code end}}if((keystate & FIRE_PRESSED)!=0){//firekey_fire=true;keyevent=true;//deal your unstop job code here//System.out.println("fire press");//deal your unstop job code end}else if((keystate & FIRE_PRESSED)==0){//release keyif(key_fire==true){key_fire=false;//deal your one press-one job code here//System.out.println("fire release");//deal your one press-one job code end}}if(!keyevent){//no keyevent here//System.out.println("NO KEY press");//no keyevent end}}}public static void cleanJob(){instance=null;}}使用singlon实现,因为每个gamecanvas都需要很多的内存空间。
021 MIDP2.0游戏编程
• MIDP2.0安全性
在MIDP2.0的域的安全机制中,主要涉及以下概念:
保护域:是MIDlet suite所允许的权限访问的集合。 权限访问:是指必须通过授权才能使用的 APIs 或功能。
第七章 MIDP2.0游戏开发
• MIDP2.0新特性
• MIDP2.0安全性
在MIDP2.0的域的安全机制中,主要涉及以下概念:
• MIDP2.0游戏开发
GameCanvas
GameCanvas为这个类的每个实例提供了独立的脱屏缓冲区,也可以查询游戏键的 状态。 Layer(层)是用于在游戏中表现某种类型的可视化对象的抽象类。
Layer
Sprite
Sprite(子图)是Layer(层)的子类,这个对象代表了某个图片,其中往往含有一 系列的帧。 通过提供Layers的顺序列表,LayerManager 简化了对多重Layer的帖色渲染过程。
• Display的扩展
每个MIDlet都有一个Display对象,Display为获取各种通用 参数的色彩值提供了一些方法: getColor(int colorSpecifier)接受下列参数之一,从而为特定 参数决定系统色彩,并返回一个十六进制数 (0xAARRGGBB) 1、COLOR_BACKGROUND 2、COLOR_BORDER 3、COLOR_FOREGROUND 4、COLOR_HIGHLIGHTED_BACKGROUND 5、COLOR_HIGHLIGHTED_BORDER 6、COLOR_HIGHLIGHTED_FOREGROUND
第七章 MIDP2.0游戏开发
• 小测验
1.判断题 1、MIDP2.0编写的程序可以在MIDP1.0上运行() 2、保护域是指必须通过授权才能使用的 APIs 或功能() 3、信任MIDlet Suite指该MIDlet suite能通过验证并其JAR文件的 完整性能被保证,并能被该设备上的某一保护域所信任()
022 MIDP2.0游戏编程
第七章 MIDP2.0游戏开发
• MIDP2.0新特性
• GameCanvas
GameCanvas示例 • 范例见GameCanvasTest.java
范例通过 GameCanvas 派生新类MyGameCanvas,在 MyGameCanvas中可以用方向键控制方块移动,用A、B、C、 D键来改变方块的颜色。此外,创建一个定时器任务类 MyTask, 定期调用MyGameCanvas类的 action 方法,检查键盘按键情况 和对屏幕进行重绘。最后通过MIDlet 派生类处理程序的启动和 退出,在程序启动时创建定时器。
第七章 MIDP2.0游戏开发
• MIDP2.0新特性
• GameCanvas
GameCanvas同时处理多个按键 //右键跟上键同时按下的状态 int key = GameCanvas.RIGHT_PRESSED | GameCanvas.UP_PRESSED; if ((result = keystate & key) != 0) { if (result == GameCanvas.RIGHT_PRESSED) //如果只有右键被按下 {
第七章 MIDP2.0游戏开发
J2ME手机游戏开发技术
专业教程 理论讲解部分
第七章 MIDP2.0游戏开发
• MIDP2.0游戏开发新特性
MIDP2.0 中对于游戏支持的功能有下面几类: FullScreen (全屏)模式的支持。 透明PNG 图像支持。
专门为游戏开发提供的 GameCanvas 类,能够使用脱机屏幕 缓冲区。
• GameCanvas
GameCanvas相对于Canvas的增强点: 1.全屏模式 2.按键状态检测 3.内置双缓冲
什么是JAVA MIDP2.0
什么是MIDP2.0?小尼克一直在跟着Java博士学习制作N820的Java应用,最近听说他又买了一部新的手机——N840。
1.MIDP博士,我买了一部新手机,N840耶!呵呵,新手机好啊,新机型上市的还挺快的。
这款新手机也是支持Java应用的哦。
以前作的N820应用可以在这上面用么?恩,Java程序当然可以用了,但是,新手机的功能提高了,Java应用也比以前丰富了,另外开发工具也升级了。
是这样啊,真好啊。
N840和N820有什么不同呢?恩,单从Java的功能来讲,不同点在于N840对应的是MIDP2.0,而N820只能对应MIDP1.0。
呃?MIDP是什么呀?以前好像没有听说过呀……。
看,把重要的东西都忘了吧,关于MIDP的说明Java初级讲座的第一讲里面就有,今后要注意复习哦。
好的。
请您稍等一下,我先去复习复习。
请大家也先看一看Java 初级讲座的第一讲,对手机Java 程序的结构进行一下复习吧。
(/cn/lecture/lecture_t1_1.php )复习完啦,让您久等了。
所谓的MIDP ,就是用于手机或者便携机器的profile 的一个。
可是什么是profile 呢…呃,我又不明白了。
所谓Profile ,是指定义使用何种功能的东西。
也就是说,MIDP 定义了手机等可以使用的Java 功能具体都有什么。
是这样的啊。
MIDP 的版本从1.0上升到2.0,是不是就说明手机可使用的功能也升级了呢?恩。
MIDP2.0增加了MIDP1.0没有定义的一些功能。
总而言之,对应MIDP2.0的手机,相比MIDP1.0的手机来说,能用的东西变多了。
2. MIDP1.0和MIDP2.0的不同博士,MIDP 的版本变成了2.0,新增加的功能都有那些呢?恩。
详细情况请参见sun 公司的Web 页面,上面记载了所有的内容,有不少呢。
(/techtopics/mobility/midp/articles/midp20/) 概括起来,MIDP2.0的新功能有以下几个方面,下面先简单介绍一下。
选修_2_GAME_API
概述_2
LayerManager 对于有着许多Layer 的游戏而言,LayerManager 通过实现分 层次的自动渲染,从而简化了游戏开发。它允许开发者设置一 个可视窗口(View Window),表示用户在游戏中可见的窗口; LayerManager 自动渲染游戏中的Layer,从而实现期望的视图效 Layer 果。 Sprite Sprite 又称“精灵”,也是一种Layer,可以显示一帧或多 帧的连续图像。但所有的帧都是相同大小的,并且由一个Image 对象提供。Sprite 通过循环显示每一帧,可以实现任意顺序的动 画;Sprite 类还提供了许多变换(翻转和旋转)模式和碰撞检测 方法,能大大简化游戏逻辑的实现。
示例_1
下例中,参考像素点被定义在猴子悬挂的手上:
示例_2
getRefPixelX()和getRefPixelY() 方法可用于查询参考像素点在绘 图坐标系统中的位置。开发者也 可以调用setRefPixelPosition(x,y) 方法来定位Sprite,使得参考像素 点定义在绘图坐标系统中的指定 位置。这些方法自动地适应任何 应用在Sprite 上的变换。 在右例中,参考像素点被定位 在树枝末端的一点;Sprite 的位 置也改变了,使得参考像素点定 位在这一点上,猴子看起来像挂 在树枝上。
概述_3
TiledLayer TiledLayer 又称“砖块”,这个类允许开发者在不必使用非 常大的Image 对象的情况下创建一个大的图像内容。TiledLayer 有许多单元格构成,每个单元格能显示由一个单一Image 对象提 供的一组贴图中的某一个贴图。单元格也能被动画贴图填充,动 画贴图的内容能非常迅速地变化;这个功能对于动画显示非常大 的一组单元格非常有用,例如一个充满水的动态区域。
针对API初学者的教程
针对API初学者的教程第一篇文章来源:vb大世界什么是API?API(Advanced Programmers Interface,高级程序员接口)(注:API实际是指Application Programming Interface,应用程序编程接口;此处疑为原文错误,不过在VB中也可以这么说吧!)是一套用来控制Windows的各个部件(从桌面的外观到位一个新进程分配的内存)的外观和行为的一套预先定义的Windows函数.用户的每个动作都会引发一个或几个函数的运行以Windows告诉发生了什么.这在某种程度上很象Windows的天然代码.其他的语言只是提供一种能自动而且更容易的访问API的方法. VB在这方面作了很多工作.它完全隐藏了API并且提供了在Windows环境下编程的一种完全不同的方法. 这也就是说,你用VB写出的每行代码都会被VB转换为API函数传递给Windows.例如,Form1.Print...VB 将会以一定的参数(你的代码中提供的,或是默认参数)调用TextOut 这个API函数.同样,当你点击窗体上的一个按钮时,Windows会发送一个消息给窗体(这对于你来说是隐藏的),VB获取这个调用并经过分析后生成一个特定事件(Button_Click).API函数包含在Windows系统目录下的动态连接库文件中(如User32.dll,GDI32.dll,Shell32.dll...).API 声明正如在"什么是API"中所说,API函数包含在位于系统目录下的DLL文件中.你可以自己输入API函数的声明,但VB提供了一种更简单的方法,即使用API Text Viewer.要想在你的工程中声明API函数,只需运行API Text Viewer,打开Win32api.txt(或.MDB如果你已经把它转换成了数据库的话,这样可以加快速度.注:微软的这个文件有很多的不足,你可以试一下本站提供下载的api3 2.txt),选择"声明",找到所需函数,点击"添加(Add)"并"复制(Copy)",然后粘贴(Paste)到你的工程里.使用预定义的常量和类型也是同样的方法.你将会遇到一些问题:假设你想在你的窗体模块中声明一个函数.粘贴然后运行,VB会告诉你:编译错误...Declare 语句不允许作为类或对象模块中的Public 成员...看起来很糟糕,其实你需要做的只是在声明前面添加一个Private(如Privat e Declare Function...).--不要忘了,可是这将使该函数只在该窗体模块可用.在有些情况下,你会得到"不明确的名称"这样的提示,这是因为函数.常量或其他的什么东西共用了一个名称.由于绝大多数的函数(也可能是全部,我没有验证过)都进行了别名化,亦即意味着你可以通过Alias子句使用其它的而不是他们原有的名称,你只需简单地改变一下函数名称而它仍然可以正常运行.你可以通过查看VB的Declare语句帮助主题来获取有关Alias的详细说明.消息(Messages)好了,现在你已经知道什么是API函数了,但你也一定听说过消息(如果你还没有,你很快就会)并且想知道它是什么.消息是Windows告诉你的程序发生了哪些事件或要求执行特定操作的基本方法.例如,当用户点击一个按钮,移动鼠标,或是向文本框中键入文字时,一条消息就会被发送给你的窗体.所有发送的消息都有四个参数--一个窗口句柄(hwnd),一个消息编号(msg)还有两个32位长度(Long)的参数. hwnd即要接受消息的一个窗口的句柄,msg即消息的标识符(编号).该标识符是指引发消息的动作类型(如移动鼠标),另外两个参数是该消息的附加参数(例如当鼠标移动时光标的当前位置)但是,当消息发送给你时你为什么看不到呢--就象有人在偷你的信一样?请先别恼火,让我告诉你.小偷其实是Visual Basic.但它并没有偷走你的信,而是在阅读了之后挑出重要的以一种好的方式告诉你.这种方式就是你代码中的事件(Event).这样,当用户在你的窗体上移动鼠标时,Windows会发送一条WM_MOUSEMOVE消息给你的窗口,VB得到这条消息以及它的参数并运行你在事件MouseMove中的代码,同时VB会把这条消息的第二个32位数(它包含了x,y坐标,单位为像素(Pixel),每个位16位)转换为两个单精度数,单位为缇(Twip).现在,如果你需要光标坐标的像素表示,然而VB已经把它转换成了缇,因此你需要重新把它转换为以像素为单位.在这里,Windows给了你所需要的,但VB"好意地"进行了转换而使你不得不重新转换.你可能会问--我难道不能自己接收消息吗?答案是肯定的,你可以使用一种叫做子类处理(Subclass)的方法.但你除非必须否则最好不要使用,因为这与VB的安全程序设计有一点点的违背.(注:子类处理确实有很大的风险,但如果使用得当,是很有用处的.不过有一点一定要注意,即千万不要使用VB的断点调试功能,这可能会导致VB崩溃!)需要补充说明的是:你可以发送消息给你自己的窗口或其他的窗口,只需调用SendMessage或PostMessage(Se ndMessage会使接受到消息的窗口立刻处理消息,而PostMessage是把消息发送到一个称为消息队列的队列中去,等候处理(它将会在该消息处理完后返回,例如有些延迟)).你必须制定接受消息的窗口的句柄,欲发送消息的编号(所有的消息的编号均为常量,你可以通过API Text Viewer查得)以及两个32位的参数.针对API初学者的教程第二篇文章来源:vb大世界Windows的一些特别之处这个主题是要告诉你Windows 的一些与在VB中的不同的细节Windows通过句柄(Handle)识别每个窗体,控件,菜单,菜单项或其他任何你能想得到的东西.当你的程序运行时,它所包含的每个部件都有一个唯一确定的句柄用来同其他的部件相区别.例如,某个按钮得句柄就与其他部件不同,当你想要通过API来执行有关该按钮的某种操作时就必须使用这个句柄.从哪儿得到它呢?VB 为每个拥有Windows句柄的控件都提供了Hwnd属性来表示其句柄.Windows 使用像素(Pixel)而不是缇(Twip).因此,把涉及API函数调用的控件的ScaleMode属性设为3--(Pixel)是个不错的主意,这样你可以通过ScaleXXX属性得到它们的国际单位值.尽管这样,你可能有时仍需要进行从Twip到Pixel的转换(反之亦然),你可以通过Screen对象的TwipsPerPixelX和TwipsPerPixelY来实现.举例如下:PixelXValue=TwipXValue\Screen.TwipsPerPixelXPixelYValue=TwipYValue\Screen.TwipsPerPixelYTwipXValue=PixelXValue*Screen.TwipsPerPixelXTwipYValue=PixelYValue*Screen.TwipsPerPixelY我并没有在实际中见到过TwipsPerPixelX 和TwipsPerPixelY 的值有什么不同,但你最好是把它们区别开来而不是混用,这至少是一种好的程序设计风格.另外需要注意的是,这里用的是" \ "(整除) 而不是" / " ,这是因为像素值必须是整数.另外需要提到的是,Windows函数中用到了不同的坐标系统,因此需要注意.最后要注意的是,一旦你使用了API 函数,VB就可能不再可靠了---API调用中一个简单的语法错误就会导致VB 崩溃!(请经常保存您的工程).VB 并不能识别API调用中的错误,因此一旦你的程序出现异常,要先检查API调用---是否缺少ByVal,或者是错误的类型,参数等等.从哪里得到有关函数的说明?这个主题不会告诉你如何通过API函数改变按钮文字或如何快速查找一个文件.这不是一个API函数文档. 为了得到有关函数的说明,你需要SDK帮助或微软的SDK文档(至少有40M---我怎么可能放在这里?).这些S DK帮助通常都包含在Borland Dephli 3.0 开发包或者MS Visual C++中.到网上去或找您的朋友要一个,版本越新越好注意Win3.x 的SDK 帮助对你并没有用,因为很多函数已经过于陈旧甚至废弃不用,尽管他们中的大多数由于与Windows95兼容而依然存在.API参数类型如果你已经有了一个SDK帮助,你肯定主意到了函数的返回之或参数有很多奇怪的类型如VOID,LPCSTR, 和DWORD.如果你对C语言比较熟悉的话,那你肯定明白它们的意思.对于其他不熟悉C语言的人,这里有一张摘自VB Books Online(标题是:C语言声明到Visual Basic的转换)注释:你应该注意到了BOOL类型(Boolean)求出的值为Long而不是Boolean.因此0表示"假"(False),其他任何值表示"真"(True).HWND,HDC,HMENU,etc.---etc.指其他所有与于前面所述相似的类型.它们都以"H"开头来表示不同对象的句柄.举例来说,HBITMAP表示一副位图的句柄,HBRUSH标是一个刷子的句柄等等.它们均为Long而且要按值传递(ByVal).同样要注意LPVOID被声明为Any型变量,本文将会有独立的一个主题用来论述Any类型.有些类型以"LP"开头.LP 是Long Pointer的缩写.因此LPWORD实际表示数据所存的内存地址.不过,你并没有必要调用某个函数来获取这个地址.当你按引用(ByRef)传递参数时,你实际上传递的就是它的地址.在这里你只需记住:如果某个参数的类型以"LP"开头,应该按引用(ByRef)传递.顺便说一句,LPARAM 与Lparam 很相似但不是Lparam,Lparam不是一个指针,在这里你必须传递它的真实值,因此要按值(ByVal)传递.NULL也是一种奇怪的类型.你可以从VB 中了解到有关它的描述,这里我不去讨论它.按你需要的形式传递它吧,在大多数情况下,可以用ByVal 0& 或vbNullString.最后,VOID是用来指那些没有返回值的函数的.API中没有SUBs,这就是它们的标志.只要记住:如果一个函数被声明为VOID ,你必须在VB 中把它声明为SUB.针对API初学者的教程第三篇文章来源:vb大世界Any有些消息的参数声明为Any.这表示该参数是一种可变的类型(你可以以整型,字符串,用户自定义或其他的类型来传递).这有一个这样的例子:Public Declare Function SendMessage Lib "User32" Alias "SendMessageA" ByVal Hwnd as Long, ByVal wMsg as Long, ByVal wParam as Long, lParam as Any) as LonglParam 声明为Any并按引用(ByRef)传递.这里是在这个函数中如果lParam是不同类型的值时应遵循的规则:如果该值是传递形式numeric ByVal(as Long,or as Any)Null ByVal(as Long,or as Any)String ByRef(as String,or as Any)Type ByRef(as Any)array of Type ByRef(as Any)如果你的函数声明同上面的一个而且你想传递一个Long型数,你应该这样写:Call SendMessage(Me.Hwnd,WM_XXXX,0&,ByVal LongValue)注意尽管头三个参数也是数值,但它们前边并没有ByVal.这是因为在函数声明中它们已经被声明为按值传递(ByVal).第四个参数,由于是按引用传递(ByRef)(VB并不知道你要传递参数的类型),因此你必须加上ByVa l 你可以使用别名技术来传递不同类型的参数:Public Declare Function SendMessageLng Lib "User32" Alias "SendMessageA"(ByVal Hwnd as Long, By Val wMsg as Long, ByVal wParam as Long, ByVal lParam as Long) as Long或:Public Declare Function SendMessageStr Lib "User32" Alias "SendMessageA"(ByVal Hwnd as Long, ByV al wMsg as Long, ByVal wParam as Long, lParam as String) as Long注意API参数类型本身是不会改变的.例子中的第四个参数总是一个4字节的长型数.当你按值(ByVal)传递一个Long或Null时,该4字节长的数值就直接传递给函数.如果你传递一个String或其他的什么,你是按引用(ByRef)传递,VB传递的实际上是变量的地址,也是4个字节.参数传递你已经知道如何传递参数了,只需把他放到调用的函数中即刻.然而,当你使用API函数时,在传递参数是有一些你应该注意的细节. ByVal还是ByRef. 通常情况下,你不用为此担心,VB的API浏览器已经为你做好了一切,只需你输入数值它就会照所声明的方式传递.总的来说,ByVal是把实际的数值传递给函数,而ByRef是把地址传给函数.唯一的麻烦就是Any 类型. 把字符串传递给API函数也并不难.API函数需要的是字符串首字符的地址,然后读取该地址直到遇到一个Null字符.听起来很糟糕,但只是VB处理字符串的实际方法.你唯一要记住的是一定要按引用传递(ByRef)字符串当你想得到所需的函数返回值信息时,情况有稍微的一点不同.这里是GetComputerName函数的声明:Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA"(ByVal lpBuffer As String, nSize As Long) As Long第一个参数是一个指向字符串的远程指针,第二个参数是字符串的长度.如果你只是简单的声明一个字符串类型的变量并把它传递给函数,就会出现错误.因此,你首先需要初始化字符串.这里是如何得到计算机名字的例子: Dim Buffer As StringBuffer = Space(255)Ret& = GetComputerName(Buffer, Len(Buffer))if Ret& > 0 then CompName$ = Left(Buffer, Ret&)在这里,待传递的字符串被初始化为有255个空格的字符串.我们把它传递给函数同时还有它的长度.如果出错则返回值为0.CompName中将保存计算机名. 有些函数也需要传递数组,这里是一个例子:Declare Function SetSysColors Lib "user32" Alias "SetSysColors" (ByVal nChanges As Long, lpSysColor As Long, lpColorValues As Long) As Long最后两个参数是Long型数组.为了传递数组,你只需传递它的第一个元素.下面是示例代码:Const COLOR_ACTIVECAPTION = 2Const COLOR_INACTIVECAPTION = 3Const COLOR_CAPTIONTEXT = 9Const COLOR_INACTIVECAPTIONTEXT = 19Dim SysColor(3) As LongDim ColorValues(3) As LongDim Ret& SysColor(0) = COLOR_ACTIVECAPTIONSysColor(1) = COLOR_INACTIVECAPTIONSysColor(2) = COLOR_CAPTIONTEXTSysColor(3) = COLOR_INACTIVECAPTIONTEXTColorValues(0) = RGB(58, 158, 58) '深绿ColorValues(1) = RGB(93, 193, 93) '浅绿ColorValues(2) = 0 '黑色ColorValues(3) = RGB(126, 126, 126) '灰色Ret& = SetSysColors(4&, SysColor(0), ColorValues(0))该程序将改变所有活动和非活动窗口的标题栏背景和文本的颜色.针对API编程初学者的教程第四篇文章来源:vb大世界回调(CallBacks)所谓回调,就是你自己定义一个函数,并告诉Windows何时为何调用.你可以写一个有特定数量和类型参数的函数,然后告诉Windows何时调用,并传递给它所需的参数.Windows就会调用你定义的函数,处理参数,并给你返回值.回调的一个典型应用是从Windows获得连续的数据流.这里是一个需要回调的函数的声明:Declare Function EnumWindows Lib "User32"ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long第一个参数是你的回调函数的地址,第二个参数是你想传递的的任意数值.该值将被传递到你的函数,于是你就知道了它要调用什么.VB 5.0已经提供了一个很有用的操作符AddressOf ,可以得到一个函数的地址.当你调用一个函数时它只能用在参数的前面,下面这种用法是错误的并且会导致出错:FuncP = AddressOf MyFunction因此你必须这样调用EnumWindows函数:Success& = EnumWindows(AddressOf cbFunc, 58&)你必须也要自己写回调函数.问题是有很多不同类别的回调并且有各种各样的参数,有关这些参数的描述可以在SDK帮助或MS SDK文档中找到.这里是一个回调的声明:Function cbFunc (ByVal Hwnd, ByVal lParam) as Long这里是一个回调的例子:Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA"(ByVal hwnd As Long,B yVal lpString As String,ByVal cch As Long) As LongSuccess& = EnumWindows(AddressOf cbFunc, 58&)Function cbFunc (ByVal Hwnd, ByVal lParam) as LongIf lParam = 58 then 'enum windowsStr$ = Space(255)Ret& = GetWindowText(Str$, Len(Str$))Debug.Print Left(Str$, Ret&)End IfEnd Function这个例子将列出窗口的标题,(不包含子窗体)窗口程序Windows并不知道事件. 这些是VB特有的隐藏Windows获取你的窗口发生事件的真正方法的一种方式.V B很像是一个将Windows语言翻译成VB语言的解释器.但是事实并非如此,你很快就会遇到.设想你想知道用户何时加亮了菜单选项(不是点击,只是加亮即选择了)V B并不提供这种事件,但你可能见到其他的程序,但你浏览它的菜单时状态栏会出现相应的文字.如果他们能,你为何不能?OK,这里是大致的真实情况.每个窗口都有一个特殊的程序叫做窗口程序.它实际上是一个回调函数.该函数将在你的窗口发生事件的任何时间发送消息.这样当用户加亮一个菜单项时就会发送一条消息(WM_COMM AND).那为什么我看不到这条消息呢?这是因为是VB创建窗口程序而不是你.当Windows发送消息时,该程序将为之分派特定的事件,并将其参数转换为比较容易用的事件的参数.但是在有些情况下,它会忽略有些消息而不能收到真实的输入.如果你真的想得到这些消息,你必须对你的窗体进行子类处理,我们将在另外一个主题中谈到.这里是一个回调窗口程序的声明:Function WindowProc(ByVal Hwnd As Long, ByVal wMsg As Long,ByVal wParam As Long, ByVal lPa ram As Long) As Long第一个参数指定窗口的句柄,第二个参数是消息的标识符(如WM_COMMAND或WM_MOUSEMOVE),wPa ram和lParam时两个32位的数值,它们的意义依赖于消息的类型.针对API编程初学者的教程第五篇文章来源:vb大世界子类处理当你一最大限度利用了VB所给你的并且还想知道更多的东西,或只是想更多地了解你自己的窗口,你将会发现子类处理的优势.子类处理是指用一个新的窗口函数来取代当前活动窗口函数.这个用户自定义函数能处理任何需要的消息,并能调用原来的窗口函数,它将在原来的窗口函数之前收到各种消息.但原来的那个窗口处理函数依然存在,并没有消失.如果你不想处理某条消息,你应该让原来的窗口函数去处理它.子类处理是通过调用SetWindowLong函数实现的,该函数将改变指定窗口的特殊属性.下面是它的声明: Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"(ByVal hwnd As Long, ByVal n Index As Long,ByVal dwNewLong As Long) As Long第一个参数代表要进行子类处理的窗口,第二个参数应该是GWL_WNDPROC(-4),第三个参数是新的窗口函数的地址.参见回调和窗口函数一节.此函数将在窗口取得焦点,发生事件,或其他情况下(如其他进程改变了系统的某些参数)被随时调用.如果发生错误SetWindowLong函数将返回0,否则将返回原来的窗口函数的地址.这个地址特别重要,你应该把它保存在一个变量中或其他地方.当你不处理某些消息时(实际上,你可能只处理不到1%的消息,其他的都将由原窗口函数处理),调用原来的窗口函数就需要该地址.调用原窗口函数将由CallWindowProc来完成.这里是它的声明:Declare Function CallWindowProc Lib "user32" Alias"CallWindowProcA"(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long,ByVal Msg As Long,ByVal wParam As Long, ByVal lParam As Long) As Long 第一个参数是原窗口函数的地址,其他的同你接收到的四个参数一样.你可以改变其中的值来控制对消息的处理.例如,当你收到了一条WM_MOUSEMOVE消息时,你从lParam中得到鼠标所在位置的坐标并将其改成了其他的坐标.那么原窗口函数就会认为鼠标位于其他的位置从而做出一些有趣的事如显示其他控件的Too ltip.你指定的返回值也是有意义的,它依赖于发送的消息.在结束你的程序时将控制权交回给原窗口函数是很重要的,通常在Form_Unload中完成如下:Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProcAddress)如果你在VB中启动程序时忘掉了这一行,结果将是VB崩溃并会丢失尚未保存的数据.千万要小心.这里是子类处理的一个简单示例:Dim oldWndProc As LongPrivate Sub Form_Load()oldWndProc = SetWindowLong(Me.Hwnd, GWL_WNDPROC, AddressOf MyWndProc)End SubPrivate Sub Form_Unload()Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProc)End SubFunction MyWndProc(ByVal Hwnd As Long,ByVal wMsg as Long,ByVal wParam As Long,ByVal lPara m As Long)Debug.Print wMsg & " " & wParam & " " & lParamRet& = CallWindowProc(oldWndProc, Hwnd, wMsg, wParam, lParam)End Function处理参数有时函数并不以你所需的方式返回信息.一个典型的例子是将两个代表鼠标位置的整形(2 byte)数合并为一个4 Byte的数.还有一个例子是判断一个数的某位是否为1.你还可能得到一个代表一个结构地址的Long型数.合并和分离一个数并不需要过多的描述.你能在下面的网站(/SiliconValley/Lab/1632/)上找到APIMacro.bas,它包含了你需要的多种函数.可以用一下方法检查一个数的第N位是否为1:If Value and (2^N) then ...置1Value = Value Or 2^N置0Value = Value And Not 2^N如果你想设定或取得预先知道的某位的信息,用1024代替2^10要快的多.因为这样VB无需自己进行计算(V B憎恨"^" ?).如果你接收到一个类型的指针,你要做的工作将稍多一点.你可以使用CopyMem函数来取得信息.下面是它的声明:Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, By Val ByteLen As Long)如果你接收到了一个指向RECT 类型的指针并存在Long型变量Addr 中,可以这样处理:Dim Info As RectCall CopyMem(Info, ByVal Addr, len(Info))注意ByVal关键字.现在,如果你想把信息写回,使用:Call CopyMem(ByVal Addr, Info, Len(Info))结束语我希望这份教程能帮助你理解如何控制API函数的威力和如何正确使用它们.但是要小心!就像火,如果你让它失去控制,你就会玩蛋.当然,不要忘了VB是进行简单.安全程序设计的语言,而API函数则正好相反.如果你想得到更多的控制功能,最好转移到VC++ 或者Delphi.(这一点,洞主不敢苟同).祝你在API探险中好运!。
j2me教程
MIDlet-Jar-Size 描述了对应的 jar 文件的字节数. 如果你使用 wtk 重新编译程序的话, 你必须手动修改这个属性 (译注:不是吧,程序似乎自动会修改的吧) MIDlet-Jar-Size 属性与 jar 文件不匹配的话程序不会运行(译注:
大伙自己试试吧). (因为老是手动修改 jar 大小的确是非常麻烦的,所以作者在文章的最后附带了一个 build 用的 script,
Wireless Toolkit 包含MIDlet 开发环境,模拟器, 还有一些例程.在这里我就不对怎么安装j2me在浪费笔墨了,因为
随着环境的不同。安装不尽相同,而且联机文档中已经说的蛮清楚的了.
当你查看 demo 程序的时候, 你会发现它包括 jar 文件和一个 jad 文件. Jar 包括了 class 文件, 资源文件,以及一 个 manifest 文件. jad 包含了加载 MIDlets 必须的一些属性:比如 jar 的大小, 包含 MIDlet 的 jar 的 url 地址.下面是我的 Hello World 例程中所用到的 jad 文件内容:
MAS2.0JAVAAPI接口插件开发手册.
中国移动代理服务器MAS V2.0 JAVA API接口插件开发手册深圳市嘉讯软件有限公司2008年9月目录1.引言 (4)1.1.编写目的 (4)1.2.背景说明 (4)1.3.相关术语与缩略语解释 (4)2. API结构说明 (4)3. 运行环境 (5)4. 开发步骤 (5)4.1. 在Mas服务器新建一个企业应用 (5)4.2.启动企业应用 (6)4.3.开发时需要引入的包 (6)4.4.接口开发及使用举例 (6)4.4.1. APIClient工厂类-ApiClientFactory类 (7)4.4.1.1. 创建短信API客户端-createSmsApiClient方法 (7)4.4.2. 短信接口 (7)4.4.2.1. 短信API客户端主要操作类-SmsApiClient类 (7)4.4.2.1.1. 设置自动重连服务器-setTimingConnect方法 (7)4.4.2.1.2. 设置自动重连服务器相隔时间-setConnectTime方法 (7)4.4.2.1.3. 设置与服务连接超时时长-setConnectTimeout方法 (8)4.4.2.1.4. 设置发送超时时长-setSendTimeout方法 (8)4.4.2.1.5. 启动API-start方法 (8)4.4.2.1.6. 获得网关连接状态-getConnStatusIAGW方法 (8)4.4.2.1.7. 取消短信发送- canelSms方法 (8)4.4.2.1.8. 获得短信队列中未发送的条数-getStat方法 (8)4.4.2.1.9. 获得扩展服务代码长度- getXCodeLength方法 (8)4.4.2.1.10. 计算短信条数和字数-getSmsCount方法 (8)4.4.2.1.11. 获得预览的短信内容-getSmsContentPreview方法错误!未定义书签。
4.4.2.1.12. 短信API退出-loginOut方法 (8)4.4.2.1.13. 获得MAS短信提交的限制数量-getDestAddrsLimit方法 (9)4.4.2.1.14. 发送短信-sendSms方法 (9)4.4.2.2. 短信回调对象处理类-SmsApiClientHandler类 (10)4.4.2.2.1. 发送响应通知-notifySmsSendResponse方法错误!未定义书签。
第十三章 MIDP20游戏开发
Layer类比较抽象,下面介绍具体的两个子 类:TiledLayer类和Sprite类。
游戏背景:TiledLayer类
在游戏开发中通常都要设置背景,TiledLayer 就是为了解决这个问题而出现的。 TiledLayer可以把一个整个的源图分割成若干 个用户制定尺寸的小图,而用户按照小图的 编号来安排背景形状。 这种技术高效且节约资源,在2D游戏中被广 泛用于创建特别大的可滚动背景。
游戏的屏幕:GameCanvs类
GameCanvas概述 GameCanvas概述 GameCanvas类是在Canvas类的基础上派生 的,并在此之上增加双缓冲和随时查询按键 状态的功能。因为游戏画布类被定义为虚类, 所以必须要用派生新类。
游戏的屏幕:GameCanvs类
GameCanvas类包含的方法如下:
与静态贴图不同,动画贴图是需要额外创建 的,且序号一定为负数。 创建的第一个动画贴图序号为-1,第二个为2,依此类推。 动态贴图的例子: TiledLayerDemo.java
游戏精灵:Sprite类
Sprite类也是Layer的子类,它专门用来代表 游戏中的动画角色,比如飞机、坦克等。 Sprite类概览 Sprite类概览 MIDP2.0为Sprite类提供了强大的支持,可以 创建静态、动态、不透明和透明的Sprite。在 游戏中还可以使用Sprite类提供的碰撞检测功 能来简化游戏逻辑。
图像贴图 图像贴图用于填充TiledLayer的单元格,由一 个可变或不可变的Image对象提供。
游戏背景:TiledLayer类
源图像被切割成一系列相同大小的图像贴图, 对于每个单元格进行填充。 图像贴图的大小随Image一起被指定,相同 的一系列图像贴图可以用不同的排列方式存 储。比如1×6、2×3、3×2的排列方式。 排列方式的选取取决于对游戏开发者的方便 与否。
MIDP2.0及其移植技术分析
MIDP2.0及其移植技术分析摘要:MIDP即移动信息设备规范,是专门基于资源和网络连接有限的移动设备之上的J2ME应用规范。
本文在分析的基础上,详细阐述MIDP的事件处理、文件系统、用户图形接口和网络等主要部分在不同平台间移植的实现过程。
关键词:J2ME MIDP 移植平台无关本地代码1 简介随着现代信息化社会的发展,小型移动通信设备已经从最初的一种单纯的通信工具转变成如今集通信、工作、娱乐等功能为一体的综合设备;但仅有这些还不能满足用户的要求。
个性永远是千变万化的,时尚也不会始终为一种模式。
因此,在移动终端上开发通用的、丰富的应用已成为必然的趋势。
这些应用可以按用户的意愿随时安装和删除。
J2ME正是这样一种JAVA应用开发平台。
实际上,JAVA语言从其诞生起就以其运行的平台无关性这一强大的优势而成为网络应用的宠儿。
J2ME是JAVA2标准版本的微型版本,专门为小型移动设备所设计。
这些设备处理器的处理能力都不强,可使用的资源也有限。
因此,J2ME只包含了J2SE中在移动通信设备上所必需的功能和组件,使其能够在移动设备及其有限的资源上开发出丰富多彩且平台无关的应用。
J2ME在结构上分为CDC和基于其上,以Foundation Profile为主的规范,以及CLDC和基于其上,以MIDP为主的规范。
MIDP是移信息设备规范的简称。
规范具体定义了J2ME适用的硬件和软件框架,并提供了这个框架要实现的基本功能及其标准接口;而应用开发者就可以基于这个框架开发出各种应用。
2000年9月,SUN公司发布了MIDP的第一个正式版本。
它将J2ME适用的设备定位在至少拥有数百KB RAM和ROM,并具有基本网络和显示功能的移动通信设备上;在该基础上定义了一系列软件接的移动通信设备上;在该上基础上定义了一系列软件接口,其中包括基本输入输出、图形化用户接口、网络、事件机制、文件系统、应用管理系统等之后,随着JAVA技术的不断发展和用户需求的不断提高,SUN公司又于2002年11月发布了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MIDP 2.0: The Game APIby Mikko Kontio-01/09/2003翻译:bolow中国JAVA手机网MIDP 2.0为移动设备提供了众多新的特性,主要表现在媒体的支持,增强的Ui接口,更多的网络协议,OTA以及安全性等方面。
然而最让我们感兴趣的是游戏api的新特性。
本文意在通过一些例子来介绍新的游戏API类及其用法。
例子调试环境为J2ME Wireless Toolkit 2.0 Beta.游戏 API游戏 API 帮助开发者(游戏开发者或者其他需要更好ui界面的开发者)帮助用户快速开发实用并且节省内存以及存储空间的程序界面。
使用MIDP 1.0 game开发者必须定义自己的一套图像类来获得好的界面及程序性能,这必然会增加程序存储方面的开销,使你的jar文件变得更大。
新的游戏api可以解决这些问题。
游戏API的基本思想是游戏界面由图层组成。
背景可以在一个图层上,而游戏人物可以在另一个图层上。
每一个图层都可以分别被游戏API控制。
按照经验,游戏的额场景通常会比手机的屏幕大,所以在传统的方法中控制屏幕的滚动是一件很痛苦的事情。
新的游戏API 一个新的观察窗口(view window),通过它可以看到所有的游戏场景,并且它可以很容易的被移动很定位。
游戏API 的路径为javax.microedition.lcdui.game。
这五个新的类是:GameCanvas, Layer, LayerManager, Sprite, TiledLayer.GameCanvas是一个提供了游戏的基本接口的抽象类。
这个类与Canvas类相比有两个优点:1。
它拥有屏幕缓冲,2。
它可以直接得到设备键盘的物理状态。
Layer是一个定义了游戏元素的抽象类。
Sprite和TiledLayer继承了这个类。
Layer是一个非常常用的类。
LayerManager负责管理Layer对象,并且按照指定的顺序画他们。
Sprite包含了若干帧图像的Layer。
这些帧保存在Image对象中。
通过Sprite类我们可以只使用其中的部分帧,或者通过播放一个帧的序列来创建一个动画。
Sprite类还能检查它是否与其他的Sprite类或者TiledLayers有重合。
TiledLayer和Sprite有点相似,但是它更多的被用来创建背景,比如赛道或者其他更大的区域。
TiledLayer包含一个表格(a grid of cells),我们可以用图像或者文字来填充他。
所以说一个背景或者一个场景是可以用一系列的小图片来创建的。
Handling user input在MIDP 2.0中,传递用户的输入与MIDP 1.0有所不同. 在 1.0 中你需要Canvas的 getGameAction()方法来得到游戏中用户的按键。
在2.0 中你可以调用GameCanvas的getKeyStates()方法来直接得到键盘的状态。
下面是一个示例代码。
首先我们得到键盘的状态,然后通过bit操作判断方向键的状态后作出相应的响应。
protected void keyPressed(int keyCode) {int move = 0;int keyState = getKeyStates();if ((keyState & LEFT_PRESSED) != 0) {// do something}if ((keyState & RIGHT_PRESSED) != 0) {// do something}if ((keyState & UP_PRESSED) != 0) {// do something}if ((keyState & DOWN_PRESSED) != 0) {// do something}}使用屏幕缓存屏幕缓存(off-screen buffer)使得用户可以很方便的创建无闪烁的动画,并且不需要创建额外的类来实现双缓冲。
对象先被画到缓存中,准备好后在刷新到屏幕。
在下面的代码中GameCanvas的getGraphics()用来的到一个显示缓存。
在while 循环中,缓冲用来绘制LayerManager (layers object)的组件. 然后缓存被flushGraphics()方法刷新。
调用flushGraphics(int x, int y, int width, int height)方法可以只把指定的区域刷新到屏幕上。
public void run() {Graphics g = getGraphics();while (play) {try {// First draw all the layerslayers.paint(g, 0, 0);// If the game is on, flush the graphicsif (play) {flushGraphics();}try {mythread.sleep(sleepTime);} catch (ng.InterruptedException e) {}} catch (Exception e) {e.printStackTrace();}}}使用图层在一个游戏中(或者其他的图形程序),显示区域内通常包含不同的内容(图像可能是有关联的或者是没有关联的)。
比如一只蜜蜂可以在森林,陆地,水面上飞翔,但是在一个迷宫中人却不能穿越围墙。
MIDP 2.0游戏 API为此引进了图层。
图层提供了控制屏幕上的对象或者上下文的方法。
图层可以是TiledLayer (比如背景), Sprite (比如飞机), 或者通过继承Layer类自定义的类.下面代码是对图层使用的示例,本例中最重要的类是TiledLayer, LayerManager, 以及Image. Image是用来保存具有相同大小的图像或者图象元素的类。
TiledLayer使用这些图像来布置背景当TiledLayer的实例被创建以时,构造方法要求五个参数,列数,行数,图像,图像元素的宽度和高度。
这里的例子中背景表格包含40 行, 16 列, 图像时Tiles.png并且长宽都是7。
代码开头的一些常量(TILE_GROUND etc.) 表示对图像元素的引用。
当TiledLayer实例被创建后,图像元素的表格可以用fillCells()方法来填充或者fillCell()来填充。
在代码的最后TiledLayer被加入到LayerManager. append()方法用来把图层加入到观察窗口最下面。
使用insert()可以把图层插入到指定位置。
private TiledLayer tiles;private LayerManager layers;private Image tilesImage;public final int TILE_GROUND = 1;public final int TILE_WATER = 2;public final int TILE_SHORE_LEFT = 3;public final int TILE_FOREST = 4;public final int TILE_AIR = 5;public final int TILE_SHORE_RIGHT = 5;// ...// Creating an instance of the TiledLayerlayers = new LayerManager();try {tilesImage = Image.createImage("/Tiles.png");} catch (IOException e) {}tiles = new TiledLayer(40, 16, tilesImage, 7, 7);// ...// Filling the TiledLayer with tilestiles.fillCells(0, 0, 40, 16, TILE_AIR);tiles.fillCells(14, 12, 12, 4, TILE_WATER);tiles.fillCells(0, 10, 14, 6, TILE_GROUND);// and more tiles like FOREST and the shores...layers.append(tiles);效果如下。
使用精灵正如前面提到的那样, 精灵被定义为屏幕上的一个单独的对象. 这个对象可以是推石头的小人, 一架正在射击的飞机。
Sprite类的工作方式有点类似TilesLayer ( 实事上他们都是从Layer类继承来的). Sprite也拥有一个包含几副等大小的图像的Image 对象。
但是这些图像与组成背景的图像元素不同, 他们是表现游戏主角的动画的帧。
因此精灵可以拥有动画效果,并且通过更换其中的一些帧就可以轻松改变精灵的形象。
下面代码展示了怎么创建一个Sprite的实例。
原理其实和TiledLayer一样.try {spriteImage = Image.createImage("/Sprite.png");} catch (IOException e) {}sprite = new Sprite(spriteImage, 7, 7);Layer类中的以下两个方法可以轻松的控制精灵的移动:move(int dx, int dy)setPositions(int x, int y)通过LayerManager来控制精灵的移动,绘制使非常方便的。
下面的代码展示了怎样去控制一个精灵的移动。
精灵的大小为7×7,并且每次移动的幅度也是7个象素public static final int UP = 0;public static final int RIGHT = 1;public static final int DOWN = 2;public static final int LEFT = 3;// ...switch (direction){case UP:sprite.move(0, -7);break;case DOWN:sprite.move(0, 7);break;case RIGHT:sprite.move(7, 0);break;case LEFT:sprite.move(-7, 0);break;default: break;}游戏编写中还有一个重要的任务就是发现精灵间的碰撞。
精灵可能必须呆在某个游戏区域或者指定的迷宫,同时判断精灵间的相互碰撞也是非常重要的。
碰撞在有的游戏中意味着转换方向,有时候却意味着game overSprite提供了以下四个方法,使我们可以对精灵的碰撞作出判断:collidesWith(Image image, int x, int y,boolean pixelLevel)collidesWith(Sprite s, boolean pixelLevel)collidesWith(TiledLayer t, boolean pixelLevel)defineCollisionRectangle(int x, int y,int width, int height)当两个Sprite的实例(也可以时TiledLayer,Sprite,Image)碰撞或者说重合时,我们可以对此作出响应。