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