j2me手机游戏开发之俄罗斯方块--附完整源代码

本文介绍了一个基于J2ME平台的俄罗斯方块游戏实现。主要内容包括游戏界面设计、关键类的定义与实现,如GIF播放器类、游戏逻辑类等。此外还提供了完整的源代码下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 原理比较简单的,就是一个基于Frame的游戏,

主游戏画面设计如下:

 //FIELD: 22X17                      //
 //////////////////////////////////////
 //1                                          1         0 //
 //2                                          2  TETRIS 0 //
 //3                                          3  DANY   0 //
 //4 ____________________4________0 //
 //5                                          5 NEXT:   0 //
 //6                                          6         0 //
 //7                                          7 1 2 3 4 0 //
 //8                                          8 2     2 0 //
 //9                                          9 3     3 0 //
 //0                                          0 1 2 3 4 0 //
 //1   PRESS ANY KEY        1         0 //
 //2     TO  START                2 SCORE:  0 //
 //3                                          3 9000000 0 //
 //4                                          4 LEVEL:  0 //
 //5                                          5 1       0 //
 //6                                          6 LINES:  0 //
 //7                                          7 00:00   0 //
 //8                                          8 RECORD: 0 //
 //9                                          9 999999  0 //
 //0                                          0PRESS ESC0 //
 //1                                          1 TO MENU 0 //
 //2 1 2 3 4 5 6 7 8 9 0 2 2 3 4 5 6 //
 //////////////////////////////////////

 

所有的数据处理和绘图都基本于在Frame里完成.主流程如下:

 

 


//
//生成实例
//
CGameField gamefiled = new CGameField();
CJ2meGameDrawer drawer = new CJ2meGameDrawer();
CJ2meGameSoundPlayer player = new CJ2meGameSoundPlayer();

//
//初始化和设置环境
//
gamefiled.setup(width, height,drawer,player);


//
//在重绘事件发生时调OnFrame处理
//

void OnPaint(Graphics g)
{
  gamefiled.OnFrame();
}


游戏很简单的,其中有些难点问题,其它文章都在提及.

完整源代码及编译脚本和图片声音资源:

下载地址:

http://download.youkuaiyun.com/source/682898

源代码文件是从moto的sdk的某个文件复制了一些import和一个空的midlet类进行修改的,呵呵,保留了它的版本信息

 

(上传的文件给删除了,我....贴一下源码.)

 

 

package com.Tetris;

import javax.microedition.lcdui.*;
import javax.microedition.media.Manager;
import javax.microedition.midlet.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

import javax.microedition.lcdui.game.Sprite;


import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.StopTimeControl;
import javax.microedition.media.control.VolumeControl;
import javax.microedition.rms.RecordStore;

import javax.microedition.media.PlayerListener;

 

public class TetrisGame extends MIDlet implements CommandListener {

 private Display display;

 public static final Command exitCommand = new Command("Exit", Command.EXIT,
   1);

 public TetrisGame() {
 }

 public void commandAction(Command c, Displayable d) {
  if (c == exitCommand) {
   exitMIDlet();
  }
 }

 protected void destroyApp(boolean unconditional)
   throws MIDletStateChangeException {
  exitMIDlet();
 }

 public void exitMIDlet() {
  notifyDestroyed();
 }

 public Display getDisplay() {
  return display;
 }

 protected void initMIDlet() {
  Canvas c = new TetrisCanvas();
 
  c.addCommand(exitCommand);
  c.setCommandListener(this);
  getDisplay().setCurrent(c);
  //System.out.println("hasRepeatEvents "+c.hasRepeatEvents());
 }

 protected void pauseApp() {
 }

 protected void startApp() throws MIDletStateChangeException {
  if (display == null) {
   display = Display.getDisplay(this);
   initMIDlet();
  }
 }
 

 class TetrisCanvas extends Canvas implements Runnable {

  private static final int SLEEP_INITIAL = 100;
  private Graphics graphics=null;
  private int sleepTime = SLEEP_INITIAL;

  private volatile Thread thread;
  private boolean bDownPressed=false;
  private boolean bLeftPressed=false;
  private boolean bRightPressed=false;
  private boolean bOnkeyDown=false;
  
  CGameField  gamefield ;
  CGameJ2meDrawer gamedrawer ;
  CGameJ2meSoundPlayer soundPlayer;
  public TetrisCanvas() {
   //System.out.println("TetrisCanvas() "+ Thread.currentThread());
   this.setFullScreenMode(true);
   if(gamefield ==null||gamedrawer==null)
   {
    gamefield = new CGameField();
    try {
     gamedrawer = new CGameJ2meDrawer();
     soundPlayer = new CGameJ2meSoundPlayer();
     gamefield.Setup(this.getWidth(), this.getHeight(), gamedrawer,soundPlayer);
     gamedrawer.setup(graphics);
     soundPlayer.setup();
     
     
    } catch (Exception e1) {
     // TODO Auto-generated catch block
     e1.printStackTrace();
    } 
   }
  }
  
  protected void keyPressed(int keyCode)
  {
   //System.out.println("keyPressed: "+ keyCode);
   int gameaction = getGameAction(keyCode);
   if(gameaction==GAME_B)
   {
    exitMIDlet();
   }
   else
   {
  
    switch(gameaction)
    {
    case LEFT:
     bLeftPressed = true;
     bOnkeyDown  = true;
     gamefield.OnKeyDown(TETRIS_KEYCODE.Left);
     break;
    case RIGHT:
     bRightPressed = true;
     bOnkeyDown  = true;
     gamefield.OnKeyDown(TETRIS_KEYCODE.Right);
     break;
    case UP:
     gamefield.OnKeyDown(TETRIS_KEYCODE.Up);
     break;
    case DOWN:
     bDownPressed = true;
     bOnkeyDown  = true;
     gamefield.OnKeyDown(TETRIS_KEYCODE.Down);
     break;
    case GAME_A:
     gamefield.OnKeyDown(TETRIS_KEYCODE.Escape);
     break;
    case FIRE:
    case GAME_C:
    case GAME_D:
     gamefield.OnKeyDown(TETRIS_KEYCODE.Rotate);
     break;
    default:
     gamefield.OnKeyDown(TETRIS_KEYCODE.Unk);
     break;
    }
   }
   
   if(gamefield.bExit)
   {
    exitMIDlet();
   }
  }
  
  protected void pointerPressed(int x, int y)
  {
   gamefield.OnPointerPressed(x,y);
   if(gamefield.bExit)
   {
    exitMIDlet();
   }
  }
       
  protected void keyReleased(int keyCode)
  {
   //System.out.println("keyReleased: "+ keyCode);
   int gameaction = getGameAction(keyCode);
   switch(gameaction)
   {
   case LEFT:
    bLeftPressed = false;
    break;
   case RIGHT:
    bRightPressed = false;
    break;
   case DOWN:
    bDownPressed = false;
    break;
   }
  }
  
  // The game loop.

  public void run() {
   //System.out.println("run: "+ Thread.currentThread());
   while(true) //(thread == Thread.currentThread())
   {
    
    this.repaint();
    try {
     Thread.sleep(sleepTime);
    } catch (InterruptedException e) {
    }
   }
  }

  // When the canvas is shown, start a thread to
     // run the game loop.

     protected void showNotify()
     {
         thread = new Thread(this);
         thread.start();
     }
     // When the game canvas is hidden, stop the thread.
     //
     protected void hideNotify()
     {
         thread = null;
     }

    
  protected void paint(Graphics arg0) {
   
  
   
   if(arg0!=null && gamedrawer!=null && gamefield!=null)
   {
    
    gamedrawer.graphics = arg0;
    
    if(!bOnkeyDown)
    {
     if(bLeftPressed)
     {
      gamefield.OnKeyDown(TETRIS_KEYCODE.Left);
     }
     else if(bRightPressed)
     {
      gamefield.OnKeyDown(TETRIS_KEYCODE.Right);
     }
     
     if(bDownPressed)
     {
      gamefield.OnKeyDown(TETRIS_KEYCODE.Down);
      gamefield.OnKeyDown(TETRIS_KEYCODE.Down);
     }
    }
    else
    {
     bOnkeyDown=false;
    }
    
    gamefield.OnGameFrame();
   }
  }


 }
}


//class EffectSoundEvent
//{
// public long effetDuraction;
// public long effetStartTime;
// public int  key;
//};

class EffetSoundPlayer implements PlayerListener
{

//    START
//    50   FELL          0
//    242  LINEFULL      2000
//    750  LEVELUP       4000
//    3982 GAMEOVER      6000
//    11620 GAMEWIN      16000
 long []effetStartTime={
    500000,
   2000000,
   4000000,
   6000000,
  11000000,
 };
 
 long []effetDuraction={
   50,
   242,
   750,
   3982,
   11620,
  };

  public Player  player=null;
  public boolean bEffectEnabled=true;
  public int  currentKey=0;
  long           stoptick = 0;
  public void Setup()
  {
 
   //System.out.println("create player " + iKey);
 
   try {
    player = Manager.createPlayer(getClass().getResourceAsStream(
      "/audio/effects.wav"), "audio/x-wav");
    player.addPlayerListener(this);
   
    player.setLoopCount(1);
    player.realize(); // realize
    player.prefetch(); // prefetch
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (MediaException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 
   public void playSound(int iKey) throws Exception {

  
  if(!bEffectEnabled || iKey<0||iKey>=effetStartTime.length)
   return;
  
  //System.out.println(""+CGameField.nFrame+ " playSound key: " + iKey);
   
  currentKey = iKey;
  long st = effetStartTime[iKey];
  stoptick = System.currentTimeMillis() + effetDuraction[iKey]+1000;
  player.setMediaTime(st);
//  long act = player.setMediaTime(st);
  //System.out.println(""+CGameField.nFrame+ " exp set: " + st + " actual: "+act);
  
  
  if(player.getState()==Player.PREFETCHED)
  {
   player.start(); // and start 
  }

  
 }
  
 public void tryToStop()
 {
  if(player!=null
    &&player.getState()==Player.STARTED
    &&System.currentTimeMillis()>=stoptick )
  {
   try {
    player.stop();
   } catch (MediaException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 
  public void playerUpdate(Player player, String event, Object eventData) {
 
     //System.err.println(""+CGameField.nFrame+" event:" + event);
 
     if(event.equals(STARTED))
  {
     //  long cur = player.getMediaTime();
       //System.err.println("current :"+cur);
       stoptick = System.currentTimeMillis() + effetDuraction[currentKey]+50;
//      StopTimeControl sc = (StopTimeControl)player.getControl("StopTimeControl");
      //System.err.println("current :"+sc);
      //sc.setStopTime(cur+effetDuraction[currentKey]*1000);
  }

     if (event.equals(END_OF_MEDIA)) {
      
     }
 }
 
}


class CGameJ2meSoundPlayer extends CGameSoundPlayer
{
 EffetSoundPlayer effectPlayer = new EffetSoundPlayer();
 boolean bmgEnable = true;
 Player bgmPlayer = null;


 public void setup()
    {
     try {      
      try {
       
       InputStream is = getClass().getResourceAsStream("/audio/bgm.wav");
       bgmPlayer = Manager.createPlayer(is, "audio/x-wav");
       bgmPlayer.realize();
       bgmPlayer.prefetch();
       bgmPlayer.setLoopCount(-1);
       VolumeControl vc = (VolumeControl) bgmPlayer.getControl("VolumeControl");
       vc.setLevel(5);
       effectPlayer.Setup();
       
   } catch (MediaException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }


 public void PlayEffectSound(int soundKey)
 {
  try {
   effectPlayer.playSound(soundKey);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 public void StopEffectSound()
 {
  try {
   effectPlayer.player.stop();
  } catch (MediaException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 public void ControlEffectSound()
 {
  try {
   effectPlayer.tryToStop();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public void SetVolume(int level)
 {
  VolumeControl vc = (VolumeControl) bgmPlayer.getControl("VolumeControl");
  vc.setLevel(level);
  vc = (VolumeControl) effectPlayer.player.getControl("VolumeControl");
  vc.setLevel(level);
 }
 
 
 
 public void PlayBackgroundMusic()
 {
  if(bmgEnable)
  {
   try {
    if(bgmPlayer.getState()==Player.PREFETCHED )
     bgmPlayer.start();
   } catch (MediaException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 
 public void StopBackgroundMusic()
 {
  try {
   if(bgmPlayer.getState()==Player.STARTED )
    bgmPlayer.stop();
  } catch (MediaException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 public void EnableBgMusic(boolean val)
 {
  bmgEnable = val;
 }
 
 public void EnableEffectSound(boolean val)
 {
  effectPlayer.bEffectEnabled = val;
 }
 

}


class GIFPlayer {

 //   private GifDecoder d;
 private Sprite sp;
    private int ind;
    private int count;
    private long delay;
    private long start;
    private int  left=0;
    private int  top=0;
   
    public boolean isPlaying=false;
    private long stopTime=0;
   
    public void Setup(String lpszfilename,int w, int h,int _delay) {
        start = System.currentTimeMillis();
       
        try {
         Image img = Image.createImage(lpszfilename);
         if(img !=null)
         {
          sp = new Sprite(img,w,h);
         }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
       
//        System.out.println("setup  "+ lpszfilename
//          + " "+ (System.currentTimeMillis() - start));
        ind = 0;
        count = sp.getRawFrameCount();
        delay = _delay;
      
    }
   
    public void Start(int x, int y, long duration)
    {
     ind = 0;
     isPlaying = true;
     left = x;
     top  = y;
     stopTime =  System.currentTimeMillis()+duration;
     sp.setRefPixelPosition(left,top);
    }
   
    public void Stop()
    {
     isPlaying = false;
     ind = 0;
    }

    public void DrawFrame(Graphics g) {
     if(!isPlaying) return;
     
     long now= System.currentTimeMillis();
        if (now - start >= delay) {
            start = System.currentTimeMillis();
           
            //System.out.println("frame = " + ind + "  delay = " + delay);
            ind++;
            if (ind >= count) {
                ind = 0;
            }
            if(now>stopTime)
            {
             isPlaying=false;
             ind = 0;
            }
            sp.nextFrame();
            sp.paint(g);
           
        }
   
    }

}


class CGameJ2meDrawer extends CGameDrawerBase
{
 public Graphics graphics;
 public Sprite   sp;
 public Sprite   sphl;
 public Image bkbmp;
 public Sprite AlphabetSpW;
 public Sprite AlphabetSpX;
 public Sprite AlphabetSpHL;
 public Sprite AlphabetSpTT;
 public Image    frmbmp;
 
 private GIFPlayer[] gifPlayers = new  GIFPlayer[3];
 String  [] gifFiles={
   "levelup.png",
   "gameover.png",
   "gamewin.png",
 };
 int     [][]gifFrameSize=
 {
   {70,70},
   {60,60},
   {70,110},
 };


    CGameJ2meDrawer()
    {
     super();
    }
   
    public void setup(Graphics g)
    {
     graphics = g;
     try {
      
      String filename = "/img/"+CGameField.nSquareSize+".png";
   Image img = Image.createImage(filename);
   sp = new Sprite(img,CGameField.nSquareSize,CGameField.nSquareSize);
   filename = "/img/"+CGameField.nSquareSize+"hl.png";
   sphl = new Sprite(Image.createImage(filename),CGameField.nSquareSize,CGameField.nSquareSize);
   
   
   bkbmp = Image.createImage("/img/bk320.PNG");
    
   
   
   filename = "/img/Alphabetx.png";
   AlphabetSpX = new Sprite(Image.createImage(filename),TETRIS_FONT.NormalSize,TETRIS_FONT.NormalSize);
   
   filename = "/img/Alphabetw.PNG";
   AlphabetSpW = new Sprite(Image.createImage(filename),TETRIS_FONT.NormalSize,TETRIS_FONT.NormalSize);
   
   filename = "/img/Alphabethl.png";
   AlphabetSpHL = new Sprite(Image.createImage(filename),TETRIS_FONT.NormalSize,TETRIS_FONT.NormalSize);
   
   filename = "/img/AlphabetTitle.png";
   AlphabetSpTT = new Sprite(Image.createImage(filename),TETRIS_FONT.LargeSize,
     TETRIS_FONT.LargeSize);
   
   frmbmp = Image.createImage("/img/frm.png");
   
   for(int i=0;i<3;i++)
   {
    gifPlayers[i] = new GIFPlayer();
    gifPlayers[i].Setup("/img/"+gifFiles[i],gifFrameSize[i][1],gifFrameSize[i][0],40);
   }
   
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }

    public  void DrawLine(Color color, Point pt1, Point pt2)
    {
     graphics.setColor(color.rgb);
     graphics.drawLine(pt1.X,pt1.Y,pt2.X,pt2.Y);
    }

    public void DrawStringCenterVH(String s, int font, Point centerPt) {
     if(s.length()==0) return ;
     int nSize =TETRIS_FONT.NormalSize;
     if(font == TETRIS_FONT.Title)
      nSize =TETRIS_FONT.LargeSize;
     
     int sWidth = s.length()*nSize;
     int sHeith = nSize;
     Point leftTop = new Point(centerPt.X-sWidth/2,centerPt.Y-sHeith/2);
     
     DrawString(s,font,leftTop);
          
 }
   
    public void DrawGameMenuFrame(Rectangle rect)
 {
  int nX =rect.Width/20;
  int nY =rect.Height/20;
  for(int i=0;i<nX;i++)
  {
   for(int j=0;j<nY;j++)
   {
    graphics.drawImage(frmbmp,rect.X+i*20,rect.Y+j*20,0);
   }
  }

 }
   
    public void DrawString(String s, int font, Point pt)
    {

     s=s.toUpperCase();
     Sprite sp;
     int nSize =TETRIS_FONT.NormalSize;
     
     if(font == TETRIS_FONT.Plain)
      sp= AlphabetSpW;
     if(font ==  TETRIS_FONT.HightLight)
      sp= AlphabetSpHL;
     else if(font ==  TETRIS_FONT.Warning)
      sp= AlphabetSpX;
     else if(font == TETRIS_FONT.Title)
     {
      sp = AlphabetSpTT;
      nSize = TETRIS_FONT.LargeSize;
     }
     else
      sp= AlphabetSpW;
     int  npos=0;
     for(int i=0;i<s.length();i++,npos++)
     {
      
      char c =s.charAt(i);
      if(c>='0'&&c<='9' )
      {
       sp.setFrame(c-'0');
      }
      else if(c>='A' && c<='Z')
      {
       sp.setFrame(10+c-'A');
      }
      else if(c==':')
      {
       sp.setFrame(36);
      }
      else if(c=='-')
      {
       sp.setFrame(37);
      }
      else if(c==' ')
      {
       sp.setFrame(38);
      }
      else if(c=='.')
      {
       sp.setFrame(39);
      }
      else if(c=='?')
      {
       sp.setFrame(40);
      }
      else if(c=='!')
      {
       sp.setFrame(41);
      }
      else if(c=='@')
      {
       sp.setFrame(42);
      }
      else if(c=='%')
      {
       sp.setFrame(43);
      }
//      else if(c=='/n')
//      {
//       pt.Y+=(nSize+2);
//       npos=-1;
//       continue;
//      }
      else
      {
       continue;
      }
      sp.setRefPixelPosition(pt.X+nSize*npos,pt.Y);
      sp.paint(graphics);
     }
     //adrawString(s,pt.X,pt.Y,0);
    }
    public void clear(Color bkcolor)
    {

     graphics.drawImage(bkbmp,0,0,0);
   
    }

    public void DrawSquare(CSquare q)
    {
        if (!q.IsHide)
        {
         Sprite p = sp;
         if(q.HightLight)
          p = sphl;
          
         p.setFrame(q.color);
         p.setRefPixelPosition(q.getAbsX(),q.getAbsY());
         p.paint(graphics);
        }
    }

    public void Flip()
    {
       // back.DrawFast(0, 0, surfaceAnimation, new Rectangle(0, 0, 400, 600), DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey);
    }

   
    public void PlayGif(int gifKey, int x, int y,long duration)
 {
     System.out.println("PlayGif " +gifKey );
  if(gifKey<0 || gifKey>2)
   return;
  
  gifPlayers[gifKey].Start(x,y,duration);
 }
 
 public void StopGif(int gifKey)
 {
  if(gifKey<0 || gifKey>2)
   return;
  gifPlayers[gifKey].Stop();
 }
 
 public int GetGifState(int gifKey)
 {
  if(gifKey<0 || gifKey>2)
   return GIF_STOPPED;
  return gifPlayers[gifKey].isPlaying?GIF_STARTED: GIF_STOPPED;

 }

 public void DrawGifFrame(int gifKey)
 {
  if(gifKey<0 || gifKey>2 ||(gifPlayers[gifKey]==null))
   return ;
  gifPlayers[gifKey].DrawFrame(graphics);
  
 }
}

 

 

class CSquare {

 private int absX;
 private int absY;
 private int X;
 private int Y;
 
 private int OabsX;
 private int OabsY;
 private int OX;
 private int OY;
 

 public int color;
 
 public boolean IsHide;
 public boolean HightLight;
 public CSquare() {
  absX =  absY=0;
  X = Y = color = 0;
  OabsX = OabsY=OX=OY;
  IsHide = true;
  HightLight = false;
 }

 public void Assign(CSquare q) {
  X = q.X;
  Y = q.Y;
  absX = q.absX;
  absY = q.absY;
  OabsX = q.OabsX; 
  OabsY = q.OabsY;
  OX = q.OX;
  OY = q.OY;
  
  color = q.color;
  IsHide = q.IsHide;
  HightLight= q.HightLight;
 }
 
 public void Setup(int _x, int _y, int _absx, int _absy)
 {
  X = _x;
  Y = _y;
  absX = _absx;
  absY = _absy;
  OabsX = absX; 
  OabsY = absY;
  OX = X;
  OY = Y;
 }
 
 public int getX()
 {
  return X;
 }
 public int getY()
 {
  return Y;
 }
 
 public void setX(int _x)
 {
  X = _x;
  absX = OabsX+(X-OX)*CGameField.nSquareSize;
 }
 
 public void setY(int _y)
 {
  Y = _y;
  absY = OabsY-(Y-OY)*CGameField.nSquareSize;
 }
 
 public int getAbsX()
 {
  return absX;
 }
 
 public void setAbsX(int _absX)
 {
  int nGrids = (_absX-OabsX)/CGameField.nSquareSize;
  X  = OX+ nGrids;
  absX = _absX;
 }
 
 public int getAbsY()
 {
  return absY;
 }
 
 public void setAbsY(int _absY)
 {

  int nGrids = -(_absY-OabsY)/CGameField.nSquareSize;
  Y =OY+ nGrids;
  absY = _absY;
 }
 
 public void IncGridX()
 {
  setX(X+1);
 }
 
 public void DecGridX()
 {
  setX(X-1);
 }
 
 public void IncGridY()
 {
  setY(Y+1);
 }
 
 public void DecGridY()
 {
  setY(Y-1);
 }
 
 

}

class Rectangle {
 public int X=0;

 public int Y=0;

 public int Width=0;

 public int Height=0;
 Rectangle()
 {
 
 }
 Rectangle(int _x,int _y,int _w,int _h)
 {
  Width = _w;
  Height = _h;
  X = _x;
  Y = _y;
 }
 public boolean isPointInside(int _x,int _y)
 {
  if(_x>X && _x <X+Width
    &&_y>Y && _y<Y+Height
    )
  {
   return true;
  }
  return false;
 }
}

class Color {
 public static Color Black = new Color(0);

 public static Color Red = new Color(0xff0000);

 public static Color Green = new Color(0xff00);

 public static Color Blue = new Color(0xff);

 public static Color White = new Color(0xffffffff);

 public static Color Tomato = new Color(0x00e70f0f);

 public static Color Violet = new Color(0x000080c0);
 
 public static Color DarkBlue = new Color(0x002F5E);
 
 public int rgb;

 Color(int _v) {
  rgb = _v;
 }
}

class Point {
 public int X;

 public int Y;

 Point(int _x, int _y) {
  X = _x;
  Y = _y;
 }
}

class CGameSoundPlayer
{
 static final int nosoundEffect = -1;//0
 static final int soundFell = 0;//0
 static final int soundLinefull = 1;//0
 static final int soundLevelup = 2;//0
 static final int soundGameover = 3;//0
 static final int soundGamewon = 4;//0
 
 public void ControlEffectSound()
 {
  
 }
 

 public void PlayEffectSound(int soundKey)
 {
  
 }
 
 public void StopEffectSound()
 {
  
 }
 
 public void PlayBackgroundMusic()
 {
 
 }
 
 public void StopBackgroundMusic()
 {
 
 }
 
 


 public void SetVolume(int level)
 {
  
 }
 
 public void EnableBgMusic(boolean val)
 {
  
 }
 
 public void EnableEffectSound(boolean val)
 {
  
 }
 

}

class CGameDrawerBase {
 
 static final int NoneGif = -1;
 static final int LevelUpGif = 0;
 static final int GameOverGif =1;
 static final int GameWonGif = 2;
 static final int GIF_STOPPED = 0;
 static final int GIF_STARTED = 1;
 
 
 
 public void clear(Color bkcolor) {
 }

 public void DrawLine(Color color, Point pt1, Point pt2) {
 }

 public void DrawString(String s, int font, Point pt) {
 }

 public void DrawStringCenterVH(String s, int font, Point centerPt) {
 }
 
 public void DrawSquare(CSquare q) {
 }

 public void Flip() {
 }

 public void DrawGameMenuFrame(Rectangle rect)
 {
  
 }
 
 public void PlayGif(int gifKey, int x, int y,long duration)
 {
  
 }
 
 public void StopGif(int gifKey)
 {
  
 }
 
 public int GetGifState(int gifKey)
 {
  return GIF_STOPPED;
 }

 public void DrawGifFrame(int gifKey)
 {
  
 }
 
}

//static final int STATE_KNEEL = 8;

class BLOCK_TYPE {
 static final int undefine = 0;//0

 static final int square = 1; //1

 static final int line = 2; //2

 static final int L = 3;//3

 static final int J = 4;//4

 static final int S = 5;//5

 static final int Z = 6;//6

 static final int T = 7;//7
}

class TETRIS_KEYCODE {
 static final int Unk = 0;

 static final int Up = 1;

 static final int Down = 2;

 static final int Left = 3;

 static final int Right = 4;

 static final int Rotate = 5;

 static final int Escape = 6;

 static final int Start   = 7;
}

class TETRIS_FONT
{
 static final int Plain       = 0;
 static final int Warning     = 1;
 static final int Title     = 2;
 static final int HightLight  = 4;
 static final int NormalSize  =9;
 static final int LargeSize   =12;
 
}

class CTetrisMenu
{
 public  int    ID=0;
 private String Title="";
 private String []Options;
 private String []Hints;
 public CTetrisMenu parent=null;
 private int    IndexCurSel;
 private boolean bdone=false;
 private boolean bhorizOpts = false;
 private Rectangle FrameRect =null;;
 private Rectangle titleRect =null;
 private Rectangle []hintRects =null;
 
 private Rectangle []optRects =null;
 
 CTetrisMenu(int id, String _Title, String [] _options, String [] _Hints,Rectangle _rect, boolean hozi)
 {
  ID = id;
  Options = _options;
  Title   = _Title;
  Hints   = _Hints;
  IndexCurSel = 0;
  FrameRect   = _rect;
  bhorizOpts = hozi;
  
  int curY= FrameRect.Y+6;
  if(Title!=null&&Title.length()>0)
  {
   titleRect = new Rectangle(FrameRect.X + FrameRect.Width/2 - Title.length()*TETRIS_FONT.LargeSize/2,
     curY,
     Title.length()*TETRIS_FONT.LargeSize,
     TETRIS_FONT.LargeSize+6);
   curY+=TETRIS_FONT.LargeSize+12;
  }
  
  if(Hints!=null && Hints.length>0)
  {
   hintRects = new Rectangle[Hints.length];
   for(int i=0;i<Hints.length;i++)
   {
    hintRects[i]=new Rectangle(
      FrameRect.X + FrameRect.Width/2 - Hints[i].length()*TETRIS_FONT.NormalSize/2,
      curY,
      Hints[i].length()*TETRIS_FONT.NormalSize,
      TETRIS_FONT.NormalSize+4);
    curY+=TETRIS_FONT.NormalSize+4;
   }
  }
  
  
  if(_options!=null && _options.length>0)
  {
   if(!bhorizOpts)
   {
    optRects = new Rectangle[_options.length];
    for(int i=0;i<_options.length;i++)
    {
     optRects[i]=new Rectangle(
       FrameRect.X + FrameRect.Width/2 - _options[i].length()*TETRIS_FONT.NormalSize/2,
       curY,
       _options[i].length()*TETRIS_FONT.NormalSize,
       TETRIS_FONT.NormalSize+4);
     curY+=TETRIS_FONT.NormalSize+4;
    }
   }
   else
   {
    int gridWidth = FrameRect.Width/_options.length;
    optRects = new Rectangle[_options.length];
    for(int i=0;i<_options.length;i++)
    {
     optRects[i]=new Rectangle(
       FrameRect.X+gridWidth*i+gridWidth/2-_options[i].length()*TETRIS_FONT.NormalSize/2,
       curY,
       _options[i].length()*TETRIS_FONT.NormalSize,
       TETRIS_FONT.NormalSize+4
       );
     
    }
   }
  }
  
 }
 
 public void reset()
 {
  bdone=false;
 }
 
 public void DoKeyPressed(int keycode)
 {
  if(bdone) return;
  //System.out.println("DoKeyPressed "+keycode);
  
  if(keycode==TETRIS_KEYCODE.Down||keycode==TETRIS_KEYCODE.Right)
  {
   IndexCurSel++;
   if(IndexCurSel>=Options.length)
    IndexCurSel=0;
  }
  else if(keycode==TETRIS_KEYCODE.Up||keycode==TETRIS_KEYCODE.Left)
  {
   IndexCurSel--;
   if(IndexCurSel<0)
   {
    IndexCurSel=Options.length-1;
   }
  }
  else if(keycode==TETRIS_KEYCODE.Rotate)
  {
   bdone = true;
  }
 }
 
 public void DoPointerPressed(int x, int y)
 {
  if(optRects!=null)
  for(int i=0;i<optRects.length;i++)
  {
   if(optRects[i].isPointInside(x,y))
   {
    //System.out.println("inside "+i);
    IndexCurSel = i;
    bdone = true;     
    return;
   }
  }
 }
 
 public void SetCurSel(int i)
 {
  IndexCurSel = i;
 }
 public int GetCurSel()
 {
  return IndexCurSel;
 }
 
 public void Draw(CGameDrawerBase drawer)
 {
  drawer.DrawGameMenuFrame(FrameRect);
 
  if(Title!=null&&Title.length()>0)
  {
   drawer.DrawStringCenterVH(Title,TETRIS_FONT.Title,
     new Point(titleRect.X+titleRect.Width/2,
       titleRect.Y+titleRect.Height/2)
       );
  }
  
  if(Hints!=null )
  {
   for(int i=0;i<Hints.length;i++)
   {
    Point pt0 = new Point(hintRects[i].X+hintRects[i].Width/2,
      hintRects[i].Y+hintRects[i].Height/2);
      
    drawer.DrawStringCenterVH(Hints[i],TETRIS_FONT.Warning,pt0);
   
   }
  }
  
  if(Options!=null)
  {
   for(int i=0;i<Options.length;i++)
   {
    Point pt0 = new Point(optRects[i].X+optRects[i].Width/2,
      optRects[i].Y+optRects[i].Height/2);
      
    if(GetCurSel()!=i)
     drawer.DrawStringCenterVH(Options[i],TETRIS_FONT.Plain,pt0);
    else
     drawer.DrawStringCenterVH(Options[i],TETRIS_FONT.HightLight,pt0);
   }
  }
 }
 
 public boolean IsDone()
 {
  return bdone;
 }
}

 

class CBlock {
 public CSquare[] qs = new CSquare[4];

 public int Type = BLOCK_TYPE.undefine;

 public int orientation = -1; //0-3

 public float Speed = 0;

 private long LastTick = 0;

 int LastDeltaY = 0;

 public long StopTick = 0;

 public CBlock() {
  for (int i = 0; i < 4; i++) {
   qs[i] = new CSquare();
   qs[i].IsHide = false;
  }
  orientation = 0;
  Speed = 0;
  LastTick = 0;
  LastDeltaY = 0;
  StopTick = 0;

 }

 public void Resume() {
  LastTick = System.currentTimeMillis();
  
 }

 public void Create(int _type, int orient, int x, int y , int _absx,int absy) {
  LastTick = System.currentTimeMillis();
  LastDeltaY = 0;
  StopTick = 0;

  for (int i = 0; i < 4; i++) {
   qs[i].Setup(x,y,_absx,absy);
  }
  
  Random rand = new Random();

  if (orient < 0 || orient > 3) {
   orientation = (int) (rand.nextFloat() * 3);
  } else {
   orientation = orient;
  }

  if (_type <= BLOCK_TYPE.undefine || _type > BLOCK_TYPE.T) {


   int tt = (int) (rand.nextFloat() * 7) + 1;

   Type = (int) tt;

  } else {
   Type = _type;
  }

  CreateInternal(x, y);

 }

 private void CreateInternal(int x, int y) {
  int index = -1;

  switch (Type) {
  case BLOCK_TYPE.square:
   CreateTypeSquare(x, y);
   index = 0;
   break;
  case BLOCK_TYPE.line:
   CreateTypeLine(x, y);
   index = 1;
   break;
  case BLOCK_TYPE.L:
   CreateTypeL(x, y);
   index = 2;
   break;
  case BLOCK_TYPE.J:
   CreateTypeJ(x, y);
   index = 3;
   break;
  case BLOCK_TYPE.S:
   CreateTypeS(x, y);
   index = 4;
   break;
  case BLOCK_TYPE.Z:
   CreateTypeZ(x, y);
   index = 5;
   break;
  case BLOCK_TYPE.T:
   CreateTypeT(x, y);
   index = 6;
   break;
  default:
   CreateTypeL(x, y);
   index = 2;
   break;
  }

  for (int i = 0; i < 4; i++) {
   qs[i].color = index;

  }

 }

 public void UpdateLocation(CGameField gamefield, long curTick) {
  if (LastTick > 0 && curTick > LastTick) {
   int deltaY = (int) (Speed * (curTick - LastTick) / 1000)
     - LastDeltaY;
   LastDeltaY += deltaY;
   if (deltaY > 0) {
    for (int i = 0; i < deltaY; i++) {
     Down(gamefield);
    }
   }
  }
 }
 
 public void AbsUpdateLocation(CGameField gamefield, long curTick) {
  if (LastTick > 0 && curTick > LastTick) {
   int deltaY = (int) (Speed * CGameField.nSquareSize*(float)(curTick - LastTick) / 1000)
     - LastDeltaY;
   
   LastDeltaY += deltaY;
  
   for (int i = 0; i < deltaY; i++) {
    absDown(gamefield);
   }
  
  }
 }

 public void Draw(CGameDrawerBase drawer) {
  for (int i = 0; i < 4; i++) {
   drawer.DrawSquare(qs[i]);
  }
 }

 public void Left(CGameField gamefield) {
  CBlock tmp = new CBlock();
  tmp.Type = Type;
  for (int i = 0; i < 4; i++) {
   tmp.qs[i].Assign(qs[i]);
  }
  tmp.Left();
  if (gamefield.Intersected(tmp)) {
   return;
  }
  Left();
 }

 public void Right(CGameField gamefield) {
  CBlock tmp = new CBlock();
  tmp.Type = Type;
  for (int i = 0; i < 4; i++) {
   tmp.qs[i].Assign(qs[i]);
  }
  tmp.Right();
  if (gamefield.Intersected(tmp)) {
   return;
  }
  Right();
 }


 public void Down(CGameField gamefield) {
  CBlock tmp = new CBlock();
  tmp.Type = Type;
  for (int i = 0; i < 4; i++) {
   tmp.qs[i].Assign(qs[i]);
  }
  tmp.Down();
  if (gamefield.Intersected(tmp)) {
   return;
  }
  Down();
 }
 
 public void absDown(CGameField gamefield) {
//  CBlock tmp = new CBlock();
//  tmp.Type = Type;
//  for (int i = 0; i < 4; i++) {
//   tmp.qs[i].Assign(qs[i]);
//  }
//  tmp.absDown();
//  if (gamefield.Intersected(tmp)) {
//   return;
//  }
  absDown();
  if(gamefield.Intersected(this))
  {
   absUp();
  }
 }

 public void Rotate(CGameField gamefield) {
  CBlock tmp = new CBlock();
  tmp.Type = Type;
  for (int i = 0; i < 4; i++) {
   tmp.qs[i].Assign(qs[i]);
  }

  tmp.Rotate();
  if (tmp.MaxX() > CGameField.HSquareNumber - 1 || tmp.MinX() < 0
    || gamefield.Intersected(tmp)) {
   return;
  }
  Rotate();
 }

 public void Rotate() {
  int minx = MinX();
  int miny = MinY();
  orientation = orientation % 4;
  ++orientation;
  CreateInternal(minx, miny);
  int maxX = MaxX();
  if (maxX > CGameField.HSquareNumber - 1) {
   int iback = maxX - (CGameField.HSquareNumber - 1);
   for (int i = 0; i < iback; i++) {
    Left();
   }
  }

 }

 public void Left() {
  if (MinX() > 0) {
   for (int i = 0; i < 4; i++) {
    qs[i].DecGridX();
    
   }
  }
 }

 public void Right() {
  if (MaxX() < (CGameField.HSquareNumber - 1)) {
   for (int i = 0; i < 4; i++) {
    qs[i].IncGridX();
   }
  }
 }

 public void Down() {
  if (MinY() > 0) {
   for (int i = 0; i < 4; i++) {
    //qs[i].Y -= 1;
    qs[i].DecGridY();
   }
  }
 }
 
 public void absDown()
 {
  if (MinY() > 0) {
   for (int i = 0; i < 4; i++) {
    //qs[i].Y -= 1;
    qs[i].setAbsY(qs[i].getAbsY()+1);
   }
  }
 }

 void Up() {
  if (MaxY() < (CGameField.VSquareNumber - 1)) {
   for (int i = 0; i < 4; i++) {
    //qs[i].Y += 1;
    qs[i].IncGridY();
   }
  }
 }

 void absUp() {
  if (MaxY() < (CGameField.VSquareNumber - 1)) {
   for (int i = 0; i < 4; i++) {
    qs[i].setAbsY(qs[i].getAbsY()-1);
   }
  }
 }
 
 public int MinX() {
  int min = qs[0].getX();
  for (int i = 1; i < 4; i++) {
   if (min > qs[i].getX()) {
    min = qs[i].getX();
   }
  }
  return min;
 }

 public int MaxX() {
  int max = qs[0].getX();
  for (int i = 1; i < 4; i++) {
   if (max < qs[i].getX()) {
    max = qs[i].getX();
   }
  }
  return max;
 }

 public int MinY() {
  int min = qs[0].getY();
  for (int i = 1; i < 4; i++) {
   if (min > qs[i].getY()) {
    min = qs[i].getY();
   }
  }
  return min;
 }

 public int MaxY() {
  int max = qs[0].getY();
  for (int i = 1; i < 4; i++) {
   if (max < qs[i].getY()) {
    max = qs[i].getY();
   }
  }
  return max;
 }
 
 public int AbsMinX() {
  int min = qs[0].getAbsX();
  for (int i = 1; i < 4; i++) {
   if (min > qs[i].getAbsX()) {
    min = qs[i].getAbsX();
   }
  }
  return min;
 }

 public int AbsMaxX() {
  int max = qs[0].getAbsX();
  for (int i = 1; i < 4; i++) {
   if (max < qs[i].getAbsX()) {
    max = qs[i].getAbsX();
   }
  }
  return max;
 }

 public int AbsMinY() {
  int min = qs[0].getAbsY();
  for (int i = 1; i < 4; i++) {
   if (min > qs[i].getAbsY()) {
    min = qs[i].getAbsY();
   }
  }
  return min;
 }

 public int AbsMaxY() {
  int max = qs[0].getAbsY();
  for (int i = 1; i < 4; i++) {
   if (max < qs[i].getAbsY()) {
    max = qs[i].getAbsY();
   }
  }
  return max;
 }
 
 public int absWidth()
 {
  return AbsMaxX()-AbsMinX();
 }
 
 public int absHeight()
 {
  return AbsMaxY()-AbsMinY();
 }
 
 public void CenterAbs(Rectangle rect)
 {
  int curCenterX =  AbsMinX() +absWidth()/2;
  int curCenterY =     AbsMinY() +absHeight()/2;
  int offsetX =(rect.X+  rect.Width/2)-curCenterX;
  int offsetY = (rect.Y+  rect.Height/2)-curCenterY;
  for(int i=0;i<4;i++)
  {
   qs[i].setAbsX(qs[i].getAbsX()+offsetX);
   qs[i].setAbsY(qs[i].getAbsY()+offsetY);
  }
  
 }

 private void CreateTypeSquare(int X, int Y) {
  /*
   @ @
   @ @
   */
  qs[0].setX ( X);
  qs[0].setY ( Y);
  qs[1].setX ( X + 1);
  qs[1].setY ( Y);
  qs[2].setX ( X + 1);
  qs[2].setY ( Y + 1);
  qs[3].setX ( X);
  qs[3].setY ( Y + 1);
 }

 private void CreateTypeLine(int X, int Y) {

  if (orientation % 2 == 0) {
   /*
    @
    @
    @
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);
   qs[2].setX ( X);
   qs[2].setY ( Y + 2);
   qs[3].setX ( X);
   qs[3].setY ( Y + 3);
  } else {
   /*
    @ @ @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);
   qs[2].setX ( X + 2);
   qs[2].setY ( Y);
   qs[3].setX ( X + 3);
   qs[3].setY ( Y);
  }
 }

 private void CreateTypeL(int X, int Y) {

  int r = orientation % 4;
  switch (r) {
  case 0:
   /*
    @
    @
    @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);
   qs[2].setX ( X);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X);
   qs[3].setY ( Y + 2);
   break;
  case 1:
   /*
    @ @ @
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y + 1);
   break;
  case 2:
   /*
    @ @
    @
    @
    */
   qs[0].setX ( X + 1);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 2);
   qs[3].setX ( X);
   qs[3].setY ( Y + 2);

   break;
  case 3:
   /*
    @
    @ @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);

   qs[2].setX ( X + 2);
   qs[2].setY ( Y);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y + 1);
   break;
  }
 }

 private void CreateTypeJ(int X, int Y) {
  int r = orientation % 4;
  switch (r) {
  case 0:

   /*
    @
    @
    @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 1);
   qs[3].setY ( Y + 2);
   break;
  case 1:
   /*
    @ 
    @ @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y);
   break;
  case 2:
   /*
    @ @
    @ 
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X);
   qs[2].setY ( Y + 2);
   qs[3].setX ( X + 1);
   qs[3].setY ( Y + 2);

   break;
  case 3:
   /*
    @ @ @ 
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y + 1);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 2);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y);
   break;
  }
 }

 private void CreateTypeZ(int X, int Y) {
  int r = orientation % 2;
  switch (r) {
  case 0:
   /*
    @ @
    @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y + 1);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y);
   break;
  case 1:
   /*
    @
    @ @
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 1);
   qs[3].setY ( Y + 2);
   break;
  }
 }

 private void CreateTypeS(int X, int Y) {
  int r = orientation % 2;
  switch (r) {
  case 0:
   /*
    @ @
    @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y + 1);
   break;
  case 1:
   /*
    @
    @ @
    @
    */
   qs[0].setX ( X + 1);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X);
   qs[3].setY ( Y + 2);
   break;
  }
 }

 private void CreateTypeT(int X, int Y) {

  int r = orientation % 4;

  switch (r) {

  case 0:
   /*
    @ @ @
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y + 1);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y + 1);

   break;
  case 1:
   /*
    @
    @ @
    @
    */
   qs[0].setX ( X + 1);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 1);
   qs[3].setY ( Y + 2);
   break;
  case 2:
   /*
    @
    @ @ @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X + 1);
   qs[1].setY ( Y);
   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X + 2);
   qs[3].setY ( Y);
   break;
  case 3:
   /*
    @
    @ @
    @
    */
   qs[0].setX ( X);
   qs[0].setY ( Y);
   qs[1].setX ( X);
   qs[1].setY ( Y + 1);

   qs[2].setX ( X + 1);
   qs[2].setY ( Y + 1);
   qs[3].setX ( X);
   qs[3].setY ( Y + 2);
   break;
  }
 }

}

 


abstract class BaseRMS {

 private String rmsName;
 
 private RecordStore recordStore;
 
 BaseRMS(String _rmsName)
 {
   rmsName = _rmsName;
 }

 public void open() throws Exception {

  // 如果load RecordStore失败则重新生成一个RecordStore
  try {
   recordStore = RecordStore.openRecordStore(this.rmsName,true);
   if(recordStore.getNumRecords()>0){
    loadData();
  } else {
   createDefaultData();
  }
  }catch(Exception e){
    throw new Exception(this.rmsName + "::open::" + e);
  }
  

 }

 public void close() throws Exception {
  if (recordStore != null) {
   try {
    recordStore.closeRecordStore();
   } catch (Exception e) {
    throw new Exception(this.rmsName + "::close::" + e);
   }
  }
 }

 public RecordStore getRecordStore() {
  return this.recordStore; // 返回整块记录
 }

 public String getRMSName() {
  return this.rmsName;
 }

 abstract void loadData() throws Exception;

 abstract void createDefaultData() throws Exception;

 abstract void updateData() throws Exception;

}


class CGameRecords extends BaseRMS {

 private String[] names = new String[8];

 private int[] values = new int[8];

 public CGameRecords(String rmsName) {
  super(rmsName);
  initValues(); // 这个是初始数据
 }

 private void initValues() {
  names[0] = "DANY";
  names[1] = "NICOLE";
  names[2] = "NICOLE";
  names[3] = "DANY";
  names[4] = "NICOLE";
  names[5] = "NICOLE";
  names[6] = "DANY";
  names[7] = "NICOLE";
//  names[8] = "NICOLE";
//  names[9] = "DANY";
  
  values[0] = 140;
  values[1] = 100;
  values[2] = 80;
  values[3] = 60;
  values[4] = 30;
  values[5] = 20;
  values[6] = 10;
  values[7] = 30;
//  values[8] = 20;
//  values[9] = 10;

 }

 public void loadScores() throws Exception {
  try {
   this.open();
   if (this.getRecordStore() != null)
    this.close();
  } catch (Exception e) {
   throw new Exception("Error loading Scores" + e);
  }
 }

 public int[] getValues() {
  return this.values;// 得到分数的数组
 }

 public String[] getNames() {
  return this.names;// 得到名字的数组
 }

 public void reset() throws Exception {
  // 重新初始化数据集
  this.open();
  initValues();
  updateData();
  if (this.getRecordStore() != null)
   this.close();
 }

 public void updateScores(int score, String Name) throws Exception {
  try {// 数据量小,简单地使用冒泡排序来完成更新并重排记录
   for (int i = 0; i < names.length; i++) {
    if (score >= values[i]) {
     this.open();
     for (int j = names.length - 1; j > i; j--) {
      values[j] = values[j - 1];
      names[j] = names[j - 1];
     }
     this.values[i] = score;
     this.names[i] = Name;
     updateData();
     if (this.getRecordStore() != null)
      this.close();
     break;
    }
   }
  } catch (Exception e) {
   throw new Exception(this.getRMSName() + "::updateScores::" + e);
  }
 }

 public boolean isHighScore(int score) throws Exception {
  boolean isHighScore = false;// 遍历记录,判断新的分数是否是高分
  try {
   for (int i = 0; i < names.length; i++) {
    if (score >= values[i])
     isHighScore = true;
   }
  } catch (Exception e) {
   throw new Exception(this.getRMSName() + "::isHighScore::" + e);
  }
  return isHighScore;
 }

 protected void loadData() throws Exception {
  try {
   for (int i = 0; i < names.length; i++) {
    byte[] record = this.getRecordStore().getRecord(i + 1);
    values[i] =ByteArrayToInteger(record);
    //System.out.print("Load "+record[0]+" "+record[1]+" "+record[2]+" "+record[3]+" /n");
    
    byte[] szbytes = new byte[record.length-4];
    for(int j=0;j<record.length-4;j++)
    {
     szbytes[j]=record[4+j];
    }
    names[i]= new String(szbytes,"utf-8");
    
   }
  } catch (Exception e) {
   throw new Exception(this.getRMSName() + "::loadData::" + e);
  
  }
  
 }

 public static int ByteArrayToInteger(byte[] b) {
  int s = 0;

  for(int i=0;i<4 && i<b.length;i++)
  {
   int t = b[i]&0xFF;
   s |= t<<(i*8);
  }

//  System.out.println("ByteArrayToInteger ("+s
//    +") "+b[0]
//    +" "+b[1]
//    +" "+b[2]
//    +" "+b[3]
//    );
  return s;
 }


 public static byte[] IntegerToByteArray(int number) {
  int temp = number;
  byte[] b = new byte[4];
  for (int i = 0; i <4; i++) {
   b[i] = (byte)(temp & 0xff);
   temp = temp >> 8;
  }
//  System.out.println("IntegerToByteArray ("+number
//    +") "+b[0]
//    +" "+b[1]
//    +" "+b[2]
//    +" "+b[3]
//    );
  return b;
 }


 protected void createDefaultData() throws Exception {
  try {
   for (int i = 0; i < names.length; i++) {
       
    byte []intBytes =  IntegerToByteArray(values[i]);
    byte []szbytes = names[i].getBytes("UTF-8");
    
    byte[] record = new byte[szbytes.length+intBytes.length];
    
    //System.out.print("create "+intBytes[0]+" "+intBytes[1]+" "+intBytes[2]+" "+intBytes[3]+" /n");
    
    for(int j=0;j<intBytes.length;j++)
    {
     record[j]=intBytes[j];
    }
    
    for(int j=0;j<szbytes.length;j++)
    {
     record[intBytes.length+j]=szbytes[j];
    }

    this.getRecordStore().addRecord(record, 0, record.length);
   }
  } catch (Exception e) {
   throw new Exception(this.getRMSName() + "::createDefaultData::" + e);
  }
 }

 protected void updateData() throws Exception {
  try {
   for (int i = 0; i < names.length; i++) {
    byte []intBytes =  IntegerToByteArray(values[i]);
    byte []szbytes = names[i].getBytes("UTF-8");
    
    byte[] record = new byte[szbytes.length+intBytes.length];
    
    //System.out.print("SAVE "+intBytes[0]+" "+intBytes[1]+" "+intBytes[2]+" "+intBytes[3]+" /n");
    
    for(int j=0;j<intBytes.length;j++)
    {
     record[j]=intBytes[j];
    }
    
    for(int j=0;j<szbytes.length;j++)
    {
     record[intBytes.length+j]=szbytes[j];
    }
    
    this.getRecordStore()
      .setRecord(i + 1, record, 0, record.length);
   }
  } catch (Exception e) {
   throw new Exception(this.getRMSName() + "::updateData::" + e);
  }
 }

}


class CGameField {
 //FIELD: 22X17                      //
 //////////////////////////////////////
 //1                     1         0 //
 //2                     2  TETRIS 0 //
 //3                     3  DANY   0 //
 //4 ____________________4_________0 //
 //5                     5 NEXT:   0 //
 //6                     6         0 //
 //7                     7 1 2 3 4 0 //
 //8                     8 2     2 0 //
 //9                     9 3     3 0 //
 //0                     0 1 2 3 4 0 //
 //1   PRESS ANY KEY     1         0 //
 //2     TO  START       2 SCORE:  0 //
 //3                     3 9000000 0 //
 //4                     4 LEVEL:  0 //
 //5                     5 1       0 //
 //6                     6 LINES:  0 //
 //7                     7 00:00   0 //
 //8                     8 RECORD: 0 //
 //9                     9 999999  0 //
 //0                     0PRESS ESC0 //
 //1                     1 TO MENU 0 //
 //2 1 2 3 4 5 6 7 8 9 0 2 2 3 4 5 6 //
 //////////////////////////////////////


 public static int _Width = 0;

 public static int _Heigth = 0;

 public static int _LeftBattle = 0;

 public static int _TopBattle = 0;

 public static int _LeftIcon = 0;

 public static int _TopIcon = 0;

 public static int _LeftNextBL_LABLE = 0;

 public static int _TopNextBL_LABLE = 0;

 public static int _LeftNextBL = 0;

 public static int _TopNextBL = 0;

 public static int _LeftScore_LABLE = 0;

 public static int _TopScore_LABLE = 0;

 public static int _LeftScore = 0;

 public static int _TopScore = 0;

 public static int _LeftLevel_LABLE = 0;

 public static int _TopLevel_LABLE = 0;

 public static int _LeftLevel = 0;

 public static int _TopLevel = 0;

 public static int _LeftTime_LABLE = 0;

 public static int _TopTime_LABLE = 0;

 public static int _LeftTime = 0;

 public static int _TopTime = 0;

 public static int _LeftRECORD_LABLE = 0;

 public static int _TopRECORD_LABLE = 0;

 public static int _LeftRECORD = 0;

 public static int _TopRECORD = 0;

 public static int _LeftHINT_LABLE = 0;

 public static int _TopHINT_LABLE = 0;

 public static int _LeftHINT = 0;

 public static int _TopHINT = 0;

 public static int VSquareNumber = 22;

 public static int HSquareNumber = 10;

 public static int HAlignNumber = 7;

 public static int nSquareSize = 18;

 public static int nDeadAreaHeight = 4;

 public static int nBaseScorePerLine = 10;

 private CSquare[][] squares;

 private int CurrentMaxY;


 private int stopdelayms;
 
 CGameRecords gameRecords;
 public String []strGameRecordList;
 public boolean GameOver = false;

 public boolean GameWon = false;

 public static long nFrame = 0;

 public static float _InitSpeed=1.5f;
 //
 public int Scores = 0;

 public int Level = 0;

 public int nLine = 0;
 
 public boolean GameStarted = false;
 public boolean GamePaused = false;
 
 public static   int STATE_NONE   =0;
 public static   int STATE_FELL   =1;
 public static   int STATE_LINEFULL  =2;
 public static   int STATE_LEVELUP  =4;
 public static   int STATE_GAMEOVER  =8;
 public static   int STATE_GAMEWON  =16;
 
 
 public int    m_GameState=STATE_NONE;
 
 int m_PlayingGifkey=CGameDrawerBase.NoneGif;
 
 public CTetrisMenu pCurMenu=null;
 
 public CTetrisMenu mainMenu=null;
 public CTetrisMenu pauseMenu=null;
 public CTetrisMenu soundMenu=null;
 public CTetrisMenu bgmMenu=null;
 public CTetrisMenu effectMenu=null;
 public CTetrisMenu volumeMenu=null;
 
 public CTetrisMenu gamemodeMenu=null;
 public CTetrisMenu heroesMenu=null;
 public CTetrisMenu creditsMenu=null;
 public CTetrisMenu exitMenu=null;
 public CTetrisMenu gameOverMenu=null;
 public CTetrisMenu gameWonMenu=null;
 public CTetrisMenu quitMenu=null;
 
 public CTetrisMenu levelUpMenu=null;
 
 
 
 
 //public boolean bSoundOn =true;
 
 public boolean bExit=false;
 
 public boolean bShowCredits=false;
 
 public boolean bShowRecords=false;
 
 public boolean bEnteringName=false;
 public String  szPlayerName ="";
 public String  szCurrentChar ="A";
 public int []fullLines = new int[4];
 public int numFullLines = 0;
 
 //
 CBlock CurBlock;

 CBlock NextBlock;

 public CGameDrawerBase gameDrawer = null;
 public CGameSoundPlayer soundPlayer = null;

 long GameStartTick = 0;
 

 public CGameField() {
  
 }
 


 
 public void Setup(int ScreenWidth, int ScreenHeight,
   CGameDrawerBase drawer,
   CGameSoundPlayer _soundPlayer) {
  
  soundPlayer =_soundPlayer;
  GameStartTick = System.currentTimeMillis();
  
  _Width = ScreenWidth;
  _Heigth = ScreenHeight;
  CGameField.nSquareSize = ScreenHeight / CGameField.VSquareNumber;
  if (ScreenWidth / CGameField.nSquareSize < (CGameField.HSquareNumber + CGameField.HAlignNumber)) {
   CGameField.nSquareSize = ScreenWidth
     / (CGameField.HSquareNumber + CGameField.HAlignNumber);
  }
  
  //System.out.println("nSquareSize :"+nSquareSize);

  int effectWidth = CGameField.nSquareSize
    * (CGameField.HSquareNumber + CGameField.HAlignNumber);
  int effectHeight = CGameField.nSquareSize * CGameField.VSquareNumber;

  //calc left top
  _LeftBattle = (_Width - effectWidth) / 2;
  _TopBattle = (_Heigth - effectHeight) / 2;

  _LeftIcon = _LeftBattle + CGameField.nSquareSize * 12+5;
  _TopIcon = _TopBattle + CGameField.nSquareSize;

  _LeftNextBL_LABLE = _LeftIcon;
  _TopNextBL_LABLE = _TopBattle + CGameField.nSquareSize * 4;
  _LeftNextBL = _LeftIcon;
  _TopNextBL = _TopBattle + CGameField.nSquareSize * 5;

  _LeftScore_LABLE = _LeftIcon;
  _TopScore_LABLE = _TopBattle + CGameField.nSquareSize * 11;
  _LeftScore = _LeftIcon;
  _TopScore = _TopBattle + CGameField.nSquareSize * 12;

  _LeftLevel_LABLE = _LeftIcon;
  _TopLevel_LABLE = _TopBattle + CGameField.nSquareSize * 13;
  _LeftLevel = _LeftIcon;
  _TopLevel = _TopBattle + CGameField.nSquareSize * 14+5;

  _LeftTime_LABLE = _LeftIcon;
  _TopTime_LABLE = _TopBattle + CGameField.nSquareSize * 15;
  _LeftTime = _LeftIcon;
  _TopTime = _TopBattle + CGameField.nSquareSize * 16+11;

  _LeftRECORD_LABLE = _LeftIcon;
  _TopRECORD_LABLE = _TopBattle + CGameField.nSquareSize * 17;
  _LeftRECORD = _LeftIcon;
  _TopRECORD = _TopBattle + CGameField.nSquareSize * 18+18;

  _LeftHINT_LABLE = _LeftIcon;
  _TopHINT_LABLE = _TopBattle + CGameField.nSquareSize * 19+18;
  _LeftHINT = _LeftIcon;
  _TopHINT = _TopBattle + CGameField.nSquareSize * 20+18;

  squares = new CSquare[VSquareNumber][HSquareNumber];
  for (int y = 0; y < VSquareNumber; y++) {
   for (int x = 0; x < HSquareNumber; x++) {
    squares[y][x] = new CSquare();
    squares[y][x].Setup(x,y,
      _LeftBattle  + nSquareSize * (x+1),
     _TopBattle+ nSquareSize * (VSquareNumber - y - 1)
     ); 
   }
  }
  reset();

  gameDrawer = drawer;

  LoadRecord();
  CreateMenus();
  pCurMenu = mainMenu;
 }
 
 String  [] optionsMain={
   "START",
   "HEROES",
   "SOUND",
   "GAME MODE",
   "CREDITS",
   "EXIT"
  };
  
 String  [] optionsPause={
   "RESUME",
   "SOUND",
   "CREDITS",
   "HEROES",
   "QUIT",
   "EXIT"
  };
 
 String  [] optionsGameMode={
   "EASY",
   "HARD",
   "ELITE"
  };

 String  [] optionsSound={
   "BG MUSIC",
   "EFFECT SOUND",
   "VOLUME",
   "OK",
  };
 
 String [] optionsOnOff={
   "ON",
   "OFF"
 };
 
 String [] optionsVolume={
  "0",
  "5",
  "25",
  "50",
  "75",
  "100",
 };
 
 String  [] optionsYesNo={
   "YES",
   "NO"
  };
 
 String  [] optionsOK={
   "OK",
  };
 
 String []optionsLevelUp= {
  "Continue?", 
 };
 
 String []creditHints={
   " ",
   "PROGRAMMER",
   "DANY",
   "CONTACT",
   "DANY21CN@21CN.COM",
   "THANKS",
   "NICOLE",
   " ",
 };
 
 String []gamewonHints={
   " ",
   "Congratulations!",
   "You are Winner",
   " ",
 };
 
 String []levelupHints={
   " ",
   "Congratulations!",
   "LEVEL  ",
   ""
 };
 
 
 String []gameoverHints={
   " ",
   "Sorry",
   "Please try again!",
   " ",
 };
 
 
 
 
 private void CreateMenus()
 {
  
  //CTetrisMenu(int id, String _Title, String [] _options, String [] _Hints,Rectangle _rect, boolean hozi)
   mainMenu=new CTetrisMenu(1,
     "TERTIS",
     optionsMain,
     null,
     new Rectangle(25,120,120,120),
     false);
  
   pauseMenu=new CTetrisMenu(1,
     "PAUSED",
     optionsPause,
     null,
     new Rectangle(25,120,120,120),
     false);
  
   soundMenu=new CTetrisMenu(1,
     "SOUND",
     optionsSound,
     null,
     new Rectangle(25,120,120,100),
     false);
  
   bgmMenu=new CTetrisMenu(1,
     "BG MUSIC",
     optionsOnOff,
     null,
     new Rectangle(25,120,120,120),
     false);
  
   effectMenu = new CTetrisMenu(1,
     "EFFECT SOUND",
     optionsOnOff,
     null,
     new Rectangle(25,120,120,120),
     false);
  
   volumeMenu = new CTetrisMenu(1,
      "VOLUME",
      optionsVolume,
      null,
      new Rectangle(25,120,120,120),
      false);
  
   gamemodeMenu=new CTetrisMenu(1,
     "MODE",
     optionsGameMode,
     null,
     new Rectangle(25,120,120,90),
     false);
  
   heroesMenu=new CTetrisMenu(1,
     "HEROES",
     optionsOK,
     strGameRecordList,
     new Rectangle(8,65,160,200),
     false);
  
   creditsMenu=new CTetrisMenu(1,
     "CREDITS",
     optionsOK,
     creditHints,
     new Rectangle(8,65,160,180),
     false);
  
   exitMenu=new CTetrisMenu(1,
     "EXIT NOW?",
     optionsYesNo,
     null,
     new Rectangle(25,120,120,90),
     false);
  
   quitMenu=new CTetrisMenu(1,
     "QUIT THE GAME?",
     optionsYesNo,
     null,
     new Rectangle(25,120,120,90),
     false);
 
   gameOverMenu=new CTetrisMenu(1,
     "GAME OVER",
     optionsOK,
     gameoverHints,
     new Rectangle(18,140,140,120),
     false);
  
   gameWonMenu = new CTetrisMenu(1,
     "YOU WIN!",
     optionsOK,
     gamewonHints,
     new Rectangle(18,140,140,120),
     false);
  
   levelUpMenu = new CTetrisMenu(1,
     "LEVEL UP!",
     optionsLevelUp,
     levelupHints,
     new Rectangle(18,140,140,120),
     false);
  
  
 }

 private void CreateBlocks() {
  int x = CGameField.HSquareNumber / 2;
  int y = CGameField.VSquareNumber
  - CGameField.nDeadAreaHeight;
  
  CurBlock.Create(NextBlock.Type, NextBlock.orientation,
    x,y,squares[y][x].getAbsX(),squares[y][x].getAbsY());
  NextBlock.Create(BLOCK_TYPE.undefine, -1, 0, 0,0,4*nSquareSize);
  NextBlock.CenterAbs(new Rectangle(165,75,60,70));
 }

 public boolean StartGame() {
//  if (GamePaused) {
//   //already started
//   //
//   return true;
//  }
  
  GameStartTick = System.currentTimeMillis();
  
  this.reset();
  CurBlock = new CBlock();
  NextBlock = new CBlock();

  CreateBlocks();

  CurBlock.Speed = _InitSpeed;
  GameStarted = true;
  GamePaused = false;
  GameOver = false;
  soundPlayer.PlayBackgroundMusic();
  
  return true;
 }

 public boolean Pause() {
  boolean res = PauseInternal();
  if(res) pCurMenu = pauseMenu;
  return res;
 }
 
 public boolean PauseInternal()
 {
  if (GameStarted && !GamePaused) {
   soundPlayer.StopBackgroundMusic();
   GamePaused = true;
   return true;
  }
  return GamePaused;
 }

 public void Resume() {
  if (GameStarted && GamePaused) {
   CurBlock.Resume();
   soundPlayer.PlayBackgroundMusic();
   GamePaused = false;
  }

 }

 public void reset() {
  for (int y = 0; y < VSquareNumber; y++) {
   for (int x = 0; x < HSquareNumber; x++) {
    squares[y][x].IsHide = true;
   }
  }
  numFullLines = 0;
  CurrentMaxY = -1;
  Scores = 0;
  stopdelayms = 250;
  Level = 1;
  nLine = 0;
 }
 
 long gameplaydiff=0;
 
 public void DrawBackGround(CGameDrawerBase drawer) {
  gameDrawer.clear(Color.Black);

//  Point p1 = new Point(_LeftBattle + nSquareSize - 1, _TopBattle
//    + nSquareSize * 4);
//  Point p2 = new Point(_LeftBattle + nSquareSize * 11, p1.Y);
//  Point p3 = new Point(p2.X, _TopBattle + nSquareSize * 22);
//  Point p4 = new Point(p1.X, p3.Y);
//  drawer.DrawLine(Color.Tomato, p1, p2);
//  drawer.DrawLine(Color.Blue, p2, p3);
//  drawer.DrawLine(Color.Blue, p3, p4);
//  drawer.DrawLine(Color.Blue, p4, p1);

//  drawer
//    .DrawString("TETRIS", Color.DarkBlue, new Point(_LeftIcon,
//      _TopIcon));
//  drawer.DrawString("BY Dany", 0, new Point(_LeftIcon, _TopIcon
//    + CGameField.nSquareSize));

//  drawer.DrawString("NEXT", Color.White, new Point(_LeftNextBL_LABLE,
//    _TopNextBL_LABLE));

//  drawer.DrawString("SCORE", Color.White, new Point(_LeftScore_LABLE,
//    _TopScore_LABLE));
  
  drawer.DrawStringCenterVH((new Integer(Scores)).toString(), 0,
    new Point(203, 178));

//  drawer.DrawString("LEVEL", Color.White, new Point(_LeftLevel_LABLE,
//    _TopLevel_LABLE));
  
  drawer.DrawStringCenterVH((new Integer(Level)).toString(), 0,
    new Point(203, 212));

  if (GameStarted&&!GamePaused)
    gameplaydiff= System.currentTimeMillis() - GameStartTick;
  
  long nMinutes = gameplaydiff/1000/60;
  long nSeconds = gameplaydiff/1000 - nMinutes*60;
//  float fps = 0.0f;
//  if (diff > 0)
//   fps = ((float) nFrame / (float) diff * 1000.0f);

//  drawer.DrawString("LINES", Color.DarkBlue, new Point(_LeftTime_LABLE,
//    _TopTime_LABLE));
  drawer.DrawStringCenterVH((new Integer(nLine)).toString(), 0, new Point(
    203, 246));

//  drawer.DrawString("RECORD", Color.DarkBlue, new Point(_LeftRECORD_LABLE,
//    _TopRECORD_LABLE));
 
   drawer.DrawStringCenterVH(""+nMinutes+":"+nSeconds,
     0, new Point(203, 282));

  drawer.DrawStringCenterVH("PRESS B", 0, new Point(203,
    294));
  
  drawer.DrawStringCenterVH("TO EXIT", 0,
    new Point(203, 306));

  for (int y = 0; y < VSquareNumber; y++) {
   for (int x = 0; x < HSquareNumber; x++) {
    drawer.DrawSquare(squares[y][x]);
   }
  }

 }

 void AddBlock(CBlock block) {
  for (int i = 0; i < 4; i++) {
   squares[block.qs[i].getY()][block.qs[i].getX()].Assign(block.qs[i]);

  }

  if (CurrentMaxY < block.MaxY()) {
   CurrentMaxY = block.MaxY();
  }
 }

 public boolean Intersected(int x, int y) {
  if (x >= 0 && x < HSquareNumber && y >= 0 && y < VSquareNumber) {
   return !squares[y][x].IsHide;
  }
  return false;
 }

 public boolean Intersected(CBlock block) {
  for (int i = 0; i < 4; i++) {
   if (Intersected(block.qs[i].getX(), block.qs[i].getY())) {
    return true;
   }
  }
  return false;
 }

 public boolean ShouldStopFalling(CBlock block, long curTick) {
  for (int i = 0; i < 4; i++) {
   int nx = block.qs[i].getX();
   int ny = block.qs[i].getY() - 1;

   if (ny < 0
     || (ny < VSquareNumber && nx < HSquareNumber && !squares[ny][nx].IsHide)) {
    //if (block.StopTick == 0)
    //{
    //    block.StopTick = curTick;
    //}
    //else if (curTick - block.StopTick >= stopdelayms)
    //{
    AddBlock(block);
    
   
    m_GameState |= STATE_FELL;
    
    return true;
    //}
   }
  }

  return false;
 }

 void CopyDown(int stY) {
  int my = CurrentMaxY + 1;
  for (int y = stY; y < my + 1; y++) {
   for (int x = 0; x < HSquareNumber; x++) {
    squares[y][x].IsHide = squares[y + 1][x].IsHide;
    squares[y][x].HightLight = squares[y + 1][x].HightLight;
    squares[y][x].color = squares[y + 1][x].color;
   }
  }
 }
 
 
 void CalcScore(int nLine)
 {
  
  switch (nLine) {
  case 1:
   Scores += 10;
   break;
  case 2:
   Scores += 40;
   break;
  case 3:
   Scores += 80;
   break;
  case 4:
   Scores += 160;
   break;
  }
 }
 
 boolean IsLevelUp()
 {
  
  int oldLevel = Level;
  if (Scores >= 500 && Scores < 1500) {
   Level = 2;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 1500 && Scores < 3000) {
   Level = 3;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 3000 && Scores < 5000) {
   Level = 4;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 5000 && Scores < 7500) {
   Level = 5;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 7500 && Scores < 10500) {
   Level = 6;
   stopdelayms = (int) (stopdelayms * 0.9f);
  } else if (Scores >= 10500 && Scores < 14000) {
   Level = 7;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 14000 && Scores < 18000) {
   Level = 8;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 18000 && Scores < 22500) {
   Level = 9;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 22500 && Scores < 27500) {
   Level = 10;
   stopdelayms = (int) (stopdelayms * 0.95f);
  } else if (Scores >= 27500) {
   Level = 11;
   stopdelayms = (int) (stopdelayms * 0.95f);
  }
//  else
//   return true;
  
  return oldLevel<Level;
 }
 
 void DeleteLines()
 {
  if(numFullLines<=0) return;
  
  int deletedLine = numFullLines;
  numFullLines =0;
  
  for(int i=deletedLine-1;i>=0;i--)
  {
   CopyDown(fullLines[i]);
   CurrentMaxY--;
  }
  
  nLine+=deletedLine;
 
 }

 public int CheckFullLinesNum() {
  
  if(numFullLines!=0)
  {
   return numFullLines;
  }
  
  for (int y = 0; y < CurrentMaxY + 1; y++) {
   int x = 0;
   for (x = 0; x < HSquareNumber; x++) {
    if (squares[y][x].IsHide) {
     break;
    }
   }
   
   if (x == HSquareNumber) {
    fullLines[numFullLines++]=y;
    for (x = 0; x < HSquareNumber; x++) {
     squares[y][x].HightLight=true;
    }
   }
  }
  
  if(numFullLines!=0)
  {
   m_GameState|=STATE_LINEFULL;
  }
 
  
  return numFullLines;
 }

 public boolean IsFull() {
  if (CurrentMaxY >= (VSquareNumber - nDeadAreaHeight))
   return true;

  return false;
 }

 public boolean IsANewRecord() {

  try {
   return gameRecords.isHighScore(this.Scores);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return false;
 }

 public void AddNewRecord(String name) {
  try {
   gameRecords.updateScores(this.Scores,name);
   genGameRecordStrings();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public void Flush() {
  gameDrawer.Flip();
 }
 
 public void genGameRecordStrings()
 {
  if(gameRecords !=null)
  {
   String []fills =
   {
     "",
     " ",
     "  ",
     "   ",
     "    ",
     "     ",
     "      ",
     "       ",
     "        ",
     "         ",
     "          ",
   };
   int []values = gameRecords.getValues();
   String []names = gameRecords.getNames();
   if(strGameRecordList==null)
   {
    strGameRecordList = new String[names.length+2];
    strGameRecordList[0] = " ";
    strGameRecordList[strGameRecordList.length-1]=" ";
   }
   for(int i=0;i<names.length;i++)
   {
    String szvalues = ""+values[i];
    strGameRecordList[i+1] = names[i]+
    fills[6-names[i].length()]+
    " "+
    fills[10-szvalues.length()]+szvalues;
   }
   
  }
 }

 boolean CheckGameOver()
 {
  if (IsFull()) {
   GameStarted = false;
   GameOver = true;
  
   m_GameState|=STATE_GAMEOVER;
   pCurMenu = gameOverMenu;
   pCurMenu.SetCurSel(-1);
  
   soundPlayer.StopBackgroundMusic();
   return true;
  }
  return false;
 }
 
 boolean CheckGameWon()
 {
  if (Level >= 11) {
   GameStarted = false;
   GameWon = true;
   pCurMenu = gameWonMenu;
   pCurMenu.SetCurSel(-1);
   soundPlayer.StopBackgroundMusic();
   m_GameState |= STATE_GAMEWON;
   return true;
   
  }
  return false;
 }
 
 public void ProcessFrame()
 {
  long curTick = System.currentTimeMillis();
  
  //Polling the sound player.
  //
  soundPlayer.ControlEffectSound();
  
  if (GameStarted&&!GamePaused && m_PlayingGifkey==CGameDrawerBase.NoneGif)
  {
   
   //Is needed to clear up the full lines?
   //
   if(numFullLines>0)
   {
    //calc Score
    //
    CalcScore(numFullLines);
    
    //Delete full lines
    //
    DeleteLines();
    
    
    //Is leveling up?
    //
    if (IsLevelUp())
    {
     m_GameState|=STATE_LEVELUP;     
     
     //Leveling up..
     //
     CurBlock.Speed = CurBlock.Speed * 1.2f;
    }
    
    CheckGameWon();
    CheckGameOver();
    
    if(!CheckGameWon() && !CheckGameOver())
    {
     //Play with Next Block;
     //
     CreateBlocks();
    }
    return;
   }
   
   if (ShouldStopFalling(CurBlock, curTick))
   {
    if(CheckFullLinesNum()>0)
    {
     return;
    }

    if (!CheckGameOver()){
     //Play with Next Block;
     //
     CreateBlocks();
    }
    return;
   }

   //Update Current Block Loction.
   //
   CurBlock.UpdateLocation(this, curTick);
  }

 }
 
 int ind = 0;
 
 void DrawScene()
 { 
  DrawBackGround(gameDrawer);
  
  if (CurBlock != null && (numFullLines<=0))
   CurBlock.Draw(gameDrawer);
  
  if (NextBlock != null)
   NextBlock.Draw(gameDrawer);
  
  if(pCurMenu!=null)
   pCurMenu.Draw(gameDrawer);
  
  gameDrawer.DrawGifFrame(m_PlayingGifkey);
  

  if(bEnteringName )
  {
   gameDrawer.DrawGameMenuFrame(new Rectangle(15,120,140,80));
   
   gameDrawer.DrawStringCenterVH("ENTER NAME", TETRIS_FONT.Title, new Point(
     83, 120 + 10));
   
   String tmpsz = szPlayerName;
   if(nFrame%2==0)
    tmpsz +=szCurrentChar;
   gameDrawer.DrawString(tmpsz, 0, new Point(
     56, 120 + 10 + 20));
  }
  
//  Image  frame = gifDecoder.getFrame(ind);
//         int delay = gifDecoder.getDelay(ind);
//         System.out.println("frame = " + ind + "  delay = " + delay);
//         ind++;
//         .drawImage(frame, 0, 0, 0);
       // do something with frame
 }
 
 public void PlayEffectSounds()
 {
  int ikey=-1;
  if((m_GameState&STATE_GAMEWON)!=0)
  {
   ikey = CGameSoundPlayer.soundGamewon;
  }
  else if((m_GameState&STATE_GAMEOVER)!=0)
  {
   ikey = CGameSoundPlayer.soundGameover;
  }
  else if((m_GameState&STATE_LEVELUP)!=0)
  {
   PauseInternal();
   ikey = CGameSoundPlayer.soundLevelup;
  }
  else if((m_GameState&STATE_LINEFULL)!=0)
  {
   ikey = CGameSoundPlayer.soundLinefull;
  
  }
  else if((m_GameState&STATE_FELL)!=0)
  {
   ikey = CGameSoundPlayer.soundFell;
  }
  soundPlayer.PlayEffectSound(ikey);
  m_GameState &=~STATE_FELL;
  m_GameState &=~STATE_LINEFULL;
 }
 


 

 public void PlayEffectAnimates()
 {
  
  if(m_PlayingGifkey==CGameDrawerBase.NoneGif)
  {
   if((m_GameState&STATE_GAMEWON)!=0)
   {
    m_PlayingGifkey = CGameDrawerBase.GameWonGif;
    gameDrawer.PlayGif(m_PlayingGifkey,25,70,24*60*60000);
    
   }
   else if((m_GameState&STATE_GAMEOVER)!=0)
   {
    m_PlayingGifkey = CGameDrawerBase.GameOverGif;
    gameDrawer.PlayGif(m_PlayingGifkey,55,80,24*60*60000);
   }
   else if((m_GameState&STATE_LEVELUP)!=0)
   {
    m_PlayingGifkey = CGameDrawerBase.LevelUpGif;
    gameDrawer.PlayGif(m_PlayingGifkey,50,70,24*60*60000);
    levelupHints[2] = "YOU ARE LEVEL "+Level;
    pCurMenu = levelUpMenu;
    
   }

  }
  else
  { 
   //System.out.println("m_PlayingGifkey :"+m_PlayingGifkey);
   
   if(gameDrawer.GetGifState(m_PlayingGifkey)==CGameDrawerBase.GIF_STOPPED)
   {
    if(m_PlayingGifkey==CGameDrawerBase.LevelUpGif)
    {
     Resume();
    }
    else if(m_PlayingGifkey==CGameDrawerBase.GameOverGif)
    {
     
    }
    else if(m_PlayingGifkey==CGameDrawerBase.GameOverGif)
    {
     
    }
    
    m_PlayingGifkey=CGameDrawerBase.NoneGif;
   }
   
   
  
  }
//  m_GameState &=~STATE_GAMEWON;
//  m_GameState &=~STATE_GAMEOVER;
//  m_GameState &=~STATE_LEVELUP;
//  m_GameState &=~STATE_FELL;
//  m_GameState &=~STATE_LINEFULL;
  m_GameState =0;
 }
 
 public void OnGameFrame() {
  
  nFrame++;
  ProcessFrame();
  PlayEffectSounds();
  PlayEffectAnimates();
  DrawScene();
 
  
 }

 public void OnPointerPressed(int x, int y)
 {
  if(pCurMenu!=null)
  {
   pCurMenu.DoPointerPressed(x,y);
   ProcessMenuSelection();
  }
  else
  {
   if(GameStarted && !GamePaused && !GameOver && !GameWon)
   {
    Pause();
   }
  }
  
 }
 
 public void ProcessMenuSelection()
 {
  if(pCurMenu.IsDone())
  {
   pCurMenu.reset();
   
   int cursel=pCurMenu.GetCurSel();
   //System.out.println("cursel:"+pCurMenu.GetCurSel());
   
   if(pCurMenu == mainMenu)
   {
    switch(cursel)
    {
//    "START",
//    "HEROES",
//    "SOUND",
//    "GAME MODE",
//    "CREDITS",
//    "EXIT"
     case 0:
      StartGame();
      pCurMenu =null;
      break;
     case 1:
      heroesMenu.parent = pCurMenu;
      pCurMenu = heroesMenu;
      break;
     case 2:
      soundMenu.parent = pCurMenu;
      pCurMenu = soundMenu;
      break;
     case 3:
      gamemodeMenu.parent = pCurMenu;
      pCurMenu = gamemodeMenu;
      break;
     case 4:
      creditsMenu.parent= pCurMenu;
      pCurMenu =creditsMenu;
      break;
     case 5:
      exitMenu.parent = pCurMenu;
      pCurMenu = exitMenu;
      break;
     default:
      pCurMenu =null;
      break;
    }
    
   }
   else if(pCurMenu == pauseMenu)
   {
//    "RESUME",
//    "SOUND",
//    "CREDITS",
//    "QUIT",
//    "EXIT"
    switch(cursel)
    {
     case 0:
      Resume();
      pCurMenu =null;
      break;
     case 1:
      soundMenu.parent = pCurMenu;
      pCurMenu = soundMenu;
      break;
     case 2:
      creditsMenu.parent= pCurMenu;
      pCurMenu =creditsMenu;
      break;
     case 3:
      heroesMenu.parent = pCurMenu;
      pCurMenu = heroesMenu;
      break;
     case 4:
      quitMenu.parent =pCurMenu;
      pCurMenu = quitMenu;
      soundPlayer.StopBackgroundMusic();
      break;
     case 5:
      exitMenu.parent = pCurMenu;
      pCurMenu = exitMenu;
      break;
     default:
      pCurMenu =null;
      break;
    }
    
   }
   else if(pCurMenu == soundMenu)
   {
    switch(cursel)
    {
//    "BGM"    
//    "EFFECT",
    case 0:
     bgmMenu.parent = pCurMenu;
     pCurMenu = bgmMenu;
     break;
    case 1:
     effectMenu.parent = pCurMenu;
     pCurMenu = effectMenu;
     break;
    case 2:
     volumeMenu.parent = pCurMenu;
     pCurMenu = volumeMenu;
     break;
    case 3:
     pCurMenu = pCurMenu.parent;
     break;
    }
   }
   else if(pCurMenu==effectMenu)
   {
    switch(cursel)
    {
    case 0:
     soundPlayer.EnableEffectSound(true);
     break;
    case 1:
     soundPlayer.EnableEffectSound(false);
     break;
    }
    pCurMenu = pCurMenu.parent;
   }
   else if(pCurMenu==bgmMenu)
   {
    switch(cursel)
    {
    case 0:
     soundPlayer.EnableBgMusic(true);
     if(GameStarted)
      soundPlayer.PlayBackgroundMusic();
     
     break;
    case 1:
     soundPlayer.StopBackgroundMusic();
     soundPlayer.EnableBgMusic(false);
     break;
    }
    pCurMenu = pCurMenu.parent;
   }
   else if(pCurMenu == volumeMenu)
   {
    int []levels={0,5,25,50,75,100};
    switch(cursel)
    {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
     soundPlayer.SetVolume(levels[cursel]);
     break;
    }
    pCurMenu = pCurMenu.parent;
   }
   else if(pCurMenu == exitMenu)
   {
//      "YES",
//      "NO"
//
    switch(cursel)
    {
    case 0:
     this.bExit = true;
     break;
    case 1:
     pCurMenu = pCurMenu.parent;
     break;
    }
   }
   else if(pCurMenu == quitMenu)
   {
//      "YES",
//      "NO"
//
    switch(cursel)
    {
    case 0:
     pCurMenu = mainMenu;
     break;
    case 1:
     pCurMenu = pCurMenu.parent;
     break;
    }
   }
    
   else if(pCurMenu == gamemodeMenu)
   {
//    "EASY",
//    "HARD",
//    "ELITE"
    
    switch(cursel)
    {
    case 0:
     _InitSpeed = 1.5f;
     break;
    case 1:
     _InitSpeed = 2.5f;
     break;
    case 2:
     _InitSpeed = 4.0f;
     break;
    }
    pCurMenu = pCurMenu.parent;
   }
   else if(pCurMenu == gameOverMenu||pCurMenu == gameWonMenu)
   {
    
    soundPlayer.StopEffectSound();
    gameDrawer.StopGif(m_PlayingGifkey);
    
    if(IsANewRecord())
    {
     bEnteringName=true;
     pCurMenu =null;
    }
    else
    {
     pCurMenu = mainMenu;
    }
   }
   else if(pCurMenu ==levelUpMenu)
   {
    gameDrawer.StopGif(m_PlayingGifkey);
    pCurMenu =null;
   }
   else
   {
    if(pCurMenu!=null)
    {
     pCurMenu = pCurMenu.parent;
    }
   }
    
  }
 }
 
 public void OnKeyDown(int keycode) {
  

  if(bEnteringName)
  {
   char cc = szCurrentChar.charAt(0);
   char oldcc=cc;
   switch (keycode) {
    
    case TETRIS_KEYCODE.Up:
     cc--;
     if(cc<'A')
     {
      cc='Z';
     }
     
     szCurrentChar=szCurrentChar.replace(oldcc,cc);
     break;
    case TETRIS_KEYCODE.Down:
     cc++;
     if(cc>'Z')
     {
      cc='A';
     }
     szCurrentChar=szCurrentChar.replace(oldcc,cc);
     break;
    case TETRIS_KEYCODE.Left:
     if(szPlayerName.length()>0)
     {
      cc= szPlayerName.charAt(szPlayerName.length()-1);
      if(szPlayerName.length()<=1)
       szPlayerName ="";
      else
       szPlayerName =szPlayerName.substring(0,szPlayerName.length()-1);
      szCurrentChar=szCurrentChar.replace(oldcc,cc);
     }
     
     break;
    case TETRIS_KEYCODE.Right:
     szPlayerName +=szCurrentChar;
     break;
    case TETRIS_KEYCODE.Rotate:
     szPlayerName +=szCurrentChar;
     if(szPlayerName.length()>0)
     {
      
      bEnteringName =false;
      bShowRecords = true;
      AddNewRecord(szPlayerName);
      pCurMenu = heroesMenu;
      pCurMenu.parent = mainMenu;
     }
      
     break;
     
   }
   
   if(szPlayerName.length()>=6)
   {
    bEnteringName =false;
    bShowRecords = true;
    AddNewRecord(szPlayerName);
    //System.out.println(szPlayerName);
    pCurMenu = heroesMenu;
    pCurMenu.parent = mainMenu;
   }
   return;
  }
  
  if(pCurMenu!=null)
  {
   pCurMenu.DoKeyPressed(keycode);
   ProcessMenuSelection();
   return;
  }
  
  
   
  if (GameStarted) {
   switch (keycode) {
   case TETRIS_KEYCODE.Down:
    CurBlock.Down(this);
    break;
   case TETRIS_KEYCODE.Left:
    CurBlock.Left(this);
    break;
   case TETRIS_KEYCODE.Right:
    CurBlock.Right(this);
    break;
   case TETRIS_KEYCODE.Rotate:
    CurBlock.Rotate(this);
    break;
   case TETRIS_KEYCODE.Escape:
    Pause();
    break;
   }
  }
   
 }

 public void SaveRecord() {

 }

 int GetTopRecord() {
  int top = 99999;
  return top;
 }

 void LoadRecord() {
  
  gameRecords = new CGameRecords("TetrisGameRecords");
  try {
   //gameRecords.reset();
   gameRecords.loadScores();
   genGameRecordStrings();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }
}
 

 

 

 

 

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值