ADD file via upload

main
pgb58ns4h 1 month ago
parent 4dce6b1fe0
commit 4ef4783035

@ -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;
}
Loading…
Cancel
Save