【发布时间】:2017-04-23 11:28:00
【问题描述】:
我正在为我的学习制作游戏“Breakout”的重新制作版本,但遇到了一个奇怪的问题:
我有一个简单的开始屏幕,玩家应该能够在其中输入名称并查看当前的高分等。要开始游戏,我使用 CardLayout 应该切换到gamePanel。不知何故,这不会发生,但游戏循环开始了,当球离开 JPanel 时,我收到 game Over 消息。奇怪的是,gamePanel 与 Over JOptionPane 游戏一起出现,并且切换回开始屏幕正常工作。我也在 StackOverflow 上进行了很多搜索,但我找到的解决方案都没有为我工作。这是我的代码:
这是我的Game.java,main Method所在的地方:
public class Game extends JFrame {
private static final int width = 1280;
private static final int height = 720;
private static final String LOBBY_PANEL = "Lobby Panel";
private static final String GAME_PANEL = "Game Panel";
private boolean run = false;
private CardLayout cardLayout;
private JPanel cardPanel = new JPanel();
private LobbyPanel lobbyPanel;
private GamePanel gamePanel;
public Game(){
super("Breakout Remastered");
cardPanel.setLayout(new CardLayout());
cardLayout = (CardLayout) cardPanel.getLayout();
lobbyPanel = new LobbyPanel(this);
gamePanel = new GamePanel(this);
cardPanel.add(lobbyPanel, LOBBY_PANEL);
cardPanel.add(gamePanel, GAME_PANEL);
this.add(cardPanel);
this.pack();
this.setSize(width, height);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
cardLayout.show(cardPanel, LOBBY_PANEL);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Game gameFrame = new Game();
gameFrame.setVisible(true);
});
}
public void playGame() {
cardLayout.show(cardPanel, GAME_PANEL);
this.validate();
this.repaint();
this.run = true;
while (run) {
gamePanel.move();
gamePanel.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException iEx) {
iEx.printStackTrace();
}
}
}
public void stopGame() {
cardLayout.show(cardPanel, LOBBY_PANEL);
this.run = false;
}
}
这是我的 GamePanel.java:
public class GamePanel extends JPanel {
private Game game;
private Ball ball = new Ball(this);
private Racquet racquet = new Racquet(this);
public GamePanel(Game game) {
this.game = game;
KeyListener keyListener = new KeyListener() {
@Override
public void keyTyped(KeyEvent keyEvent) {
}
@Override
public void keyPressed(KeyEvent keyEvent) {
racquet.keyPressed(keyEvent);
}
@Override
public void keyReleased(KeyEvent keyEvent) {
racquet.keyReleased(keyEvent);
}
};
addKeyListener(keyListener);
setFocusable(true);
}
public void move() {
ball.move();
racquet.move();
}
public void reset() {
}
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
Graphics2D g2d = (Graphics2D) graphics;
g2d.setColor(Color.BLACK);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ball.paint(g2d);
racquet.paint(g2d);
}
public void gameOver() {
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
game.stopGame();
}
public Racquet getRacquet() {
return racquet;
}
public void setRacquet(Racquet racquet) {
this.racquet = racquet;
}
}
这是我的 LobbyPanel.java:
public class LobbyPanel extends JPanel implements ActionListener {
private static final JLabel labelForUserTextField = new JLabel("Username");
private JTextField userName = new JTextField("", 20);
private JButton startButton = new JButton("Play!");
private JButton highScoreButton = new JButton("View Best");
private JButton cancelButton = new JButton("Cancel");
private Game game;
public LobbyPanel(Game game) {
startButton.addActionListener(this);
this.game = game;
this.setLayout(new GridBagLayout());
this.setBorder(new EmptyBorder(10, 10, 10, 10));
GridBagConstraints labelConst = new GridBagConstraints();
labelConst.insets = new Insets(3, 3, 3, 3);
labelConst.gridx = 0;
labelConst.gridy = 0;
this.add(labelForUserTextField, labelConst);
labelConst.gridx = 1;
this.add(userName, labelConst);
labelConst.gridx = 0;
labelConst.gridy = 1;
this.add(cancelButton, labelConst);
labelConst.gridx = 1;
this.add(highScoreButton, labelConst);
labelConst.gridx = 2;
this.add(startButton, labelConst);
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
if(actionEvent.getSource() == this.startButton) {
this.game.playGame();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
我希望有人能弄清楚为什么这段代码不能按预期工作。 提前谢谢!
【问题讨论】:
-
public class GamePanel extends JPanel { .. public void paint(Graphics graphics) {对于任何JComponent(其中JPanel是其中之一),该方法应该是paintComponent(Graphics)。 -
欢迎来到 Stack Overflow!我想 95% 的代码与你的问题无关。请创建一个 Minimal, Complete and Verifiable Example 来证明您的问题。
-
除了@AndrewThompson 所说的,你不应该使用
while (true)循环,而是使用Swing Timer 并且永远不要在Swing 应用程序中使用Thread.sleep(...),否则它会阻塞EDT -
“好吧,我可以移除 Racquet 和 Ball 类......” 所以你知道,或者至少强烈怀疑,某些部分是不相关的。删除它们并测试该理论! “我不知道问题在我的代码中的确切位置” 按照@JoeC 的建议创建minimal reproducible example 的部分好处是您会发现!如果您懒得花精力去找出答案,为什么要找其他人?
-
@Frakcool “你不应该使用
while (true)循环” 很好发现!诚然,我只关注代码,直到有一个 MCVE,在我的 IDE 中编译,按照我的口味格式化。
标签: java swing cardlayout