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
, который будет учитывать другие элементы ОС, такие как панель задач или док-станция