程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 如何利用J2ME中的線程

如何利用J2ME中的線程

編輯:J2ME

線程在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;
    }  
  }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved