分享
 
 
 

如何使用J2ME中的线程

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

如何使用J2ME中的线程

林刚 { lirincy@163.com} 引用需要注明作者,出处

线程在J2ME开发中是不可或缺的一部分,J2ME继承了J2SE中关于java.lang中的Runnable接口,以及Thread类。但是,由于J2ME应用的特殊性,J2ME

程序中去除了部分API,没有线程组的概念,也没有daemon线程。

今天,我们从一个例子出发,来学习J2ME当中的线程的概念。我们选取的例子是俄罗斯方块。首先,有一些要注意的事项:

1.注意一点,要注意在J2me中不要使用浮点数,这样可以通过编译,但是不能通过预验证。因为一般手持设备都无法负担浮点运算的高负荷。

2.在J2ME程序当中,绝大多数的空间为图片所占有,我们可以看到,今天我们的例子没有任何图片,仅仅5k,如果是开发产品,不可避免的要使用图片,

但是尽量使用压缩率高的png图片,而且不要太过复杂,因为复杂的图片会使得图片变得很大。

3.在程序中尽量使用常量特别是位置信息,这样当作修改的时候只要改一个量就可以了,而且当移植到其他平台的时候也会减少很多工作量.还有就是颜色

信息等.不用每次记忆,重新构造,因为J2me中的颜色和j2se的不太一样.没有常量定义.

4.游戏产品经常需要保护版权,而当今的很多反编译工具可以轻而易举地把jar文件的内容反编译过来,因此可以对程序进行模糊化处理,使得无法反编译

或者反编译后无法理解.可以右键点击项目,在属性中选择Build|Obfuscating,选择模糊化级别.

5.讲解中我们都使用NetBeans作为开发平台,有关安装事宜请访问www.netbeans.org.

好,我们开始吧。

A. 首先,建立一个新的移动应用程序项目,取名Tetris, 不要自动创建Hello程序,选取MIDP1.0和CLDC1.0.

B. 新建一个包,方法是右键点击项目,选取New|Java Package,取名Tetris.

C. 新建一个Midlet,同上,选取New|Java

Midlet, 取名TetrisMidlet.

D. 我们需要一个能够显示游戏的Canvas, 因此新建一个Class名叫TetrisCanvas,

在TetrisMidlet.java中将TetrisCanvas作为当前可以显示的元素:

现在的TetrisMidlet.java如下:

package

Tetris;

import

javax.microedition.midlet.*;

import

javax.microedition.lcdui.*;

/**

*

* @author lin

* @version

*/

public

class TetrisMidlet extends MIDlet {

public void startApp() {

Display display = Display.getDisplay( this );

//

TetrisCanvas extends Canvas which extends Displayable so it can

//

be displayed directly

display.setCurrent(

new TetrisCanvas());

}

public void pauseApp() {

}

public void

destroyApp(boolean unconditional) {

}

}

由于TetrisCanvas继承了Canvas,所以可以被TetrisMidlet所显示.

E.

这里,我们需要将TetrisCanvas继承Canvas,并且实现Canvas的接口函数paint(),我们现在有了一个TetrisCanvas的框架了。

package

Tetris;

import

javax.microedition.lcdui.*;

public

class TetrisCanvas extends Canvas {

/** Creates a new instance

of TetrisCanvas */

public TetrisCanvas() {

}

protected void

paint(Graphics g){

}

}

下面我们需要使得TetrisCanvas具有Thread的特性,这里有两种方法,一种是让TetrisCanvas继承Thread类,然后生成它的实例,但是由于它已经

继承了Canvas类,而Java中不允许多重继承,因此,我们在编程当中通常采取第二种做法,也就是让它实现Runnable接口,在成员中声明一个Thread

成员,实例生成指向自己,然后实现run方法。

也就是这样:

public

class TetrisCanvas extends Canvas implements Runnable {

private

Thread Blocker = null;

...

public

TetrisCanvas(){

Blocker = new Thread(this);

Blocker.start();

}

...

public

void run(){

while

(Blocker != null) {

}

}

...

}

F. 程序逻辑:下面给出程序清单。程序中我们使用一个数组来存储方块的信息,一共有十九种,还有一个数组来存储当前的画面方格的内容.在程序中

有一个paint方法来实现重画,注意绘制的先后次序,当程序规模变得很大的时候,重画的效率就非常重要,需要进行优化.我们在程序中使用了背景,

在没有背景的情况下,程序仅5k,采用背景后,程序47k,可见对图片的优化至关重要.

/*

* TetrisCanvas.java

*

* Created on 2005年7月13日, 上午11:31

*

* To change this template, choose Tools |

Options and locate the template under

* the Source Creation and Management

node. Right-click the template and choose

* Open. You can then make changes to the

template in the Source Editor.

*/

package

Tetris;

import

java.util.*;

import

java.lang.Math;

import

javax.microedition.lcdui.*;

/**

*

* @author lin

*/

public

class TetrisCanvas extends Canvas implements Runnable{

private Thread Blocker =

null;

private Random generator;

private int FutureBlockType,

BlockType,LastType,LastX,LastY,BlockX,BlockY ;

private int

BlockLines,BlockScore;

private int

BlockSpeed,CurSpeed;

private static final int

COLOR_GRAY

= 0x00eeeeee;

private static final int

COLOR_RED

= 0x00ff0000;

private static final int

COLOR_BLACK =

0x00000000;

private static final int

COLOR_WHITE =

0x00ffffff;

private static final int

COLOR_BLUE

= 0x000000ff;

private static final int

COLOR_LIGHT_BLUE= 0x0089a5d1;

private static final int

COLOR_DARK_GRAY = 0x00808080;

private static final int

COLOR_BACKGROUND= COLOR_LIGHT_BLUE;

private static final int

BLOCK_SIZE = 7;

private static final int

CANVAS_SIZE_WIDTH = 12;

private static final int

CANVAS_SIZE_HEIGHT = 22;

private static final int

CANVAS_OFFSET_X = 5;

private static final int

CANVAS_OFFSET_Y = 7;

/**

* The paint status.

*/

boolean ISCLEAR = false;

boolean ISDOWN = false;

boolean ISDEL = false;

/**

* the block

information matrix.

*/

int

BlockInfo[][]={{1,0,1,1,1,2,1,3,0xff0000,2},

{0,1,1,1,2,1,3,1,0xff0000,4},

{0,0,0,1,1,1,1,2,0x0000ff,2},

{0,1,1,0,1,1,2,0,0x0000ff,3},

{0,1,0,2,1,0,1,1,0x00ff00,2},

{0,0,1,0,1,1,2,1,0x00ff00,3},

{0,0,0,1,1,0,1,1,0xffff00,2},

{0,1,1,0,1,1,1,2,0x00ffff,2},

{0,1,1,0,1,1,2,1,0x00ffff,3},

{1,0,1,1,1,2,2,1,0x00ffff,3},

{0,1,1,1,1,2,2,1,0x00ffff,3},

{0,1,0,2,1,1,2,1,0xff00ff,3},

{0,0,1,0,1,1,1,2,0xff00ff,3},

{0,1,1,1,2,0,2,1,0xff00ff,3},

{1,0,1,1,1,2,2,2,0xff00ff,3},

{0,0,0,1,1,1,2,1,0xffffff,3},

{1,0,1,1,1,2,2,0,0xffffff,3},

{0,1,1,1,2,1,2,2,0xffffff,3},

{0,2,1,0,1,1,1,2,0xffffff,3},

};

// Gridmatrix 中只存储颜色信息

int Gridmatrix[][]=new

int[CANVAS_SIZE_HEIGHT][CANVAS_SIZE_WIDTH];

/**

* Initialize the

applet. Resize and load images.

*/

public void init() {

BlockType=Math.abs(generator.nextInt()%19);

FutureBlockType=Math.abs(generator.nextInt()%19);

LastType=BlockType;

BlockLines=0;

BlockScore=0;

BlockSpeed=1;

CurSpeed=BlockSpeed;

BlockX=4; LastX=BlockX;

BlockY=0; LastY=BlockY;

//初始化Gridmatrix矩阵,内容为带边框的主绘图区。

for(int

i=0;i<CANVAS_SIZE_HEIGHT;i++)

for(int

j=0;j<CANVAS_SIZE_WIDTH;j++)

Gridmatrix[i][j]=0;

for(int

i=0;i<CANVAS_SIZE_WIDTH;i++)

Gridmatrix[CANVAS_SIZE_HEIGHT-1][i]=COLOR_DARK_GRAY;

for(int

i=0;i<CANVAS_SIZE_HEIGHT;i++) {

Gridmatrix[i][0]=COLOR_DARK_GRAY;

Gridmatrix[i][11]=COLOR_DARK_GRAY;

}

}

/** Creates a new instance

of TetrisCanvas */

public TetrisCanvas() {

generator = new Random( System.currentTimeMillis() );

init();

Blocker = new Thread(this);

Blocker.start();

}

private void

draw3DBlock(Graphics g, int c, int x, int y, int width, int height){

int

color = g.getColor();

g.setColor( COLOR_WHITE );

g.drawRect( x, y, width, height );

g.setColor(c);

g.fillRect( x + 1, y + 1, width-2, height-2 );

g.setColor( COLOR_BLACK );

g.drawLine( x + width-1, y, x + width-1, y + height-1 );

g.drawLine( x, y + height-1, x + width-1, y + height-1 );

g.setColor(color);

}

public static boolean

drawText(Graphics g, String str, int x, int y, int anchor, int color, int size)

{

Font

f_old,f_new;

int

c_old;

try

{

f_old = g.getFont();

f_new =

Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,size);

g.setFont(f_new);

c_old = g.getColor();

g.setColor(color);

g.drawString(str, x, y, anchor );

g.setColor(c_old);

g.setFont(f_old);

return true;

}catch (Exception ex) {

return false;

}

}

protected void

paint(Graphics g){

//画背景

try{

Image

image_Splash = Image.createImage("/back.png");

g.drawImage(image_Splash, 0, 0,Graphics.TOP | Graphics.LEFT);

}

catch(Exception ex) {

}

//画下一个要出现的方块

drawText(g, "下一个", 91, 5, Graphics.TOP| Graphics.LEFT, COLOR_BLUE,

Font.SIZE_SMALL);

g.setColor(COLOR_GRAY);

g.drawRoundRect(91, 18, 26, 30, 2, 2);

g.setColor(COLOR_DARK_GRAY);

g.fillRoundRect(92, 19, 24, 28, 2, 2);

for(int

i=0;i<=3;i++)

draw3DBlock(g,

BlockInfo[FutureBlockType][8],

93+BlockInfo[FutureBlockType][i*2+1]*BLOCK_SIZE,

20+BlockInfo[FutureBlockType][i*2]*BLOCK_SIZE,

BLOCK_SIZE,BLOCK_SIZE);

drawText(g, "速度:"+String.valueOf(CurSpeed), 91, 60, Graphics.TOP|

Graphics.LEFT, COLOR_BLUE, Font.SIZE_SMALL);

drawText(g, "行数:"+String.valueOf(BlockLines), 91, 75, Graphics.TOP|

Graphics.LEFT, COLOR_BLUE, Font.SIZE_SMALL);

drawText(g, "成绩:", 91, 90, Graphics.TOP| Graphics.LEFT, COLOR_BLUE,

Font.SIZE_SMALL);

g.setColor(COLOR_GRAY);

g.drawRoundRect(91, 105, 26, 20, 2, 2);

g.setColor(COLOR_DARK_GRAY);

g.fillRoundRect(92, 106, 24, 18, 2, 2);

drawText(g, String.valueOf(BlockScore), 93, 107, Graphics.TOP|

Graphics.LEFT, COLOR_WHITE, Font.SIZE_MEDIUM);

//画当前战况

for(int

i=0;i<CANVAS_SIZE_HEIGHT-1;i++)

for(int j=1;j<CANVAS_SIZE_WIDTH-1;j++)

if (Gridmatrix[i][j]!=0)

draw3DBlock(g,Gridmatrix[i][j],CANVAS_OFFSET_X+j*BLOCK_SIZE,

CANVAS_OFFSET_Y+i*BLOCK_SIZE,

BLOCK_SIZE,BLOCK_SIZE);

if

(!ISDOWN){

//画上新的方块

LastX=BlockX;

LastY=BlockY; LastType=BlockType;

for(int

i=0;i<=3;i++)

draw3DBlock(g,BlockInfo[BlockType][8],

CANVAS_OFFSET_X+BlockX*BLOCK_SIZE+BlockInfo[BlockType][i*2+1]*BLOCK_SIZE,

CANVAS_OFFSET_Y+BlockY*BLOCK_SIZE+BlockInfo[BlockType][i*2]*BLOCK_SIZE,

BLOCK_SIZE,BLOCK_SIZE);

}

}

private boolean feasible(){

for(int

i=0;i<=3;i++)

if

(Gridmatrix[BlockY+BlockInfo[BlockType][i*2]][BlockX+BlockInfo[BlockType][i*2+1]]!=0)

return

false;

return

true;

}

private void delline(){

for(int

i=0;i<=3;i++)

Gridmatrix[BlockY+BlockInfo[BlockType][i*2]][BlockX+BlockInfo[BlockType][i*2+1]]=BlockInfo[BlockType][8];

int

temp=4;

boolean

CanSkip=false;

int

i=CANVAS_SIZE_HEIGHT-2;

while((temp>0)&&(i>=1)){

CanSkip=false;

label1: for(int

j=1;j<=CANVAS_SIZE_WIDTH-2;j++){

if (Gridmatrix[i][j]==0)

{CanSkip=true; i--; break label1;}

}

if (!CanSkip){

temp--;

for(int k=i;k>=1;k--)

for(int l=1;l<=CANVAS_SIZE_WIDTH-2;l++)

Gridmatrix[k][l]=Gridmatrix[k-1][l];

BlockLines++;

BlockScore+=200;

if((BlockScore%2000)<200) CurSpeed++;

}

}

}

public void run() {

while (Blocker

!= null) {

if(!ISDOWN){

BlockY++;

if (!feasible()) {

ISDOWN=true; BlockY--; delline();

try {Thread.sleep(400);} catch

(InterruptedException e){}

}

else{

repaint();

try

{Thread.sleep(950-100*(int)BlockSpeed);} catch (InterruptedException e){}

}

}

else{ BlockScore+=50;

if((BlockScore%2000)<50)

CurSpeed++;

ISDOWN=false;

repaint();

BlockSpeed=CurSpeed;

BlockType=FutureBlockType;

FutureBlockType=Math.abs(generator.nextInt()%19);

BlockX=4; LastX=BlockX;

BlockY=0; LastY=BlockY;

if

(!feasible()) { init();}

}

}

Blocker = null;

}

protected void

keyPressed(int keyCode) {

//处理按下键盘的事件,这是Canvas的实例方法

switch (getGameAction(keyCode)) {//将按键的值转化成方向常量

case Canvas.UP://向上

break;

case Canvas.DOWN://向下

BlockY++;

if (!feasible()) BlockY--;

repaint();

BlockSpeed=9;

//Blocker.run();

break;

case Canvas.LEFT://向左

BlockX--;

if

(!feasible()) BlockX++;

break;

case Canvas.RIGHT://向右

BlockX++;

if

(!feasible()) BlockX--;

break;

case Canvas.FIRE:

int

tempBlockType=BlockType;

if

(BlockType==1) BlockType=-1;

else if (BlockType==3) BlockType=1;

else if (BlockType==5) BlockType=3;

else if (BlockType==6) BlockType=5;

else

if (BlockType==10) BlockType=6;

else if (BlockType==14) BlockType=10;

else if (BlockType==18) BlockType=14;

BlockType++;

if

(!feasible()) BlockType=tempBlockType;

break;

default:

break;

}

repaint(); return;

}

}

参考

J2MEWTK 2.2 documentation.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有