【发布时间】:2022-01-13 18:53:28
【问题描述】:
我的游戏重新启动按钮不起作用,并且在单击时会倍增。我不完全理解 Java 我认为自己很好。
游戏主线
package snake_game;
public class snake {
public static void main(String arg[]) {
new GameFrame();
// is exacly the same as frame f = new frame();
// this is shorter and does the same job
}
}
GamePanel
package snake_game;
// import java.awt.event.ActionEvent;
// import java.awt.event.ActionListener;
// import java.awt.Graphics;
// import java.awt.event.KeyAdapter;
// import java.awt.event.KeyEvent;
// or I could write simply
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements ActionListener {
// panal dimentions
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
// panal dimentions
// size
static final int UNIT_SIZE = 25;
// size to make 600 * 600 = 1200 px equel between 25 px
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
// size
// delay how fast the game will be
static final int DELAY = 75;
// delay
// dimentions
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
// dimentions
// snake
int bodyParts = 6;
// snake
// apple
int appleEaten;
int appleX;
int appleY;
// apple
char direction = 'R';
boolean running = false;
Timer timer;
Random random;
GamePanel game;
JButton resetButton;
GamePanel() {
random = new Random();
this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
// when we want to make the program to continie we must say what the programm
// must execute next
}
public void startGame() {
newApple();
running = true;
timer = new Timer(DELAY, this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
for (int i = 0; i < SCREEN_HEIGHT / UNIT_SIZE; i++) {
g.drawLine(i * UNIT_SIZE, 0, i * UNIT_SIZE, SCREEN_HEIGHT);
g.drawLine(0, i * UNIT_SIZE, i * SCREEN_WIDTH, i * UNIT_SIZE);
}
g.setColor(Color.red);
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
for (int i = 0; i < bodyParts; i++) {
if (i == 0) {
g.setColor(Color.green);
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
} else {
g.setColor(new Color(45, 180, 0));
// random color
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// random color
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
}
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 30));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("SCORE:" + appleEaten, (SCREEN_WIDTH - metrics.stringWidth("SCORE:" + appleEaten)) / 2,
g.getFont().getSize());
} else {
gameOver(g);
}
}
public void newApple() {
appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
}
public void move() {
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}
switch (direction) {
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
}
public void checkApple() {
if ((x[0] == appleX) && (y[0] == appleY)) {
bodyParts++;
appleEaten++;
newApple();
}
}
public void checkCollisions() {
// check if head collides with body
for (int i = bodyParts; i > 0; i--) {
if ((x[0] == x[i]) && (y[0] == y[i])) {
running = false;
}
}
// check if head touches left border
if (x[0] < 0) {
running = false;
}
// check if head touches right border
if (x[0] > SCREEN_WIDTH) {
running = false;
}
// check if head touches top border
if (y[0] < 0) {
running = false;
}
// check if head touches bottom border
if (y[0] > SCREEN_HEIGHT) {
running = false;
}
if (!running) {
timer.stop();
}
}
public void gameOver(Graphics g) {
// score
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 30));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("SCORE:" + appleEaten, (SCREEN_WIDTH - metrics1.stringWidth("SCORE:" + appleEaten)) / 2,
g.getFont().getSize());
// game over text
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over")) / 2, SCREEN_HEIGHT / 2);
// restart button
resetButton = new JButton();
resetButton.setText("Restart");
resetButton.setSize(100, 50);
resetButton.setLocation(150, 150);
resetButton.addActionListener(this);
game = new GamePanel();
this.add(resetButton);
this.add(game);
this.setVisible(true);
// restart button
}
@Override
public void actionPerformed(ActionEvent e) {
if (running) {
move();
checkApple();
checkCollisions();
}
repaint();
// restart button
if (e.getSource() == resetButton) {
this.remove(game);
game = new GamePanel();
this.add(game);
resetButton.setVisible(false);
SwingUtilities.updateComponentTreeUI(this);
// restart button
}
}
public class MyKeyAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_RIGHT:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_UP:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_DOWN:
if (direction != 'U') {
direction = 'D';
}
break;
}
}
}
}
GameFrame
package snake_game;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
GameFrame() {
GamePanel panel = new GamePanel();
this.add(panel);
this.setTitle("Snake");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setUndecorated(false);
}
}
【问题讨论】:
-
this.remove(game); game = new GamePanel(); this.add(game)不!这将导致没有特殊处理的问题。最好创建一个SnakeGameModel,它可以传递给面板以设置它并显示当前视图。然后当用户重置时,将游戏模型设置回默认值(或创建一个新模型)并将其传递给单个GamePanel。
标签: java swing jbutton restart