分享
 
 
 

用NetBeans开发平台开发J2ME游戏实例讲解(第四部分)

王朝java/jsp·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

用NetBeans开发平台开发J2ME游戏实例讲解(第四部分)

lirincy@163.com 林刚 2005.07 转载请注明出处作者

(3) 使用rms来记录成绩排行榜

J2ME 记录管理系统(RMS)提供了一种机制,通过这种机制,MIDlet 能够持久存储数据,并在以后检索数据。我们在程序中就需要这样的一个排行榜,

这个排行榜在程序关闭以后仍然能够记录数据,rms正好满足了这个要求,有关rms的信息,请参考:

http://www-128.ibm.com/developerworks/cn/java/j-wi-rms/index.html

http://game.kongzhong.com/content/j2mecontent_730.html

我们在程序中要实现排行榜的功能,需要做的事情有这样几件:

A. 在选项菜单当中加入排行榜,这好办, 在HuaRongDaoMielet.java中加入产生排行榜的代码;

B. 新建一个类,取名Score, 关于新建类的方法,上面的论述中有讲述,我们需要的接口函数很简单,getScore(), setScore()就可以了,注意这

里,rms是字节数组组成的记录体系,因此我们如果要存储整型量,就要有整形到byte[]以及byte[]到整型量的转换,如下:

/**

* 数组到整数.

*/

private int getInt(byte[]

buf, int offset) {

return (buf[offset+0] & 0xff)

<< 24 |

(buf[offset+1] & 0xff) << 16 |

(buf[offset+2] & 0xff) << 8 |

(buf[offset+3] & 0xff);

}

/**

* 整数到数组.

*/

private void putInt(byte[] buf, int offset, int value) {

buf[offset+0]

= (byte)((value >> 24) & 0xff);

buf[offset+1]

= (byte)((value >> 16) & 0xff);

buf[offset+2]

= (byte)((value >> 8) &

0xff);

buf[offset+3]

= (byte)((value >> 0) &

0xff);

}

其中offset是byte[]的偏移量,一个整型量用4个字节来表示。

另外我们需要对rms存储系统进行初始化,在构造函数当中引入open()函数,如下所示:

// 每关成绩 = {int level,int

moves;}

private byte[] scoreRec; // 当前关成绩.

private

static final int SCORE_LEN = 8;

private RecordStore

store; //

记录存储,没有打开时为空.

/*

* 构造函数.

*/

Score() {

store

= null;

scoreRec = new byte[SCORE_LEN];

putInt(scoreRec,

0, 0);

putInt(scoreRec,

4, 0);

open();

}

/**

* 打开存储记录

*/

boolean open() {

try

{

store

= RecordStore.openRecordStore("HuaRongDaoScore", true);

} catch (RecordStoreException

ex) {

}

if

(store == null)

return

false;

return

true;

}

可以看出,我们的每个记录长度是8个字节,都是整型量,第一个是关,第二个是成绩,最后的结构类似于:

关 步数

0 33

1 98

2 109

3 77

...

最后,在这个类中最重要的两个函数readScore()和setScore(), 分别负责读取和设置某一关的成绩。在这两个函数当中,我们要注意在rms

中遍历某个元素的方法,你需要自己设个标记TAG,来标记你的记录,因为rms不象数组一样,可以按照下标来索引,rms的几个函数包括

getRecord()

getRecordSize()

enumerateRecords()

addRecord()

setRecord()

等等都要知道是做什么用的。

/**

* 读取某级别的成绩.

*/

public int readScore(int

level) {

try {

// 查找成绩

RecordEnumeration

enm = store.enumerateRecords(null, null, false);

while

(enm.hasNextElement()) {

int ndx

= enm.nextRecordId();

if (store.getRecordSize(ndx) == SCORE_LEN) {

int l = store.getRecord(ndx, scoreRec, 0);

if (l == SCORE_LEN && getInt(scoreRec, 0) == level)

return getInt(scoreRec, 4);

}

}

// 没有这一关的成绩,新建

putInt(scoreRec, 0, level);

putInt(scoreRec, 4, 0);

store.addRecord(scoreRec, 0, SCORE_LEN);

return 0;

}

catch (RecordStoreException ex) {

ex.printStackTrace();

return

-1;

}

}

/**

* 设置某级别的成绩.

*/

boolean

setScore(int level, int moves) {

try

{

// 查找成绩

RecordEnumeration enm = store.enumerateRecords(null, null, false);

while (enm.hasNextElement()) {

int ndx = enm.nextRecordId();

if (store.getRecordSize(ndx) ==

SCORE_LEN) {

int l = store.getRecord(ndx, scoreRec, 0);

if (l == SCORE_LEN && getInt(scoreRec, 0) == level)

//只存储较小的值

if ( getInt(scoreRec,4)

== 0 || getInt(scoreRec, 4)

> moves){

putInt(scoreRec, 4, moves);

store.setRecord(ndx, scoreRec,

0, SCORE_LEN);

}

}

}

// 没有这一关的成绩,新建

putInt(scoreRec, 0, level);

putInt(scoreRec, 4, moves);

store.addRecord(scoreRec, 0, SCORE_LEN);

}

catch (RecordStoreException ex) {

ex.printStackTrace();

return

false;

}

return true;

}

C. 最后要看看这个Score类怎样使用,我们需要在主Midlet里面初始化它,然后在ConrolLogic.java中 设置成绩。

首先,声明这个类成员, 并且进行初始化:HuaRongDaoMidlet.java

public class HuaRongDaoMidlet

extends MIDlet implements CommandListener{

... ...

private

Score score;

/** The Form object for the

Options command */

private

Form optionsForm;

... ...

public

void startApp() {

score = new Score();

... ...

在程序结束时关闭它,

... ...

public

void commandAction(Command c, Displayable d) {

if ( c == CMD_EXIT && d == splash ){

//退出

score.close();

destroyApp(false);

notifyDestroyed();

... ...

然后我们希望控制逻辑ControlLogic能够使用这个Score的实例,因此我们把它作为参数传递给ControlLogic.

... ...

}else if (c == CMD_START && d == splash) {

// 开始新游戏

logic=new ControlLogic(levelChoice.getSelectedIndex()+1, score);

display.setCurrent(logic);

logic.addCommand(CMD_UNDO);

logic.addCommand(CMD_EXIT);

logic.setCommandListener(this);

... ...

最后,在ControlLogic.java当中我们可以开始使用Score类了:

先声明

成员:

...

...

public int

moves=0;//所用的步数.

private Score score;//排行榜

private

History history = new History();

...

...

在初始化时接受参数:

... ...

public ControlLogic(int gameLevel, Score s) {//构造函数

try {

this.level = gameLevel;

score = s;

if ( score == null)

score.open();

... ...

最终我们在成绩被刷新的地方设置成绩。由于我们在Score类的setScore()函数中已经作了刷新成绩判断,这里的调用就很简单。

... ...

protected void paint(Graphics g) {

...

...

//显示步数

Draw.paint(g,String.valueOf(moves), 60, 15, Graphics.BASELINE

| Graphics.HCENTER);

if ( win()) {

isWin=true;

Draw.paint(g,"你赢了!", 60, 70, Graphics.TOP

| Graphics.HCENTER);

score.setScore(level-1, moves);

}

因为我们的关数是1,2,3,4...而rms存储的关数是0,1,2...因此这里有一个 -1的操作。

好了,至此我们的添加排行榜的工程就完成了,下面是HuaRongDaoMidlet.java至此的清单, 调试一下你的程序,看是不是专业了很多呢?

package HuaRongDao;

/*

* HuaRongDaoMidlet.java

*

* Created on 2005年7月1日,

下午8:18

*/

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

import java.io.IOException;

import java.io.InputStream;

import java.lang.InterruptedException;

/**

*

* @author lin

* @version

*/

public class HuaRongDaoMidlet

extends MIDlet implements CommandListener{

private

Display display;

private

SplashScreen splash;

private

ControlLogic logic;

private

Score score;

/** The Form object for the

Options command */

private

Form optionsForm;

/** Set of choices for the

levels */

private

ChoiceGroup levelChoice;

/** Set of lists for the topScores */

private

String topScores;

private final static Command

CMD_EXIT = new Command("退出", Command.EXIT,

1);

private final static Command

CMD_OK = new Command("确认", Command.OK,

1);

private final static Command

CMD_OPTION = new Command("选项", Command.SCREEN,

1);

private final static Command

CMD_START = new Command("开始", Command.SCREEN,

1);

private final static Command

CMD_PAUSE = new Command("暂停", Command.SCREEN,

1);

private final static Command

CMD_UNDO = new Command("上一步", Command.SCREEN,

1);

public HuaRongDaoMidlet(){

display = Display.getDisplay(this);

}

public

void startApp() {

score = new Score();

splash=new SplashScreen();

splash.addCommand(CMD_START);

splash.addCommand(CMD_EXIT);

splash.addCommand(CMD_OPTION);

splash.setCommandListener(this);

display.setCurrent(splash);

}

public

void pauseApp() {

}

public

void destroyApp(boolean

unconditional) {

}

public

void commandAction(Command c, Displayable d) {

if ( c == CMD_EXIT && d == splash ){

//退出

score.close();

destroyApp(false);

notifyDestroyed();

}else if (c == CMD_EXIT && d == logic){

//从游戏中返回

//if (logic.isWin)

logic = null;

display.setCurrent(splash);

}else if (c == CMD_OPTION){

//进入选项

updateOptions();

display.setCurrent(genOptions());

}else if (c == CMD_OK && d == optionsForm)

{

// 从选项回到主界面

display.setCurrent(splash);

}else if (c == CMD_START && d == splash) {

// 开始新游戏

logic=new ControlLogic(levelChoice.getSelectedIndex()+1, score);

display.setCurrent(logic);

logic.addCommand(CMD_UNDO);

logic.addCommand(CMD_EXIT);

logic.setCommandListener(this);

}else

if (c == CMD_PAUSE) {//处理“暂停”

//logic.pause();

}else if (c == CMD_UNDO) {//处理“上一步”

logic.unMove();

}

}

private

Screen genOptions() {

if(optionsForm == null){

optionsForm = new Form("选项");

optionsForm.addCommand(CMD_OK);

optionsForm.setCommandListener(this);

levelChoice = new ChoiceGroup("华容道布局", Choice.EXCLUSIVE);

levelChoice.append("过五关", null);

levelChoice.append("横刀立马", null);

levelChoice.append("水泄不通", null);

levelChoice.append("小燕出巢", null);

levelChoice.append("近在咫尺", null);

levelChoice.append("走投无路", null);

optionsForm.append(levelChoice);

updateOptions();

optionsForm.append(topScores);

optionsForm.append("小毛驴工作室,2005, 版权没有,违者打屁股");

}

return optionsForm;

}

private

void updateOptions() {

topScores = "积分榜\n";

if ( score.readScore(0)!= -1 )

topScores += "过五关最少步数: "+String.valueOf(score.readScore(0))+"\n";

if ( score.readScore(1)!= -1 )

topScores += "横刀立马最少步数:"+String.valueOf(score.readScore(1))+"\n";

if ( score.readScore(2)!= -1 )

topScores += "水泄不通最少步数:"+String.valueOf(score.readScore(2))+"\n";

if ( score.readScore(3)!= -1 )

topScores += "小燕出巢最少步数:"+String.valueOf(score.readScore(3))+"\n";

if ( score.readScore(4)!= -1 )

topScores += "近在咫尺最少步数:"+String.valueOf(score.readScore(4))+"\n";

if ( score.readScore(5)!= -1 )

topScores

+= "走投无路最少步数:"+String.valueOf(score.readScore(5));

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有