重绘时特定对象闪烁
Specific objects flickering when repainted
本题不是“整个屏幕都在闪烁”类型的题。
我正在尝试理解Java图形并制作了一个简单的游戏,但是当用新对象重绘场景时,一些对象一直在闪烁,奇怪 不是整个屏幕.
这是我的 render()
方法:
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
createBufferStrategy(6);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D)g;
//fill screen with black background
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
//draw cool stuff
try {
for (int i = 0; i < Element.elements.size(); i++) {
Element.elements.get(i).render(g2d);
}
} catch (Exception e) {
System.err.println("No such element to render");
}
//dispose graphics
g.dispose();
g2d.dispose();
bs.show();
}
什么可能导致这个问题?我不认为气泡的数量会导致这个问题。
您的模型更新是在鼠标移动时在事件线程中完成的,需要与您的渲染线程同步。发生闪烁是因为在渲染发生时您的模型有时处于不一致状态。
解决此问题的一种方法是在您更新模型的线程中进行渲染。您可以 运行 在事件线程中使用 SwingUtilities
:
进行渲染
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
render();
}
});
} catch (InvocationTargetException | InterruptedException e) {
running = false;
System.err.println("Render interrupted");
}
如果您正在使用由 AWT 或 Swing 呈现的组件,您应该始终在事件线程中进行呈现。
由于您自己控制整个渲染过程,因此您可以选择在单独的线程中进行渲染,但您必须同步对模型的访问(也就是说,写入事件线程执行的模型应该与渲染线程执行的读取同步)。
例如:
在Shredder.scan()
中(从事件线程调用)
public static void scan() {
synchronized (Element.elements) {
for (Element element : Element.elements) {
if (element.containsMouse()) {
if (element.getSize() < 24) {
Element.elements.remove(element);
} else {
element.cloneItself();
Element.elements.remove(element);
}
skip = true;
break;
}
}
}
}
并且在您的渲染线程中:
synchronized (Element.elements) {
for (int i = 0; i < Element.elements.size(); i++) {
Element.elements.get(i).render(g2d);
}
}
就形式而言,将需要同步的代码放在一个位置是个好主意,这样调用代码就不必关心保持一致性。
本题不是“整个屏幕都在闪烁”类型的题。
我正在尝试理解Java图形并制作了一个简单的游戏,但是当用新对象重绘场景时,一些对象一直在闪烁,奇怪 不是整个屏幕.
这是我的 render()
方法:
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
createBufferStrategy(6);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D)g;
//fill screen with black background
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
//draw cool stuff
try {
for (int i = 0; i < Element.elements.size(); i++) {
Element.elements.get(i).render(g2d);
}
} catch (Exception e) {
System.err.println("No such element to render");
}
//dispose graphics
g.dispose();
g2d.dispose();
bs.show();
}
什么可能导致这个问题?我不认为气泡的数量会导致这个问题。
您的模型更新是在鼠标移动时在事件线程中完成的,需要与您的渲染线程同步。发生闪烁是因为在渲染发生时您的模型有时处于不一致状态。
解决此问题的一种方法是在您更新模型的线程中进行渲染。您可以 运行 在事件线程中使用 SwingUtilities
:
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
render();
}
});
} catch (InvocationTargetException | InterruptedException e) {
running = false;
System.err.println("Render interrupted");
}
如果您正在使用由 AWT 或 Swing 呈现的组件,您应该始终在事件线程中进行呈现。
由于您自己控制整个渲染过程,因此您可以选择在单独的线程中进行渲染,但您必须同步对模型的访问(也就是说,写入事件线程执行的模型应该与渲染线程执行的读取同步)。
例如:
在Shredder.scan()
中(从事件线程调用)
public static void scan() {
synchronized (Element.elements) {
for (Element element : Element.elements) {
if (element.containsMouse()) {
if (element.getSize() < 24) {
Element.elements.remove(element);
} else {
element.cloneItself();
Element.elements.remove(element);
}
skip = true;
break;
}
}
}
}
并且在您的渲染线程中:
synchronized (Element.elements) {
for (int i = 0; i < Element.elements.size(); i++) {
Element.elements.get(i).render(g2d);
}
}
就形式而言,将需要同步的代码放在一个位置是个好主意,这样调用代码就不必关心保持一致性。