1

私はJavaスイングを使用してゲームボード用の2つのボタンリスナーを持っています。

最初にテトリス グリッドが作成され、次に各ボタン リスナー内に機能が追加されます。

Play.java で次のようにボードを設定します。

final TetrisGame g = new TetrisGame(11,1);
final BoardGraphics graphics = new BoardGraphics(TetrisBoard.BOARD_WIDTH, 40, g);

次に、同じ Play.java でボタン リスナーを作成します。

graphics.btnStart.addActionListener(new ActionListener()
        {
           public void actionPerformed(ActionEvent e)
           {
              Action arc = p.getAction(g);
              g.update(arc);
              graphics.colours.clear();
              graphics.setColor(g.getBoard().getGrid());
              while (arc instanceof Store){
                  arc = p.getAction(g);
                  g.update(arc);
                  graphics.colours.clear();
                  graphics.setColor(g.getBoard().getGrid());
              }

             graphics.tiles.redraw();
             System.out.println();
             System.out.println(g.toString());
             System.out.println();
           }

        });


        graphics.btnAuto.addActionListener(new ActionListener()
        {
           public void actionPerformed(ActionEvent e)
           {

               while (!g.gameEnded()){
                  Action arc = p.getAction(g);
                  g.update(arc);
                  graphics.colours.clear();
                  graphics.setColor(g.getBoard().getGrid());
                  while (arc instanceof Store){
                      arc = p.getAction(g);
                      g.update(arc);
                      //graphics.colours.clear();
                      graphics.setColor(g.getBoard().getGrid());
                  }
                  graphics.tiles.redraw();
                  System.out.println();
                  System.out.println(g.toString());
                  System.out.println();
                  /*try {
                    Thread.sleep(1000);
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }*/

               }

           }

        });

btnStart は完全に機能し、1 回押すと、AI エージェントによって与えられた次の動きに従ってテトリスボードがペイントされます。

ユーザーが btnStart を押して最後まで動きを生成することなく、btnAuto が各動きを再生するようにしたいと思います。ただし、私の btnAuto はグリッドに何も描画しませんが、ゲームの最終状態である終了状態を描画します。

各移動が while ループで生成された後、これがグリッドを再描画しない理由を誰にも理解できますか?

4

1 に答える 1

3

while ループが Swing イベント スレッドで呼び出されているため、スレッドが GUI のレンダリングやユーザーとの対話などの必要なアクションを実行できません。

while (!g.gameEnded()){
  Action arc = p.getAction(g);

  // ....

}

ここでは、ループの代わりにSwing Timerを使用します。while (true)もう 1 つのオプションはバックグラウンド スレッドを使用することですが、必要なのは非常に単純なゲーム ループであり、バックグラウンドで長時間実行する必要がないため、この 2 番目のオプションはより複雑であり、追加の利点はないと思います。

余談ですが、あなたがどのように描画を行っているのか、どのように Graphics オブジェクトを描画するようになっているのか知りたいです。getGraphics()コンポーネントを呼び出していませんよね?


コメントであなたの状態を編集します:

現在、JPanel を拡張するネストされたクラスを持つクラスがあります。グリッドと getGraphics() の描画は、ネストされたクラス内で行われます。親クラスはコンポーネントを作成し、GUI 全体のレイアウトを設定します。

getGraphics()取得した Graphics オブジェクトは保持されないため、GUI コンポーネントを呼び出して Graphics オブジェクトを取得しないでください。これがそうであることを確認するには、単純にアプリケーションを最小化してから復元し、これを行った後にグラフィックスがどうなるか教えてください。JPanel の paintComponent オーバーライドですべての描画を行う必要があります。1 つのオプションは、BufferedImage を呼び出しgetGraphics()、それを使用して BufferedImage に描画してから、paintComponent オーバーライドで BufferedImage を表示することです。2 番目の手法を使用する場合は、システム リソースを浪費しないように、使用後に BufferedImage の Graphics オブジェクトを破棄することを忘れないでください。

于 2013-05-19T04:50:52.630 に答える