俄罗斯方块源码(2)

类别:Java 点击:0 评论:0 推荐:

package Tetris;

import java.util.Vector;
import java.util.Enumeration;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.GameCanvas;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class TetrisGameCanvas extends GameCanvas  implements Runnable{
  private Tetris tetrisCurrent = new Tetris();
  private Tetris tetrisNext = new Tetris();

  public static final int COL = 10;
  public static final int ROW = 22;
  public static final int LEN = 12;

  public static final int DOWN = 1003;
  public static final int LEFT = 1004;
  public static final int RIGHT = 1005;
  public static final int ROTATE = 1006;

  public static int CELL_WIDTH;
  public static int BASE_X;
  public static int BASE_Y;

  public static final int ST_PLAY = 1000;
  public static final int ST_PAUSE = 1001;
//  public static final int ST_PLAYRE = 1002;
  public static final int ST_WELCOM = 1003;
  public static final int ST_POINT = 1004;

  private boolean [][] fixCellData = new boolean [ROW][COL];
  private int [][] fixCellColor = new int [ROW][COL];

  private boolean conti = true;// 游戏是否继续
  private boolean begin = true;
  private int speed = 350;// 下降速度
  private int state = ST_WELCOM;// 游戏状态
  private int point = 0;// 游戏得分
  private int oldPoint = 0;
//  private boolean flash = false;//是否有消行处理

  private int newLineTop = 21;// 被消行的最上行
  private int newLineBotton = 0;// 被消行的最下行

  public TetrisGameCanvas() {
    super(true);// 抑制键盘事件

    CELL_WIDTH = getHeight() / (ROW + 2);
    BASE_X = (getWidth() - CELL_WIDTH * COL) / 2;
    BASE_Y = CELL_WIDTH;

    // 整个游戏界面中每个方格填充状态为空
    for (int row = 0; row < ROW; row ++)
      for (int col = 0; col < COL; col++) {
        fixCellData[row][col] = false;
      }

    // 下一个方块新形状数据的生成
    tetrisNext.newShape();
  }

  public void newGame() {
    state = ST_PLAY;
    // 整个游戏界面中每个方格填充状态为空
    for (int row = 0; row < ROW; row++)
      for (int col = 0; col < COL; col++) {
        fixCellData[row][col] = false;
      }
    point = 0;
    tetrisNext.newShape();
    tetrisCurrent.setShape(tetrisNext);
  }

  private void beginGame() {
    for (int row = 0; row < ROW; row ++)
      for (int col = 0; col < COL; col++)
        fixCellData[row][col] = false;

    point = 0;
    state = ST_PLAY;
    startStep();
  }

  public void pauseGame() {
    state = ST_PAUSE;
  }

  public void resumeGame() {
    state = ST_PLAY;
  }

  private void endGame() {
    state = ST_POINT;
  }

  private void startStep() {
    tetrisCurrent.setShape(tetrisNext);
    if (shapeValid(tetrisCurrent)) {//通过检测,未到达上边框,动作可以继续
      tetrisNext.newShape();
    } else {// 到达上边框
     endGame();
    }
  }

  private void midStep() {
    if (!changeShape(DOWN)) {
      endStep();
    }
  }

  private void endStep() {
    newLineTop = 21;
    newLineBotton = 0;
    // 方块固定到区域中
    int iCellColor = 0;
    int row;
    int col;
    for (row = 0; row < 3; row ++)
      for (col = 0; col < 3; col ++) {
        if (tetrisCurrent.getShapeData(row, col)) {
          fixCellData[tetrisCurrent.by + row][tetrisCurrent.bx + col]
              = true;
          fixCellColor[tetrisCurrent.by + row][tetrisCurrent.bx + col]
              = tetrisCurrent.getCellColor(iCellColor ++);
          newLineTop = newLineTop < (tetrisCurrent.by + row) ? newLineTop : (tetrisCurrent.by + row);
          newLineBotton = newLineBotton > (tetrisCurrent.by + row) ? newLineBotton : (tetrisCurrent.by + row);
        }
      }
    // 一字条状的特殊处理
    if (tetrisCurrent.shape == 0) {
      if (tetrisCurrent.direction == 1 || tetrisCurrent.direction == 3) {
        col = 1;
        row = 3;
      } else {
        col = 3;
        row = 1;
      }
      fixCellData[tetrisCurrent.by + row][tetrisCurrent.bx + col]
          = true;
      fixCellColor[tetrisCurrent.by + row][tetrisCurrent.bx + col]
          = tetrisCurrent.getCellColor(iCellColor);
      newLineTop = newLineTop < (tetrisCurrent.by + row) ? newLineTop :
          (tetrisCurrent.by + row);
      newLineBotton = newLineBotton > (tetrisCurrent.by + row) ?
          newLineBotton : (tetrisCurrent.by + row);
    }
    // 新的方块产生
    startStep();
  }

  public void start() {
    Thread thread = new Thread(this);
    thread.start();
  }

  public void exit() {
    conti = false;
    endGame();
  }

  public void run() {
    Graphics graphics = getGraphics();
    long startTime = 0;
    long endTime = 0;
    while (conti) {
      switch (state) {
        case ST_WELCOM: {
          startTime = System.currentTimeMillis();
          renderWelcom(graphics);
          endTime = System.currentTimeMillis();
          if ( (endTime - startTime) < 300) {
            try {
              Thread.sleep(300 - (endTime - startTime));
            }
            catch (Exception exp) {}
          }
          break;
        }

        case ST_PLAY: {
           startTime = System.currentTimeMillis();
          if (begin == true) {
            beginGame();
            begin = false;
          }
          else {
            input();
            midStep();
          }
          renderTetris(graphics);
          endTime = System.currentTimeMillis();
          System.out.println(endTime - startTime);
          if ((endTime - startTime) < speed) {
            try {
              Thread.sleep(speed - (endTime - startTime));
            }
            catch (Exception exp) {}
          }
          autoAddLevel();
          System.gc();
          break;
        }

        case ST_POINT: {
          startTime = System.currentTimeMillis();
          renderPoint(graphics);
          endTime = System.currentTimeMillis();
          if ( (endTime - startTime) < 1500) {
            try {
              Thread.sleep(1500 - (endTime - startTime));
            }
            catch (Exception exp) {}
          }
          state = ST_WELCOM;
          break;
        }

        case ST_PAUSE: {
          startTime = System.currentTimeMillis();
          input();
          renderTetris(graphics);
          endTime = System.currentTimeMillis();
          if ( (endTime - startTime) < speed) {
            try {
              Thread.sleep(speed - (endTime - startTime));
            }
            catch (Exception exp) {}
          }
          break;
        }
      }
    }
  }

  /**
   * 接收键盘输入
   */
  public void input() {
    int keyState = getKeyStates();
    if ((keyState & UP_PRESSED) != 0
        || (keyState & FIRE_PRESSED) != 0) {
      changeShape(ROTATE);
    }
    else if ((keyState & LEFT_PRESSED) != 0) {
      changeShape(LEFT);
    }
    else if ((keyState & RIGHT_PRESSED) != 0) {
      changeShape(RIGHT);
    }
    else if ( (keyState & DOWN_PRESSED) != 0) {
      midStep();
    }
    getKeyStates();
    getKeyStates();
  }

  /**
   * 绘制欢迎画面
   * @param graphics
   */
  public void renderWelcom (Graphics graphics) {
    graphics.setColor(Tetris.COLOR_WHITE);
    graphics.fillRect(0, 0, getWidth(), getHeight());
//      Image welcomImage = null;
//      try {
//        welcomImage.createImage("/pic/welcom.png");
//      } catch (Exception exp) {}
//      graphics.drawImage(welcomImage, 0, 0, Graphics.TOP | Graphics.LEFT);
    int centerX = getWidth() / 2;
    int centerY = getHeight() / 2;
//    graphics.setColor(Tetris.COLOR_BLUE);
//      graphics.drawLine(centerX - 40, centerY - 20, centerX - 34, centerY - 20);
//      graphics.drawLine(centerX - 40, centerY + 20, centerX - 34, centerY + 20);
//      graphics.drawLine(centerX - 40, centerY - 20, centerX - 40, centerY + 20);
//      graphics.drawLine(centerX - 34, centerY - 20, centerX - 34, centerY + 20);
    for (int i = 0; i <7; i++) {
      graphics.setColor(Tetris.COLOR_DATA[i]);
      graphics.drawString("☆", Tetris.getRandom() % getWidth(), Tetris.getRandom() % getHeight(),
                          Graphics.TOP | Graphics.HCENTER);
    }
  /*
    graphics.drawString("☆", 10, 20, Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆", 100, 10, Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆", 30, 80, Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆", 150, 80, Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆", 180, 20, Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆", 200, 80, Graphics.TOP | Graphics.HCENTER);*/
    graphics.setColor(Tetris.COLOR_DATA[Tetris.getRandom() % 6]);
    graphics.drawString("☆☆☆Tetris☆☆☆", centerX, centerY - 20,
                        Graphics.TOP | Graphics.HCENTER);
    graphics.drawString("☆☆☆☆INE☆☆☆☆", centerX, centerY,
                        Graphics.TOP | Graphics.HCENTER);
    flushGraphics();
  }

  /**
   * 方块游戏画面绘制
   * @param graphics
   */
  public void renderTetris (Graphics graphics) {
      graphics.setColor(Tetris.COLOR_BLUE);
      graphics.fillRect(0, 0, getWidth(), getHeight());
      graphics.setColor(Tetris.COLOR_WHITE);
      graphics.drawRect(BASE_X - 2, BASE_Y - 2, CELL_WIDTH * COL + 4,
                        CELL_WIDTH * ROW + 4);
      graphics.setColor(Tetris.COLOR_GRAY);
      graphics.drawRect(BASE_X - 1, BASE_Y - 1, CELL_WIDTH * COL + 2,
                        CELL_WIDTH * ROW + 2);
      graphics.setColor(Tetris.COLOR_BLACK);
      graphics.fillRect(BASE_X, BASE_Y, CELL_WIDTH * COL + 1, CELL_WIDTH * ROW + 1);
      Vector vec = new Vector();
      doNewLine(graphics, vec); // 方块落下消行处理
      if (!vec.isEmpty()) {
        boolean erase = true;
        for (int i = 0; i < 6; i++) {
          flashLine(vec, graphics, erase);
          drawFixCell(graphics);
          drawNextShape(graphics);
          drawInfo(graphics);
          flushGraphics();
          erase = !erase;
        }
        endFlashLine(vec);
      }
      drawFixCell(graphics); // 绘制固定的方块
      tetrisCurrent.draw(graphics); // 移动中的方块的绘制
      drawNextShape(graphics);// 下一个方块的绘制
      drawInfo(graphics);
      flushGraphics(); // 在屏幕上绘制所有图像元素
      if (!vec.isEmpty()) {
        try {
          Thread.sleep(60);
        }
        catch (Exception exp) {}
      }
  }

  /**
   * 得分绘制
   * @param graphics
   */
  public void renderPoint (Graphics graphics) {
    graphics.setColor(Tetris.COLOR_BLUE);
    graphics.fillRect(0, 0, getWidth(), getHeight());
    drawInfo(graphics);
    flushGraphics();
  }

  private void speedUp() {
    if ( speed <= 35) return;

    speed -= 35;

    if (state == ST_PLAY) {
      pauseGame();
      resumeGame();
    }
  }

  private void speedDown() {
    if ( speed >= 350) return;

    speed += 35;

    if (state == ST_PLAY) {
      pauseGame();
      resumeGame();
    }
  }

  /**
   * 根据得分自动增加难度
   */
  private void autoAddLevel() {
    if ((point - oldPoint) >= 1000) {
      if (speed > 35)  {
        speed -= 35;
        oldPoint = point;
      }
    }
  }

  public void setLevel(int tempSpeed) {
    if (tempSpeed >= 35 && tempSpeed <= 350) speed = tempSpeed;
  }

  public int getLevel() {
    return speed;
  }

  /**
   * 边界检测
   * @return
   */
  private boolean downShapeValid() {
    for (int row = 2; row >= 0; row --)
      for (int col = 0; col < 3; col ++) {
        if ((tetrisCurrent.getShapeData(row, col) == true)// 方块数据中有格子
            && ((tetrisCurrent.by + row + 1) <= (ROW - 1))// 下一行不为底端
            && (fixCellData[tetrisCurrent.by + row + 1][tetrisCurrent.bx + col] == true))//下一行该列中已有填充的格子
              return false;// 下一格子已填充
      }
    return true;// 下一格子未填充
  }

   private Tetris tetrisTemp = new Tetris();
  /**
   * 形状改变
   * @param changeMode
   * @return
   */
  private boolean changeShape(int changeMode) {
//    Tetris tetrisTemp = new Tetris(tetrisCurrent);
    tetrisTemp.setShape(tetrisCurrent);
    switch (changeMode) {
      case DOWN:
        tetrisTemp.moveDown();
        if (shapeValid(tetrisTemp)) {
          tetrisCurrent.moveDown();
          return true;
        }
        break;
      case LEFT:
        tetrisTemp.moveLeft();
        if (shapeValid(tetrisTemp)) {
          tetrisCurrent.moveLeft();
          return true;
        }
        break;
      case RIGHT:
        tetrisTemp.moveRight();
        if (shapeValid(tetrisTemp)) {
          tetrisCurrent.moveRight();
          return true;
        }
        break;
      case ROTATE:
        tetrisTemp.rotate();
        if (shapeValid(tetrisTemp)) {
          tetrisCurrent.rotate();
          return true;
        }
        break;
    }
    return false;
  }

  /**
   * 方块边界检测
   * @param tetrisTemp
   * @return: false表示未通过动作不能继续,true表示通过动作可以继续
   */
  private boolean shapeValid(Tetris tetrisTemp) {
    int row;
    int col;
    for (row = 2; row >= 0; row --)
      for (col = 2; col >= 0; col --) {
        if (tetrisTemp.getShapeData(row, col) == true) {
          if ( (tetrisTemp.bx + col) < 0 ||
              (tetrisTemp.bx + col) >= COL ||
              (tetrisTemp.by + row) >= ROW )
            return false;
          if (fixCellData[tetrisTemp.by + row][tetrisTemp.bx + col] == true) // 格子是否被填充
            return false;
        }
      }
    // 一条形状方块特殊处理
    if (tetrisTemp.shape == 0) {
      if (tetrisTemp.direction == 1 || tetrisTemp.direction == 3) {
        col = 1;
        row = 3;
      } else {
        col = 3;
        row = 1;
      }
      if ( (tetrisTemp.bx + col) < 0 ||
            (tetrisTemp.bx + col) >= COL ||
            (tetrisTemp.by + row) >= ROW )
          return false;
        if (fixCellData[tetrisTemp.by + row][tetrisTemp.bx + col] == true) // 格子是否被填充
          return false;
    }
    return true;
  }

  /**
   * 下一个方块形状的绘制
   * @param graphics
   */
  private void drawNextShape(Graphics graphics) {
    graphics.setColor(Tetris.COLOR_BLACK);
    graphics.drawString("Next:", BASE_X + CELL_WIDTH * (COL + 2),
                        BASE_Y + CELL_WIDTH, Graphics.TOP | Graphics.LEFT);
    tetrisNext.draw(graphics, BASE_X + CELL_WIDTH * (COL + 2),
                    BASE_Y + 5 * CELL_WIDTH);
  }

  /**
   * 绘制玩家当前得分等信息
   * @param graphics
   */
  private void drawInfo (Graphics graphics) {
    switch (state) {
      case ST_PLAY: {
        drawPoint (graphics, BASE_X, BASE_Y);
        drawLevel (graphics, BASE_X - 2 * CELL_WIDTH, BASE_Y);
        break;
      }
      case ST_POINT: {
        drawPoint (graphics, 0, BASE_Y);
        drawLevel (graphics, CELL_WIDTH * (COL + 8), BASE_Y);
        break;
      }
    }
  }

  /**
   * 绘制得分
   * @param graphics
   * @param x
   * @param y
   */
  private void drawPoint (Graphics graphics, int x, int y) {
    graphics.setColor(Tetris.COLOR_BLACK);
    graphics.drawString("Point:", x + CELL_WIDTH * (COL + 2),
                        y + 10 * CELL_WIDTH, Graphics.TOP | Graphics.LEFT);
    graphics.setColor(Tetris.COLOR_CORAL);
    graphics.drawString(String.valueOf(point), x + CELL_WIDTH * (COL + 2),
                        y + 16 * CELL_WIDTH, Graphics.TOP | Graphics.LEFT);
  }

  /**
   * 绘制难度
   * @param graphics
   * @param x
   * @param y
   */
  private void drawLevel (Graphics graphics, int x, int y) {
    graphics.setColor(Tetris.COLOR_BLACK);
    graphics.drawString("Level:", x - CELL_WIDTH * 6,
                        y + CELL_WIDTH, Graphics.TOP | Graphics.LEFT);
    graphics.setColor(Tetris.COLOR_CORAL);
    graphics.drawString(String.valueOf(11 - speed / 35), x - CELL_WIDTH * 6,
                        y + 6 * CELL_WIDTH, Graphics.TOP | Graphics.LEFT);
  }

  private void drawFixCell(Graphics graphics) {
    for (int row = 0; row < ROW; row ++)
      drawFixLine(graphics, row, false, true);
  }

  private void drawFixLine(Graphics graphics, int row, boolean erase, boolean fix) {
      for (int col = 0;  col < COL; col ++) {
        if (fixCellData[row][col] == true)
          Tetris.drawCell(graphics,
                      fixCellColor[row][col],
                      BASE_X + col * CELL_WIDTH,
                      BASE_Y + row * CELL_WIDTH,
                      erase,
                      fix);
      }
  }

  /**
   * 新增加的行的处理
   * 判断是否消行
   * @param graphics
   */
  private void doNewLine(Graphics graphics, Vector vec) {
    if (newLineBotton > (ROW - 1)) {
      newLineBotton = ROW - 1;
    }

    for (int i = newLineTop; i <= newLineBotton; i ++) {
      boolean clear = true;
      for (int col = 0; col < COL; col ++) {
        if (fixCellData[i][col] == false) {
          clear = false;
          break;
        }
      }
      if (clear) vec.addElement(new Integer(i));
    }
  }

  private void endFlashLine(Vector vec) {
    Enumeration e = vec.elements();
    while (e.hasMoreElements()) {
      int flashRow = Integer.parseInt(e.nextElement().toString());
      for (int row = flashRow; row > 0; row--)
        for (int col = 0; col < COL; col++) {
          fixCellData[row][col] = fixCellData[row - 1][col];
          fixCellColor[row][col] = fixCellColor[row - 1][col];
        }
    }

    switch (vec.size()) {
      case 1:
        point += 100;
        break;
      case 2:
        point += 300;
        break;
      case 3:
        point += 600;
        break;
      case 4:
        point += 1000;
        break;
    }
  }

  /**
   * 消行
   * @param vec
   * @param graphics
   */
  private void flashLine(Vector vec, Graphics graphics, boolean erase) {
    int row = 0;
      Enumeration e = vec.elements();
      while (e.hasMoreElements()) {
        row = Integer.parseInt(e.nextElement().toString());
        drawFixLine(graphics, row, erase, true);
      }

      try {
        Thread.sleep(30);
      } catch (Exception exp) {}
/*
      e = vec.elements();
      while (e.hasMoreElements()) {
       row = Integer.parseInt(e.nextElement().toString());
       drawFixLine(graphics, row, false, true);
     }*/
  }
}

本文地址:http://com.8s8s.com/it/it15458.htm