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); }*/ } } 
|