1

javax.swing.JFrameダブルバッファ戦略を使用してゲームアニメーションを描画するために使用しています。まずはフレームを組み立てます。

JFrame frame = new JFrame();
frame.setVisible(true);

今、私はこのようにオブジェクトを描きます(それは円で構いません)。

frame.createBufferStrategy(2);
bufferStrategy = frame.getBufferStrategy();
Graphics g = bufferStrategy.getDrawGraphics();
circle.draw(g);
bufferStrategy.show();

問題は、描画が行われるときにフレームが常に完全に設定されていないことです.

JFrame は、最終的なサイズに達するまで、サイズを変更するために最大 3 つのステップを必要とするようです。これにより、図面がフレームから外れたり、完全に表示されなくなったりすることがあります。

私はすでに を使用して物事を遅らせることができましたSwingUtilities.invokeLater()。これにより結果は改善されましたが、描画がスライドして離れたり、時期尚早に描画されたように見えることがあります。

アイデア/戦略はありますか?前もって感謝します。

編集:これまでのところありがとうございます。そもそも、ちょっとした Pong ゲームを書いているとは言いませんでした。混乱して申し訳ありませんが、私が実際に探していたのは、Java で行われる高速化されたゲーム アニメーションの適切なセットアップでした。提案を読んでいると、ここで(間接的ではありますが)私の質問に答えていることがわかりました。この例では、物事が明確になりました。

これを要約すると、Java でゲーム グラフィックスをアニメーション化するための最初のステップは、GUI ロジックのオーバーヘッドを取り除くことです。

パッシブレンダリングとアクティブレンダリングの違いに関するチュートリアル記事があります。それは初心者の頭をきれいにするのに役立つかもしれません...

4

4 に答える 4

2

GlassPaneを使用することも、単にLayerUIを上に配置することもできます(例:次のように)。

スケーリングする小さな何か

フレームのサイズを変更すると、円が再スケーリングされます。

import java.awt.*;
import java.awt.geom.Ellipse2D;

import javax.swing.*;
import javax.swing.plaf.LayerUI;

/**
 */
public class ALittleSomething {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("A Little Something");
                JLayer<JComponent> aLittleSomething = new JLayer<>(new ALittleSomethingPanel(), new ALittleSomethingUI());
                frame.getContentPane().add(aLittleSomething);
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setMinimumSize(new Dimension(800, 450));
                frame.setLocationRelativeTo(null); // Center
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    static class ALittleSomethingPanel extends JPanel {

        private JLabel aLittleSomethingLabel = new JLabel("A Little Something");

        ALittleSomethingPanel() {
            add(aLittleSomethingLabel);
            aLittleSomethingLabel.setFont(aLittleSomethingLabel.getFont().deriveFont(42f));
        }
    }

    static class ALittleSomethingUI extends LayerUI<JComponent> {

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2 = (Graphics2D) g.create();
            super.paint(g2, c);
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            int height = c.getHeight();
            int width = c.getWidth();

            Shape circle = new Ellipse2D.Double(5, 5, width - 10, height - 10);

            g2.setPaint(new GradientPaint(15, 0, new Color(90, 97, 105), 15, 30, new Color(132, 142, 152)));
            g2.setStroke(new BasicStroke(5));
            g2.draw(circle);

            g2.dispose();
        }
    }
}
于 2012-11-09T18:02:55.470 に答える
2

カスタム コンポーネントに描画し、これをフレームに追加する方がよいでしょう。まず、ルート ペインの使用方法を見て、フレームに直接描画するのがなぜ悪い考えなのかを調べてください (既に多くの要素が上に表示されています)。それから) 次に、これこれこれを見て、Swing を使用して行われた (基本的な) アニメーションの例を見てください - すべてデフォルトのバッファリング戦略だけで

また、いくつかの入門書として、カスタム ペインティングGraphics2Dの実行もご覧になることをお勧めします。

于 2012-11-09T21:23:59.310 に答える
1

質問が少し誤解を招き、ツールを本当に理解する前に物事を混ぜ合わせたので、私はこの質問に自分で答えます。ここから学んだことは、Java でのグラフィック プログラミングには、パッシブレンダリングとアクティブレンダリングの 2 つのアプローチがあるということです。

パッシブレンダリングはイベント ディスパッチ スレッド (EDT) 内から発生し、これはオペレーティング システムと VM にコンポーネントを描画する適切なタイミングを決定させるプロセスですが、物事が描画される正確な瞬間を決定することは実際には不可能であるか、決定したいと考えていました。 . これは、アニメーション ゲーム グラフィックスを作成するための正しいアプローチではありません。

代わりに必要なのは、このような記事に記載されているアクティブレンダリング ターゲットです。そこで、レンダリング イベントのディスパッチを完全に無効にし、バッファ フリッピングまたはブリットを介してシーン全体をアクティブに再描画します ( BufferStrategy を参照)。

AWT/Swing でのパッシブ レンダリングとアクティブ レンダリングの違いは、Java チュートリアル で簡単に説明ます

于 2012-11-10T11:01:46.890 に答える
0

このようなものはどうですか:

private void createAndShowGUI()
{
  frame = new JFrame();
  frame.createBufferStrategy(2);
  bufferStrategy = frame.getBufferStrategy();
  Graphics g = bufferStrategy.getDrawGraphics();
  circle.draw(g);
  bufferStrategy.show();
  frame.setVisible(true);
}

そして、コンストラクターなどからそれを呼び出します:

public MyClass()
{
   SwingUtilities.invokeLater(new Runnable()
   {
      public void run()
      {
         createAndShowGUI();
      }
   });

   try
   {
      while(frame == null || !frame.isVisible())
         Thread.sleep(1);
   }
   catch(InterruptedException e)
   {
     e.printStackTrace();
     System.exit(1);
   }
}

このようなものです。申し訳ありませんが、急いで投稿しているため、コードの一部が間違っている可能性があります。

于 2012-11-09T16:47:08.493 に答える