J2METM 移动信息设备描述(MIDP)和有限联接设备配置(CLDC)分别定义在[MIDPSPEC]和 [CLDCSPEC]规范之中。这些规范定义了MIDP应用的基础部分,而MIDP应用被称为MIDlet。
移动信息设备描述(Mobile Information Device Profile (MIDP))[MIDPSPEC] 为运行在MIDP容 器中的MIDlets应用定义了一个API。此API本身是建立在 CLDC API [CLDCSPEC]之上的。 MIDP用户接口API的Java类设计不是基于Java Abstract Window Toolkit (AWT) 类的, 而是为移动电话和寻呼机这类小型移动信息设备特别设计的。这类设备只有有限的屏幕尺寸和键盘性能。当程序员采用MIDP编写图形应用时,他们只能使用MIDP 或 CLDC API。
MIDP用户接口的基本抽象图形是屏幕。Screen类对面向设备的图形和用户交互进行了封装。每次应用只能显示一个屏幕,而且只能浏览或使用屏幕上的条目。
MIDP API 具有‘高级’( ‘high-level’)和‘低级’( ‘low-level’) UI 类。高级用户接口类 (例如: Form, List, TextBox, TextField, Alert 和 Ticker) 具有设备适配功能,它对图象、文本、文 本域以及单选按扭等进行支持。低级用户接口类(例如:类Canvas)允许操作者任意绘图。在移动电话上运行的MIDle可以具有各种尺寸的彩色、具有灰度的或黑白的屏幕。高级类是一般UI元素的抽象,它便于MIDlet在不同设备之间的可移植性,而且能够确保适配不同设备的‘用户界面’(look-and-feel)。低级API可以更直接地控制屏幕上显示的内容,但MIDlet设计者应该确保不 同设备(显示尺寸、键盘及色彩等存在差异)之间的可移植性。此范例给出了高级和低级API的用法。
MIDP主要有两类屏幕:
• 高级屏幕
o List和TextBox是简单的高级屏幕类。用户不能对此类的屏幕额外增加GUI组件。为了在游戏开始时参与者能够对游戏进行选择,TicTacToe MIDlet范例使用了这样的屏幕类,此屏幕类继承自被称为ChoosePieceScreen的List类。
o 普通的Form屏幕类与List屏幕类相似,但它允许使用额外的图形组件,例如:图象、只读文本字段、可编辑文本字段、可编辑数据字段、可调指示器及选择组等。Form组件项空闲时可以增加或删除。Formz类在 TicTacToe范例中没有使用。
• 低级屏幕
o Canvas 屏幕类 (以及 Graphics 加 Image 类)能够在低级API基础上编写UI。 这些类赋予了MIDlet编程人员最大绘画灵活性。编程人员可以画出各种图形元素:直线、弧线、矩形、圆角矩形、圆、文本文字(不同色彩、字体和大小)、以及 经剪切处理的位图等,大多数游戏MIDlet是按照基于Canvas屏幕类的主GUI元素进行编写的。
MIDlet用户接口通常具有一个或多个屏幕。由于应用每次只能浏览一个屏幕,所以对MIDlet的结构进行周密的设计是非常必要的,这样就很容易处理屏幕之间的内容切换。
看看资料,找了个俄罗斯方块的游戏看了看源码,自己也做了,效果图如下:



部分代码:
public
class
MainMenuCanvas
extends
Canvas
implements
CommandListener
...
{

// 菜单图片的开始位置
private boolean fistloadpicture = true;
private int picturex , picturey ;
//上下左右空白的地方
private int blankleft , blanktop ;
//当前的选项
private int currentchoice ;
private boolean redpicture ;
//当前canvas的大小
private int wide,height ;
//图片变量
private Image image[] = new Image[3] ;
//当前是否活跃
private boolean active = true;
//背景的颜色设成(240,240,0)
private boolean activeerr = false;
//双缓冲
private Image offcanvas ;
private Timer timer ;
private MenuTask menuTask ;
private Command selectcommand = new Command("Select",Command.OK,1) ;
private Command exitcommand = new Command("Exit",Command.EXIT,2) ;
private Miner miner ;
public void restartnow()

...{
active = true ;
activeerr = false ;
currentchoice = 0 ;
redpicture = false ;
}
//构造函数
public MainMenuCanvas()

...{
restartnow( );
timer = new Timer();
menuTask = new MenuTask(this);
timer.schedule(menuTask, 400, 400);
this.addCommand(selectcommand) ;
addCommand(exitcommand) ;
this.setCommandListener(this);
}
public MainMenuCanvas(Miner b)

...{
this.miner = b;
restartnow( );
timer = new Timer();
menuTask = new MenuTask(this);
timer.schedule(menuTask, 400, 400);
this.addCommand(selectcommand) ;
addCommand(exitcommand) ;
this.setCommandListener(this);
}
// 读取图片数据
private boolean readpictures()

...{
if(fistloadpicture)

...{
fistloadpicture = false ;
try

...{
image[0] = Image.createImage("/block/menu/8.png");
image[1] = Image.createImage("/block/menu/9.png");
image[2] = Image.createImage("/block/menu/10.png");
}
catch(Exception e)

...{
return false ;
}
}
return true ;
}

private void Initdata()

...{
wide = this.getWidth() ;
height = this.getHeight() ;
if(wide > image[0].getWidth())

...{
blankleft = ( wide - image[0].getWidth()) / 2 ;
blanktop = ( height - image[0].getHeight()) / 2 ;
//blankleft= 0 ;
//blanktop = 0 ;
}
}
private void clearcanvas(Graphics g)

...{
g.setColor(0,240,240) ;
g.fillRect(0,0,wide,height);
}
private void paintcanvas(Graphics g)

...{
//检查数据合法与否
if(currentchoice > 2)currentchoice = 0 ;
if(currentchoice < 0 ) currentchoice = 2 ;
//画图,使用自制双缓冲
Graphics gg = offcanvas.getGraphics();
clearcanvas(gg);
gg.drawImage(image[currentchoice],blankleft,blanktop,Graphics.LEFT|Graphics.TOP);
g.drawImage(offcanvas,0,0,Graphics.LEFT|Graphics.TOP);
}

protected void paint(Graphics g) ...{
// TODO Auto-generated method stub
if(fistloadpicture)

...{
readpictures();
Initdata();
offcanvas = Image.createImage(wide,height);
}
if( active)

...{
if(!activeerr)

...{
paintcanvas(g);
}
else

...{
g.drawLine(0,0,100,100);
}
}
else
g.drawRect(0,0,100,100);
}
protected synchronized void keyPressed(int keyCode)

...{
switch(this.getGameAction(keyCode))

...{
case Canvas.UP:
currentchoice -- ;
break ;
case Canvas.DOWN:
currentchoice ++ ;
break ;
case Canvas.FIRE :
if( this.currentchoice == 0)//启动游戏
miner.mangeaction(1,0,0) ;
else if( this.currentchoice == 1)//启动帮助
miner.mangeaction(2,0,0);
else if(this.currentchoice == 2)//离开游戏
miner.mangeaction(3,0,0);
break;
}
redpicture = false ;
repaint();
}
//接口
public void Hide()

...{
this.active = false ;
}
public boolean IsOK()

...{
return activeerr ;
}
public synchronized void commandAction(Command c, Displayable d)

...{
if(c.getLabel().equals("Select") || c.getLabel().equals("OK") )

...{
if( this.currentchoice == 0)//启动游戏
miner.mangeaction(1,0,0) ;
else if( this.currentchoice == 1)//启动帮助
miner.mangeaction(2,0,0);
else if(this.currentchoice == 2)//离开游戏
miner.mangeaction(3,0,0);
}
else if(c.getLabel().equals("Exit"))

...{
miner.mangeaction(4,0,0);
}
}


}
package
com.pukka.game.canvas.maingame;

import
java.util.Timer;

import
javax.microedition.lcdui.Canvas;
import
javax.microedition.lcdui.Command;
import
javax.microedition.lcdui.CommandListener;
import
javax.microedition.lcdui.Displayable;
import
javax.microedition.lcdui.Graphics;
import
javax.microedition.lcdui.Image;

import
com.pukka.game.Miner;


public
class
MainGameCanvas
extends
Canvas
implements
CommandListener
...
{

private boolean finished = false;

private boolean gettingrock = false;

private int grade = 1;

private int timeleft = 60;

private int getRock = -1;

private int target = 1;

private int dragcount = 0;

private int manstate = 0;

private Image imagecontent;

private Timer timer;

private Timer timer2;

private int linedirection = 0;

private double linelength = 0;

private int score = 0;

private Image offscreen3;

private Image offscreen2;

Rock[] rock = null;

private Image imageman;

private Image imageman2;

private int angel = 0;

private int direction = 0;

private int picturex, picturey;

private int picturex2, picturey2;

private Image offscreen;

private int wide, height;

private Image[] line = new Image[9];

private Miner miner;

private GameTask gametask;

private RockTask rocktask;

private TotalTimerTask totaltask;

private Command okcommand = new Command("OK", Command.OK, 1);

private boolean statrted = false;

private boolean gameresStarted = false;

private Timer Alltime;


public MainGameCanvas(Miner miner, int grade, int score) ...{
this.grade = grade;
this.score = score;
this.target = target * grade + 1000 * (grade - 1);
this.miner = miner;
wide = this.getWidth();
height = this.getHeight();
if (!statrted)
offscreen = Image.createImage(wide, height);
Alltime = new Timer();
totaltask = new TotalTimerTask(this);
Alltime.schedule(totaltask, 300, 1000);
timer = new Timer();
gametask = new GameTask(this);
timer.schedule(gametask, 300, 30);
this.addCommand(okcommand);
this.setCommandListener(this);
}


public boolean readpictures() ...{

try ...{
imagecontent = Image.createImage("/res/back.png");
imageman = Image.createImage("/res/man.png");
imageman2 = Image.createImage("/res/man2.png");
line[0] = Image.createImage("/res/an90.png");
line[1] = Image.createImage("/res/an60.png");
line[2] = Image.createImage("/res/an45.png");
line[3] = Image.createImage("/res/an30.png");
line[4] = Image.createImage("/res/an0.png");
line[5] = Image.createImage("/res/anz30.png");
line[6] = Image.createImage("/res/anz45.png");
line[7] = Image.createImage("/res/anz60.png");
line[8] = Image.createImage("/res/anz90.png");


} catch (Exception e) ...{
e.printStackTrace();
return false;
}
return true;
}


public void paint(Graphics g) ...{

if (!statrted) ...{
paintload(g);
gamestart(g);

} else ...{
clearBuffer(g);
}
}


private void paintload(Graphics g) ...{

if (readpictures()) ...{

if (wide > imagecontent.getWidth()) ...{
picturex = (wide - imagecontent.getWidth()) / 2;
picturey = (height - imagecontent.getHeight()) / 2;

} else ...{
picturex = picturey = 0;
}
Graphics gg = offscreen.getGraphics();
gg.drawImage(imagecontent, picturex, picturey, 0);
drawscore(gg);
drawman(gg);
offscreen3 = offscreen;
drawRock(gg);
this.gameresStarted = false;
this.statrted = true;
}
}


private void gamestart(Graphics g) ...{
g.drawImage(offscreen, 0, 0, 0);
}


private void clearBuffer(Graphics g) ...{
offscreen2 = offscreen3;
Graphics gg2 = offscreen2.getGraphics();
gg2.drawImage(imagecontent, picturex, picturey, 0);
drawscore(gg2);
redrawman(gg2);
g.drawImage(offscreen2, 0, 0, 0);
redrawRock(g);
drawGou(g);

if (finished) ...{

if (score >= target) ...{
miner.mangeaction(5, 1, this.score);

} else ...{
miner.mangeaction(6, 1, 0);
}
}
}


public void redrawman(Graphics g) ...{

if (linedirection == 1) ...{

if (dragcount >= -1 && dragcount <= 5 && manstate == 0) ...{
drawman(g);
dragcount += 1;

if (dragcount == 6) ...{
manstate = 1;
}
}

if (dragcount >= 0 && dragcount <= 6 && manstate == 1) ...{

if (wide > imageman2.getWidth()) ...{
picturex2 = (wide - imageman2.getWidth()) / 2;
picturey2 = 5;

} else ...{
picturex2 = picturey2 = 0;
}
dragcount -= 1;

if (dragcount == -1) ...{
manstate = 0;
}
g.drawImage(imageman2, picturex2, picturey2, 0);
}

} else ...{
drawman(g);
}

}


public void drawscore(Graphics g) ...{
int i = this.getRock;

if (i != -1 && rock[i].isVisible() == false) ...{
score += rock[this.getRock].getScore();
this.getRock = -1;
}
g.drawString(String.valueOf(score), 7, 8, 0);

g.drawString(String.valueOf(target), 7, 32, 0);

g.drawString(String.valueOf(timeleft), wide - 20, 8, 0);

g.drawString(String.valueOf(grade), wide - 20, 32, 0);

}


public void drawman(Graphics g) ...{

if (wide > imageman.getWidth()) ...{
picturex2 = (wide - imageman.getWidth()) / 2;
picturey2 = 5;

} else ...{
picturex2 = picturey2 = 0;
}
g.drawImage(imageman, picturex2, picturey2, 0);
}


public void drawRock(Graphics g) ...{

if (rock == null || gameresStarted) ...{
Factory fc = new Factory(1);
rock = fc.getRocks();
}

for (int i = 0; i < rock.length; i++) ...{

if (rock[i].isVisible()) ...{
int picturex3, picturey3;
Image imagerock = Rock.KIND_IMAGES[rock[i].getRockType()];

if (wide > (picturex + rock[i].getDrawX())) ...{
picturex3 = (int) (picturex + rock[i].getDrawX());
picturey3 = (int) (picturey + rock[i].getDrawY());

} else ...{
picturex3 = picturey3 = 0;
}
rock[i].setState(1);// init表示已经创建。
g.drawImage(imagerock, picturex3, picturey3, 0);
}
}
}


public void redrawRock(Graphics g) ...{

for (int i = 0; i < rock.length; i++) ...{

if (rock[i].isVisible()) ...{
int picturex3, picturey3;
Image imagerock = Rock.KIND_IMAGES[rock[i].getRockType()];

if (wide > (picturex + rock[i].getDrawX())) ...{
picturex3 = (int) (picturex + rock[i].getDrawX());
picturey3 = (int) (picturey + rock[i].getDrawY());

} else ...{
picturex3 = picturey3 = 0;
}
rock[i].setState(1);// init表示已经创建。
g.drawImage(imagerock, picturex3, picturey3, 0);
}
}
}


public void AllTimerun() ...{
timeleft--;

if (timeleft == 0) ...{
this.finished = true;
totaltask.cancel();
}
}


public void Timerrun() ...{

if ((angel > -80) && (angel < 80) && (direction == 0)) ...{
angel += 1;
}

if ((angel > -80) && (angel < 80) && (direction == 1)) ...{
// 左上方转
angel -= 1;
}

if ((angel == -80) && (direction == 1)) ...{
// 变向
direction = 0;
angel += 1;
}

if ((angel >= 80) && (direction == 0)) ...{
// 变向
direction = 1;
angel -= 1;
}
this.repaint();
}


public void clearCanvas(Graphics g) ...{

}


public void drawGou(Graphics g) ...{
double a = angel * 3.1415926 / 180;
double endpointX = wide / 2 + Math.sin(a) * 20;
double endpointY = 40 + Math.cos(a) * 20;

if (linelength > 0) ...{
endpointX = wide / 2 + Math.sin(a) * (linelength + 20);
endpointY = 40 + Math.cos(a) * (linelength + 20);

if (this.getRock != -1) ...{
rock[this.getRock].setDrawX(rock[this.getRock].getDrawX()
- rock[this.getRock].getWightfactor()
* Math.sin(angel * 3.14159 / 180) * 2);
rock[this.getRock].setDrawY(rock[this.getRock].getDrawY()
- rock[this.getRock].getWightfactor()
* Math.cos(angel * 3.14159 / 180) * 2);

} else ...{
// 判断碰撞,若碰撞则把linedirection改为1;

for (int i = 0; i < rock.length; i++) ...{

if (rock[i].isVisible()) ...{
Image temp = Rock.KIND_IMAGES[rock[i].getRockType()];
boolean inX = (rock[i].getDrawX() < endpointX + 5)
&& ((rock[i].getDrawX() + temp.getWidth() + 5) > endpointX);
boolean inY = (rock[i].getDrawY() < endpointY + 5)
&& ((rock[i].getDrawY() + temp.getHeight()) > endpointY - 5);

if (inX && inY && this.linedirection == 0) ...{
rock[i].setDrawX(rock[i].getDrawX()
- rock[i].getWightfactor()
* Math.sin(angel * 3.14159 / 180) * 2);
rock[i].setDrawY(rock[i].getDrawY()
- rock[i].getWightfactor()
* Math.cos(angel * 3.14159 / 180) * 2);
rock[i].setState(2);
this.getRock = i;
linedirection = 1;
break;
}

}
}

}
}

g.drawLine(wide / 2, 40, (int) endpointX, (int) endpointY);

if ((angel >= -90) && (angel < -70)) ...{
g.drawImage(line[0], (int) endpointX - 12, (int) endpointY - 7, 0);
}

if ((angel >= -70) && (angel < -45)) ...{
g.drawImage(line[1], (int) endpointX - 12, (int) endpointY - 6, 0);
}

if ((angel >= -45) && (angel < -30)) ...{
g.drawImage(line[2], (int) endpointX - 12, (int) endpointY - 5, 0);
}

if ((angel >= -30) && (angel < -5)) ...{
g.drawImage(line[3], (int) endpointX - 12, (int) endpointY - 5, 0);
}

if ((angel >= -5) && (angel < 5)) ...{
g.drawImage(line[4], (int) endpointX - 12, (int) endpointY - 3, 0);
}

if ((angel >= 5) && (angel < 30)) ...{
g.drawImage(line[5], (int) endpointX - 5, (int) endpointY - 5, 0);
}

if ((angel >= 30) && (angel < 50)) ...{
g.drawImage(line[6], (int) endpointX, (int) endpointY - 3, 0);
}

if ((angel >= 50) && (angel < 70)) ...{
g.drawImage(line[7], (int) endpointX - 2, (int) endpointY - 8, 0);
}

if (angel >= 70) ...{
g.drawImage(line[8], (int) endpointX - 2, (int) endpointY - 9, 0);
}

}


protected synchronized void keyPressed(int keyCode) ...{

switch (this.getGameAction(keyCode)) ...{
case Canvas.UP:
break;
case Canvas.DOWN:

try ...{

if (!gettingrock) ...{
timer.cancel();
this.getRock();
}

} catch (Exception e) ...{
e.printStackTrace();
}
break;
}
;
}


public void commandAction(Command c, Displayable arg1) ...{
System.out.println(c.getLabel());

if (c.getLabel().equals("OK")) ...{
gameresStarted = true;
this.repaint();
}
}


public void timer_restart() ...{
timer = new Timer();
gametask = new GameTask(this);
timer.schedule(gametask, 0, 30);
this.gettingrock=false;
}


public void getRock() ...{
timer2 = new Timer();
rocktask = new RockTask(this);
timer2.schedule(rocktask, 0, 50);
gettingrock = true;
}


public void GetRockRun() ...{
double a = Math.abs(angel) * 3.1415926 / 180;
double maxX = wide / (2 * Math.sin(a));
double maxY = (height - 40) / Math.cos(a);
double factor = 2;

if (this.getRock != -1) ...{
factor = rock[this.getRock].getWightfactor();
}

if ((0 <= linelength) && (linedirection == 0)) ...{
linelength += 5;
}
if (((linelength >= maxX) || (linelength >= maxY))

&& (linedirection == 0)) ...{
linedirection = 1;
linelength = linelength - 5;
}

if ((0 < linelength) && (linedirection == 1)) ...{
linelength = linelength - 2 * factor;
}

if ((0 >= linelength) && (linedirection == 1)) ...{

if (this.getRock != -1) ...{
rock[this.getRock].setVisible(false);
}
linelength = 0;
linedirection = 0;
timer2.cancel();
timer_restart();
}
this.repaint();
}

}
目前已经完成基本游戏和部分j2me 的socket通信功能,主要为了联机游戏功能。如需完整源码或想玩该游戏,可以留言,大家一起看看。