Tetris/Java: Difference between revisions

Content added Content deleted
(→‎{{headerJava}}: added Java)
 
(→‎{{header|Java}}: cleaned up code a bit)
Line 10: Line 10:
public static final int EMPTY = -1;
public static final int EMPTY = -1;
public static final int BORDER = -2;
public static final int BORDER = -2;

final Color[] colors = {Color.green, Color.red, Color.blue, Color.pink,
Color.orange, Color.cyan, Color.magenta};

// for centering the shapes in the preview window
final int[][] previewOffets = {{16, 15}, {-15, 15}, {0, 0}, {0, 0},
{-15, 5}, {16, 15}, {-15, 15}};


int[][] grid;
int[][] grid;


Shape selectedShape;
Shape fallingShape;
Shape preSelectedShape;
Shape preSelectedShape;


int blockSize = 30;
// position of falling shape
int nRows = 18;
int fallingShapeRow;
int nCols = 12;
int fallingShapeCol;

int shapeRow;
int shapeCol;
int blockSize = Config.blockSize;
int topMargin = 50;
int nRows = Config.nRows;
int leftMargin = 20;
int nCols = Config.nCols;
int topMargin = Config.topMargin;
int leftMargin = Config.leftMargin;


Thread fallingThread;
Thread fallingThread;
Scoreboard scoreboard;
Scoreboard scoreboard;

Font smallFont;
Rectangle gridRect, previewRect;


public Tetris() {
public Tetris() {
setPreferredSize(new Dimension(640, 640));
setPreferredSize(Config.dim);
setBackground(new Color(0xDDEEFF));
setBackground(Config.bgColor);
setFont(new Font("Monospaced", Font.BOLD, 48));
setFocusable(true);
setFocusable(true);

smallFont = getFont().deriveFont(Font.BOLD, 18);

gridRect = new Rectangle(46, 47, 308, 517);
previewRect = new Rectangle(387, 47, 200, 200);


scoreboard = new Scoreboard();
scoreboard = new Scoreboard();
Line 75: Line 61:


case KeyEvent.VK_UP:
case KeyEvent.VK_UP:
if (canRotate(selectedShape))
if (canRotate(fallingShape))
rotate(selectedShape);
rotate(fallingShape);
break;
break;


case KeyEvent.VK_LEFT:
case KeyEvent.VK_LEFT:
if (canMove(selectedShape, -1, 0))
if (canMove(fallingShape, -1, 0))
move(selectedShape, -1, 0);
move(fallingShape, -1, 0);
break;
break;


case KeyEvent.VK_RIGHT:
case KeyEvent.VK_RIGHT:
if (canMove(selectedShape, 1, 0))
if (canMove(fallingShape, 1, 0))
move(selectedShape, 1, 0);
move(fallingShape, 1, 0);
break;
break;


Line 92: Line 78:
if (!fastDown) {
if (!fastDown) {
fastDown = true;
fastDown = true;
while (canMove(selectedShape, 0, 1)) {
while (canMove(fallingShape, 0, 1)) {
move(selectedShape, 0, 1);
move(fallingShape, 0, 1);
repaint();
repaint();
}
}
Line 110: Line 96:


void selectShape() {
void selectShape() {
shapeRow = 1;
fallingShapeRow = 1;
shapeCol = 5;
fallingShapeCol = 5;
selectedShape = preSelectedShape;
fallingShape = preSelectedShape;
preSelectedShape = Shape.values()[(int) (Math.random() * colors.length)];
Shape[] shapes = Shape.values();
preSelectedShape = shapes[(int) (Math.random() * shapes.length)];
if (selectedShape != null)
selectedShape.reset();
if (fallingShape != null)
fallingShape.reset();
}
}


Line 155: Line 142:


if (!scoreboard.isGameOver()) {
if (!scoreboard.isGameOver()) {
if (canMove(selectedShape, 0, 1)) {
if (canMove(fallingShape, 0, 1)) {
move(selectedShape, 0, 1);
move(fallingShape, 0, 1);
} else {
} else {
shapeHasLanded();
shapeHasLanded();
Line 166: Line 153:


void drawStartScreen(Graphics2D g) {
void drawStartScreen(Graphics2D g) {
g.setFont(getFont());
g.setFont(Config.mainFont);


g.setColor(new Color(0xFFFFFF));
g.setColor(Config.titlebgColor);
g.fillRect(leftMargin + 80, topMargin + 35, 252, 100);
g.fill(Config.titleRect);
g.fillRect(leftMargin + 30, topMargin + 325, 252, 40);
g.fill(Config.clickRect);


g.setColor(Color.black);
g.setColor(Config.textColor);
g.drawString("Tetris", leftMargin + 110, topMargin + 100);
g.drawString("Tetris", Config.titleX, Config.titleY);


g.setFont(smallFont);
g.setFont(Config.smallFont);
g.drawString("click to start", leftMargin + 100, topMargin + 350);
g.drawString("click to start", Config.clickX, Config.clickY);
}
}


void drawSquare(Graphics2D g, Color color, int r, int c) {
void drawSquare(Graphics2D g, int colorIndex, int r, int c) {
g.setStroke(new BasicStroke(2));
g.setColor(Config.colors[colorIndex]);

g.setColor(color);
g.fillRect(leftMargin + c * blockSize, topMargin + r * blockSize,
g.fillRect(leftMargin + c * blockSize, topMargin + r * blockSize,
blockSize, blockSize);
blockSize, blockSize);


g.setColor(Color.white);
g.setStroke(Config.smallStroke);
g.setColor(Config.squareBorder);
g.drawRect(leftMargin + c * blockSize, topMargin + r * blockSize,
g.drawRect(leftMargin + c * blockSize, topMargin + r * blockSize,
blockSize, blockSize);
blockSize, blockSize);
Line 192: Line 178:


void drawUI(Graphics2D g) {
void drawUI(Graphics2D g) {
g.setStroke(new BasicStroke(5));
// grid background
g.setColor(new Color(0xBECFEA));
g.setColor(Config.gridColor);
g.fill(gridRect);
g.fill(Config.gridRect);

g.setColor(new Color(0x7788AA));
g.draw(gridRect);
g.draw(previewRect);


// the blocks dropped in the grid
for (int r = 0; r < nRows; r++) {
for (int r = 0; r < nRows; r++) {
for (int c = 0; c < nCols; c++) {
for (int c = 0; c < nCols; c++) {
int id = grid[r][c];
int idx = grid[r][c];
if (id > EMPTY)
if (idx > EMPTY)
drawSquare(g, colors[id], r, c);
drawSquare(g, idx, r, c);
}
}
}
}


// the borders of grid and preview panel
g.setColor(Color.black);
g.setFont(smallFont);
g.setStroke(Config.largeStroke);
g.setColor(Config.gridBorderColor);
g.drawString(format("hiscore %6d", scoreboard.getTopscore()),400, 330);
g.draw(Config.gridRect);
g.drawString(format("level %6d", scoreboard.getLevel()), 400, 360);
g.draw(Config.previewRect);
g.drawString(format("lines %6d", scoreboard.getLines()), 400, 390);
g.drawString(format("score %6d", scoreboard.getScore()), 400, 420);
}


// scoreboard
void drawPreview(Graphics2D g) {
int ord = preSelectedShape.ordinal();
int x = Config.scoreX;
int y = Config.scoreY;
g.translate(previewOffets[ord][0], previewOffets[ord][1]);
g.setColor(Config.textColor);
for (int[] p : preSelectedShape.shapes[ord]) {
g.setFont(Config.smallFont);
drawSquare(g, colors[ord], 2 + p[1], 15 + p[0]);
g.drawString(format("hiscore %6d", scoreboard.getTopscore()), x, y);
}
g.drawString(format("level %6d", scoreboard.getLevel()), x, y + 30);
g.translate(-previewOffets[ord][0], -previewOffets[ord][1]);
g.drawString(format("lines %6d", scoreboard.getLines()), x, y + 60);
g.drawString(format("score %6d", scoreboard.getScore()), x, y + 90);

// preview
int idx = preSelectedShape.ordinal();
int offsetX = Config.previewOffets[idx][0] + 15 * blockSize;
int offsetY = Config.previewOffets[idx][1] + 2 * blockSize;

g.translate(offsetX, offsetY);

for (int[] p : preSelectedShape.shapes[idx])
drawSquare(g, idx, p[1], p[0]);

g.translate(-offsetX, -offsetY);
}
}


void drawFallingShape(Graphics2D g) {
void drawFallingShape(Graphics2D g) {
Color c = colors[selectedShape.ordinal()];
int idx = fallingShape.ordinal();
for (int[] p : selectedShape.pos)
for (int[] p : fallingShape.pos)
drawSquare(g, c, shapeRow + p[1], shapeCol + p[0]);
drawSquare(g, idx, fallingShapeRow + p[1], fallingShapeCol + p[0]);
}
}


Line 245: Line 240:
drawFallingShape(g);
drawFallingShape(g);
}
}

drawPreview(g);
}
}


Line 265: Line 258:


for (int[] p : pos) {
for (int[] p : pos) {
int newCol = shapeCol + p[0];
int newCol = fallingShapeCol + p[0];
int newRow = shapeRow + p[1];
int newRow = fallingShapeRow + p[1];
if (grid[newRow][newCol] != EMPTY) {
if (grid[newRow][newCol] != EMPTY) {
return false;
return false;
Line 286: Line 279:


void move(Shape s, int xIncr, int yIncr) {
void move(Shape s, int xIncr, int yIncr) {
shapeRow += yIncr;
fallingShapeRow += yIncr;
shapeCol += xIncr;
fallingShapeCol += xIncr;
}
}


boolean canMove(Shape s, int xIncr, int yIncr) {
boolean canMove(Shape s, int xIncr, int yIncr) {
for (int[] p : s.pos) {
for (int[] p : s.pos) {
int newCol = shapeCol + xIncr + p[0];
int newCol = fallingShapeCol + xIncr + p[0];
int newRow = shapeRow + yIncr + p[1];
int newRow = fallingShapeRow + yIncr + p[1];
if (grid[newRow][newCol] != EMPTY)
if (grid[newRow][newCol] != EMPTY)
return false;
return false;
Line 301: Line 294:


void shapeHasLanded() {
void shapeHasLanded() {
addShape(selectedShape);
addShape(fallingShape);
if (shapeRow < 2) {
if (fallingShapeRow < 2) {
scoreboard.setGameOver();
scoreboard.setGameOver();
scoreboard.setTopscore();
scoreboard.setTopscore();
Line 339: Line 332:
void addShape(Shape s) {
void addShape(Shape s) {
for (int[] p : s.pos)
for (int[] p : s.pos)
grid[shapeRow + p[1]][shapeCol + p[0]] = s.ordinal();
grid[fallingShapeRow + p[1]][fallingShapeCol + p[0]] = s.ordinal();
}
}


Line 487: Line 480:
{{-1, -1}, {0, -1}, {0, 0}, {0, 1}},
{{-1, -1}, {0, -1}, {0, 0}, {0, 1}},
{{1, -1}, {0, -1}, {0, 0}, {0, 1}}};
{{1, -1}, {0, -1}, {0, 0}, {0, 1}}};
}

final class Config {
final static Color[] colors = {Color.green, Color.red, Color.blue,
Color.pink, Color.orange, Color.cyan, Color.magenta};

// used for centering shapes in the preview pane
final static int[][] previewOffets = {{16, 15}, {-15, 15}, {0, 0},
{0, 0}, {-15, 5}, {16, 15}, {-15, 15}};

final static Font mainFont = new Font("Monospaced", Font.BOLD, 48);
final static Font smallFont = mainFont.deriveFont(Font.BOLD, 18);

final static Dimension dim = new Dimension(640, 640);

final static int blockSize = 30;
final static int nRows = 18;
final static int nCols = 12;
final static int topMargin = 50;
final static int leftMargin = 20;
final static int scoreX = 400;
final static int scoreY = 330;
final static int titleX = 130;
final static int titleY = 150;
final static int clickX = 120;
final static int clickY = 400;

final static Rectangle gridRect = new Rectangle(46, 47, 308, 517);
final static Rectangle previewRect = new Rectangle(387, 47, 200, 200);
final static Rectangle titleRect = new Rectangle(100, 85, 252, 100);
final static Rectangle clickRect = new Rectangle(50, 375, 252, 40);

final static Stroke largeStroke = new BasicStroke(5);
final static Stroke smallStroke = new BasicStroke(2);

final static Color squareBorder = Color.white;
final static Color titlebgColor = Color.white;
final static Color textColor = Color.black;
final static Color bgColor = new Color(0xDDEEFF);
final static Color gridColor = new Color(0xBECFEA);
final static Color gridBorderColor = new Color(0x7788AA);
}</lang>
}</lang>