2016-11-06 1 views
-1

私は大学のプロジェクトとしてゲームを書いています。それはJCanvasを使ってゲームを表示していますが、その部分は完全に機能していますが、「再生」「終了」「終了」などの項目から選択できるメニューを追加したいと思います。JPanelからCanvasでゲームを始めるには?

私はJFrameをJCanvasとJPanel(後者はメニューです)。しかし、私がパネルからゲームを開始すると、フレームがフリーズします。
いくつかのテストを実行しましたが、問題は、JPanelsのactionListenerからplayGame()メソッドが呼び出されたときに、キャンバスはそのメソッドが返されるまで更新できないということです。 https://github.com/nodar86/prog3-snake

答えて

2

どちらも再描画とイベントディスパッチは(The Event Dispatch Thread上で実行されます。それはより多くの場合に役立ちます

public class Main { 

public static Game game = new Game(); 
private static JFrame mainFrame = new JFrame("Snake"); 
private static MenuPanel menuPanel = new MenuPanel(); 

public static void main(String[] args) { 
    mainFrame.setLayout(new BorderLayout()); 

    mainFrame.add(menuPanel, BorderLayout.SOUTH); 
    mainFrame.pack(); 
    mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    mainFrame.setVisible(true); 

} 

static void playGame(){ 
    mainFrame.setVisible(false); 
    mainFrame.remove(menuPanel); 
    menuPanel.setEnabled(false); 

    ScoreboardPanel scoreboardPanel = new ScoreboardPanel(); 
    mainFrame.add(scoreboardPanel, BorderLayout.NORTH); 

    game.addPanel(scoreboardPanel); 
    mainFrame.add(game, BorderLayout.CENTER); 
    mainFrame.pack(); 
    mainFrame.setVisible(true); 

    // ANYTHING here stops the frame's rendering until playGame() returns (like game.play() or sleep(x) 
} 

}

public class MenuPanel extends JPanel { 

private class MenuActionListener implements ActionListener { 
    public void actionPerformed(ActionEvent actionEvent){ 
     switch (actionEvent.getActionCommand()){ 
      case "play": 
       // TODO This somehow breaks everything. The game loop runs but the window freezes. 
       Main.playGame(); 
       break; 
      case "highscore": 
       break; 
      case "leveleditor": 
       break; 
      case "exit": 
       System.exit(0); 
       break; 
     } 
    } 
} 

そして、ここでは完全なコードです:ここで

は、関連する部分ですEDT)。 Game.playメソッドがイベントリスナーから呼び出され、 sleepを使用してEDTをブロックするため、Swingはフレームを再描画する機会がありません。

これを直す最も簡単な方法は、Game.playのハンドメイドタイマーをjavax.swing.Timerに置き換えます。タイマーの各ティックでは、ゲームのチックでエミュレートする必要があります。これにより、必要に応じてSwingを再描画することができます。あらかじめタイマーを準備しておけば、メニューリスナーはそれを開始して止めることができます。

サイドノート:おそらく、あなたのメニューにはspecial menu componentsを使用する価値があります。

+0

ありがとうございました。また、EDTに関する情報をリンクして説明してくれてありがとう。これはすべてのものがスイングするのに役立ちます! –

2

「JCanvas」は使用していません。「キャンバス」を使用している場合を除き、「JCanvas」はありません(in here your Game class extends Canvas.)軽量で重量のあるツールキットを混在させないようにゲームを更新することをおすすめします。同じGUI。しかし、あなたがほとんど完了したように見えるので、kgeorgiyの答えを試してみてください。

関連する問題