站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Netbeans 专题用NetBeans开发平台开发J2ME游戏实例讲解(第四部分)

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

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

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 200571, 下午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));

}

}

↑返回目录
前一篇: NetBeans 4.0创建J2ME手机RSS阅读器
后一篇: 在NetBeans平台上开发J2ME游戏实例讲解(第三部分)