Java-графика мигает
Хорошо, я понимаю вашу потребность в SSCCE, поэтому я создал (мой первый).
Мне удалось реплицировать проблему до 200 строк кода. В моей системе эта демонстрация скомпилировалась и работала отлично (только мерцание было все еще там, конечно).
Я раздели все, что не имеет к этому никакого отношения. Итак, в основном у нас есть два исходных файла: диспетчер экрана и менеджер игр.
Диспетчер экрана:
http://pastebin.com/WeKpxEXW
Игровой менеджер:
http://pastebin.com/p3C5m8UN
Вы можете скомпилировать этот код с этим make файлом (я использую портированную версию Linux для Windows): CC = javac BASE = nl/jorikoolstra/jLevel CLASS_FILES = classes/$(BASE)/Game/GameMain.class classes/$(BASE)/Graphics/ScreenManager.class
jLevel: $(CLASS_FILES)
@echo Done.
classes/%.class : src/%.java
@echo Compiling src/$*.java to [email protected] [command: $(CC) src/$*.java ] ...
@$(CC) -Xlint:unchecked -d classes -classpath src src/$*.java
Если исходные файлы помещаются в каталог /src
и классы в каталоге /classes
.
После компиляции в байт-код игра может быть запущена с использованием следующего .bat файла:
@set STARUP_CLASS=nl.jorikoolstra.jLevel.Game.GameMain
@set ARGUMENTS=1280 1024 32
@java -cp classes;resources %STARUP_CLASS% %ARGUMENTS%
Обратите внимание, что переменная ARGUMENT
зависит от ваших собственных настроек экрана и что вы должны ее изменить, чтобы игра отображалась в правильном разрешении для вашего экрана.
Ответы
Ответ 1
Я вижу, почему он мерцает ----
BufferStrategy
выполняет отдельное задание на рисование с помощью метода Component paint()
, и они, похоже, используют разные объекты Graphics
, и они обновляются с другой скоростью -
когда paint()
вызывается перед show()
, это нормально. Но
когда paint()
вызывается после show()
, он перекрасит компонент в свой первоначальный пустой вид - так происходит мигание.
Очень легко устранить мерцание: переопределить paint()
метод вашего JFrame
(GameMain
), поскольку вам не нужно ничего делать (BufferStrategy
может дать вам более точный контроль над материалами для рисования)
@Override
public void paint (Graphics g) {}
Это все. (Я тестировал его, и он отлично работает, надеюсь, что это может помочь:))
===== Обновление =====
Вместо того, чтобы переопределять метод paint()
, лучший способ - вызвать setIgnoreRepaint(true)
для вашего JFrame
(GameMain
) - этот метод предназначен только для таких целей! ИСПОЛЬЗУЙТЕ ЭТО!
private GameMain(String ... args)
{
setIgnoreRepaint(true);
.....
}
Ответ 2
Это может сработать для вас, когда вы установите свой hwnd.createBufferStrategy(2)
в свой собственный метод.
Ответ 3
Вот как я реализую двойную буферизацию, может помочь вам получить концепцию.
Обратите внимание, что он реализован в JPanel, но я думаю, что он может быть реализован в других контейнерах:
TheJApplet.java:
import java.awt.*;
import javax.swing.*;
public class TheJApplet extends JApplet
{
private Image myImage;
java.net.URL GameURL = CheckerGameJApplet.class.getResource("GameIMG");
String GamePath = GameURL.getPath();
@Override
public void init()
{
String GraphPath = GamePath+"/";
File myImage_File = new File(GraphPath+"myImage.jpg");
try
{
myImage = ImageIO.read(myImage_File);
}
catch (IOException ex)
{
// Add how you like to catch the IOExeption
}
final TheJPanel myJPanel = new TheJPanel(myImage);
add(myJPanel);
}
}
TheJPanel.java:
import java.awt.*;
import javax.swing.*;
public class TheJPanel extends JPanel
{
private int screenWidth = 500;
private int screenHeight = 500;
private BufferedImage BuffImg = new BufferedImage
(screenWidth,
screenHeight,
BufferedImage.TYPE_INT_RGB);
private Graphics2D Graph = BuffImg.createGraphics();
private Image myImage;
public TheJPanel(Image myImage)
{
this.myImage = myImage;
repaint();
}
@Override
public void paintComponent(Graphics G)
{
Graphics2D Graph2D = (Graphics2D)G;
super.paintComponent(Graph2D);
if(BuffImg == null)
{
System.err.println("BuffImg is null");
}
Graph.drawImage(myImage, 0, 0, this);
Graph2D.drawImage(BuffImg, 0, 0, this);
}
}
Надеюсь, это поможет, удачи.
Ответ 4
У меня есть межплатформенная Java AWT-программа с анимацией. У него возникали проблемы, пока я строго не выполнил код примера в документации Java BufferStrategy
. Однако я использую AWT Canvas, встроенный в иерархию Swing, а не полный экран, как вы. Вы можете видеть код здесь, если это интересно.
Еще одна вещь, которую следует отметить, заключается в том, что конвейер AWT использует примитивы OpenGL для хорошей производительности, а поддержка OpenGL нестабильна во многих видеодрайверах. Попробуйте установить последние версии драйверов для своей платформы.
Ответ 5
Возникла проблема с визуализацией Java прозрачным фоном GIF. Это может быть проблемой.
Ответ 6
Мне сложно ответить на ваш вопрос без SCCSE. Я также задаюсь вопросом, что делает RepaintManagerResetter.
Возможно, вы захотите установить свой цвет фона на некоторые причудливые цвета, такие как 0xFF00FF, чтобы узнать, удастся ли кто-нибудь "очистить" фон до начала розыгрыша. Если изображение мерцания фиолетовое, то это - если оно содержит мусор или старые изображения, возможно, это двойная буферизация.
В любом случае я постараюсь обеспечить, чтобы никто не ожидал себя. Во-первых, попробуйте запретить собственный код Windows рисовать фон окна. Установите это один раз:
/*
* Set a Windows specific AWT property that prevents heavyweight components
* from erasing their background.
*/
System.setProperty("sun.awt.noerasebackground", "true");
Кроме того, убедитесь, что вы переопределили это в своем JFrame (если вы используете компоненты Swing)
@Override
public void paintComponent(Graphics G)
{
// do not call super.pC() here
...
}
Если это не помогает, предоставьте рабочий пример вашего кода, чтобы люди могли воспроизвести проблему.