如何使用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 [j]=0;
                                          for(int i=0;i<CANVAS_SIZE_WIDTH;i++)
                          Gridmatrix[CANVAS_SIZE_HEIGHT-1]=COLOR_DARK_GRAY;
                                          for(int i=0;i<CANVAS_SIZE_HEIGHT;i++) {
                                             Gridmatrix[0]=COLOR_DARK_GRAY;
                                             Gridmatrix[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[j]!=0)
                                      draw3DBlock(g,Gridmatrix[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[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;
                  }  
              }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值