您的位置:首页 > 其它

如何使用J2ME中的线程

2005-07-19 15:20 483 查看

 
如何使用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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息