BufferStrategy в оконном режиме вызывает постоянное интенсивное мерцание белого экрана

Я собрал этот код, основываясь на множестве примеров, которые я нашел здесь на stackru. Когда я запускаю программу, весь экран сильно мерцает. Я уверен, что есть кое-что простое, что я пропускаю, но до сих пор не смог найти решение. Я отлаживал это в течение пары часов, в основном с помощью чтения онлайн-форумов, поэтому решил, что пришло время спросить аудиторию.

публичный класс Screen расширяет JComponent {

    @Override
    public Dimension getPreferredSize(){
        Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
        return tempDimension;
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2D = (Graphics2D)bufferStrategy.getDrawGraphics();
        g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
        if(game==null){
            drawSplash(g2D);
        }else{
            drawBoard(g2D);
        }
        g2D.dispose();
        bufferStrategy.show();
    }
}

Если требуется какой-либо дополнительный код, я могу предоставить его. Спасибо за вашу помощь, stackru!

1 ответ

Решение

Для достижения результатов, которые вы получаете, у вас есть другой класс, который простирается от Canvas или используете BufferStrategy из контейнера верхнего уровня. В любом случае, оба должны быть видны на экране.

По сути, они сражаются друг с другом, поскольку они представляют собой два разных алгоритма рисования. Swing - пассивный алгоритм рисования - рисует обновления по мере необходимости, а BufferStrategy, который использует активный алгоритм, требующий, чтобы вы планировали обновления буфера по мере необходимости.

Оба используют алгоритм двойной буферизации.

Итак, вы должны выбрать один или другой...

public class Screen extends JComponent {

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2D = (Graphics2D) g.create();
        g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
        if (game == null) {
            drawSplash(g2D);
        } else {
            drawBoard(g2D);
        }
        g2D.dispose();
    }
}

или что-то вроде...

public void gameEngine(BufferStrategy strategy) {

    // Main loop
    while (!done) {
        // Prepare for rendering the next frame
        // ...

        // Render single frame
        do {
            // The following loop ensures that the contents of the drawing buffer
            // are consistent in case the underlying surface was recreated
            do {
                // Get a new graphics context every time through the loop
                // to make sure the strategy is validated
                Graphics2D g2D = (Graphics2D) strategy.getDrawGraphics();

                // Render to graphics
                g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
                if (game == null) {
                    drawSplash(g2D);
                } else {
                    drawBoard(g2D);
                }
                // Dispose the graphics
                g2D.dispose();

                // Repeat the rendering if the drawing buffer contents
                // were restored
            } while (strategy.contentsRestored());

            // Display the buffer
            strategy.show();

            // Repeat the rendering if the drawing buffer was lost
        } while (strategy.contentsLost());
    }
}

Который был в значительной степени оторван от JavaDocs дляBufferStrategy

Кстати, это...

@Override
public Dimension getPreferredSize(){
    Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
    return tempDimension;
}

Это действительно плохой дизайн, вы делаете предположения о состоянии компонента, который может не соответствовать действительности. Вы должны позволить окну решать, насколько большим оно будет в конечном итоге, что может быть достигнуто с помощьюsetExtendedState и передать его JFrame.MAXIMIZED_BOTH, который будет учитывать другие элементы ОС, такие как панель задач или док-станция

Другие вопросы по тегам