如何使用J2ME中的線程

 

如何使用J2ME中的線程

 林剛 { [email protected]} 引用需要註明作者,出處

線程在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.0CLDC1.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 2005713, 上午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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章