From 4ef4783035e83d59b6c6b1e9c987c4f111e43ace Mon Sep 17 00:00:00 2001 From: pgb58ns4h <1639613619@qq.com> Date: Sat, 19 Apr 2025 23:44:02 +0800 Subject: [PATCH] ADD file via upload --- scr%2Ftetris/GamePanel.java | 284 ++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 scr%2Ftetris/GamePanel.java diff --git a/scr%2Ftetris/GamePanel.java b/scr%2Ftetris/GamePanel.java new file mode 100644 index 0000000..3fad250 --- /dev/null +++ b/scr%2Ftetris/GamePanel.java @@ -0,0 +1,284 @@ +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; +} \ No newline at end of file