parent
78769b8a47
commit
df1452766e
@ -1,284 +0,0 @@
|
|||||||
package tetris;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class GamePanel extends JPanel {
|
|
||||||
private static final int BLOCK_SIZE = 30;
|
|
||||||
private static final int ROWS = 20, COLS = 10;
|
|
||||||
private final int[][] board = new int[ROWS][COLS];
|
|
||||||
private Block currentBlock, nextBlock;
|
|
||||||
private Timer timer;
|
|
||||||
private int fallSpeed = 500, score = 0;
|
|
||||||
private final NextBlockPanel nextBlockPanel;
|
|
||||||
private final ResourceManager resManager = ResourceManager.getInstance();
|
|
||||||
|
|
||||||
public GamePanel(NextBlockPanel nextBlockPanel) {
|
|
||||||
this.nextBlockPanel = nextBlockPanel;
|
|
||||||
setPreferredSize(new Dimension(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE));
|
|
||||||
setBackground(Color.BLACK);
|
|
||||||
initControls();
|
|
||||||
initTimer();
|
|
||||||
newGame();
|
|
||||||
|
|
||||||
addComponentListener(new ComponentAdapter() {
|
|
||||||
@Override
|
|
||||||
public void componentShown(ComponentEvent e) {
|
|
||||||
requestFocusInWindow();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initControls() {
|
|
||||||
addKeyListener(new KeyAdapter() {
|
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyEvent e) {
|
|
||||||
switch (e.getKeyCode()) {
|
|
||||||
case KeyEvent.VK_SPACE:
|
|
||||||
togglePause();
|
|
||||||
break;
|
|
||||||
case KeyEvent.VK_LEFT:
|
|
||||||
if (!isPaused && !isGameOver) handleMove(-1, 0);
|
|
||||||
break;
|
|
||||||
case KeyEvent.VK_RIGHT:
|
|
||||||
if (!isPaused && !isGameOver) handleMove(1, 0);
|
|
||||||
break;
|
|
||||||
case KeyEvent.VK_DOWN:
|
|
||||||
if (!isPaused && !isGameOver) hardDrop();
|
|
||||||
break;
|
|
||||||
case KeyEvent.VK_UP:
|
|
||||||
if (!isPaused && !isGameOver) rotateBlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleMove(int dx, int dy) {
|
|
||||||
if (canMove(dx, dy)) {
|
|
||||||
if (dx == -1) currentBlock.moveLeft();
|
|
||||||
else if (dx == 1) currentBlock.moveRight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void togglePause() {
|
|
||||||
isPaused = !isPaused;
|
|
||||||
if (timer != null) {
|
|
||||||
if (isPaused) {
|
|
||||||
timer.stop();
|
|
||||||
} else {
|
|
||||||
timer.setDelay(fallSpeed);
|
|
||||||
timer.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Toolkit.getDefaultToolkit().beep();
|
|
||||||
requestFocusInWindow();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canMove(int dx, int dy) {
|
|
||||||
int[][] shape = currentBlock.getShape();
|
|
||||||
for (int i = 0; i < shape.length; i++) {
|
|
||||||
for (int j = 0; j < shape[i].length; j++) {
|
|
||||||
if (shape[i][j] == 1) {
|
|
||||||
int newX = currentBlock.getX() + j + dx;
|
|
||||||
int newY = currentBlock.getY() + i + dy;
|
|
||||||
if (newX < 0 || newX >= COLS || newY >= ROWS || (newY >= 0 && board[newY][newX] != 0))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rotateBlock() {
|
|
||||||
Block temp = new Block(currentBlock.getType());
|
|
||||||
temp.moveTo(currentBlock.getX(), currentBlock.getY());
|
|
||||||
temp.rotate();
|
|
||||||
if (canRotate(temp)) currentBlock.rotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canRotate(Block block) {
|
|
||||||
int[][] shape = block.getShape();
|
|
||||||
for (int i = 0; i < shape.length; i++) {
|
|
||||||
for (int j = 0; j < shape[i].length; j++) {
|
|
||||||
if (shape[i][j] == 1) {
|
|
||||||
int x = block.getX() + j;
|
|
||||||
int y = block.getY() + i;
|
|
||||||
if (x < 0 || x >= COLS || y >= ROWS || (y >= 0 && board[y][x] != 0))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hardDrop() {
|
|
||||||
while (canMove(0, 1)) currentBlock.moveDown();
|
|
||||||
mergeBlock();
|
|
||||||
clearLines();
|
|
||||||
spawnNewBlock();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mergeBlock() {
|
|
||||||
int[][] shape = currentBlock.getShape();
|
|
||||||
for (int i = 0; i < shape.length; i++) {
|
|
||||||
for (int j = 0; j < shape[i].length; j++) {
|
|
||||||
if (shape[i][j] == 1) {
|
|
||||||
int y = currentBlock.getY() + i;
|
|
||||||
int x = currentBlock.getX() + j;
|
|
||||||
if (y < 0) gameOver();
|
|
||||||
else board[y][x] = currentBlock.getType() + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int[] SCORE_TABLE = {100, 300, 500, 800};
|
|
||||||
|
|
||||||
private void clearLines() {
|
|
||||||
int linesCleared = 0;
|
|
||||||
for (int i = ROWS - 1; i >= 0; i--) {
|
|
||||||
if (isLineFull(i)) {
|
|
||||||
if (i > 0) {
|
|
||||||
System.arraycopy(board, 0, board, 1, i);
|
|
||||||
}
|
|
||||||
Arrays.fill(board[0], 0);
|
|
||||||
linesCleared++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (linesCleared > 0) {
|
|
||||||
resManager.playClearSound(); // 添加消除音效
|
|
||||||
score += (linesCleared < 4) ? SCORE_TABLE[linesCleared - 1] : SCORE_TABLE[3];
|
|
||||||
Toolkit.getDefaultToolkit().beep();
|
|
||||||
nextBlockPanel.updateScore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLineFull(int row) {
|
|
||||||
for (int cell : board[row])
|
|
||||||
if (cell == 0) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void spawnNewBlock() {
|
|
||||||
currentBlock = (nextBlock != null) ? nextBlock : new Block(new Random().nextInt(7));
|
|
||||||
nextBlock = new Block(new Random().nextInt(7));
|
|
||||||
nextBlockPanel.setNextBlock(nextBlock);
|
|
||||||
if (!canSpawn()) gameOver();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canSpawn() {
|
|
||||||
if (currentBlock.getY() < 0) return false;
|
|
||||||
|
|
||||||
int[][] shape = currentBlock.getShape();
|
|
||||||
for (int i = 0; i < shape.length; i++) {
|
|
||||||
for (int j = 0; j < shape[i].length; j++) {
|
|
||||||
if (shape[i][j] == 1) {
|
|
||||||
int y = currentBlock.getY() + i;
|
|
||||||
int x = currentBlock.getX() + j;
|
|
||||||
if (x < 0 || x >= COLS || y >= ROWS || y < 0 || board[y][x] != 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newGame() {
|
|
||||||
for (int[] row : board) Arrays.fill(row, 0);
|
|
||||||
score = 0;
|
|
||||||
spawnNewBlock();
|
|
||||||
isGameOver = isPaused = false;
|
|
||||||
if (timer != null) {
|
|
||||||
timer.start();
|
|
||||||
}
|
|
||||||
requestFocusInWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initTimer() {
|
|
||||||
timer = new Timer(fallSpeed, e -> {
|
|
||||||
if (!isPaused && !isGameOver) {
|
|
||||||
if (canMove(0, 1)) {
|
|
||||||
currentBlock.moveDown();
|
|
||||||
} else {
|
|
||||||
mergeBlock();
|
|
||||||
clearLines();
|
|
||||||
spawnNewBlock();
|
|
||||||
}
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFallSpeed(int speed) {
|
|
||||||
fallSpeed = speed;
|
|
||||||
if (timer != null) {
|
|
||||||
timer.setDelay(speed);
|
|
||||||
if (!isPaused) {
|
|
||||||
timer.restart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getScore() {
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gameOver() {
|
|
||||||
isGameOver = true;
|
|
||||||
timer.stop();
|
|
||||||
JOptionPane.showMessageDialog(this, "得分: " + score);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void paintComponent(Graphics g) {
|
|
||||||
super.paintComponent(g);
|
|
||||||
// 绘制游戏背景图
|
|
||||||
Image gameBg = resManager.getGameBackground();
|
|
||||||
if (gameBg != null) {
|
|
||||||
g.drawImage(gameBg, 0, 0, getWidth(), getHeight(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制固定方块
|
|
||||||
for (int i = 0; i < ROWS; i++) {
|
|
||||||
for (int j = 0; j < COLS; j++) {
|
|
||||||
if (board[i][j] != 0) {
|
|
||||||
int type = board[i][j] - 1;
|
|
||||||
Image blockImage = resManager.getBlockImage(type);
|
|
||||||
if (blockImage != null) {
|
|
||||||
g.drawImage(blockImage, j * BLOCK_SIZE, i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制当前方块
|
|
||||||
if (currentBlock != null) {
|
|
||||||
int[][] shape = currentBlock.getShape();
|
|
||||||
for (int i = 0; i < shape.length; i++) {
|
|
||||||
for (int j = 0; j < shape[i].length; j++) {
|
|
||||||
if (shape[i][j] == 1) {
|
|
||||||
int x = (currentBlock.getX() + j) * BLOCK_SIZE;
|
|
||||||
int y = (currentBlock.getY() + i) * BLOCK_SIZE;
|
|
||||||
if (y < getHeight()) {
|
|
||||||
int type = currentBlock.getType();
|
|
||||||
Image blockImage = resManager.getBlockImage(type);
|
|
||||||
if (blockImage != null) {
|
|
||||||
g.drawImage(blockImage, x, y, BLOCK_SIZE, BLOCK_SIZE, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isPaused = false, isGameOver = false;
|
|
||||||
}
|
|
Loading…
Reference in new issue