Java图形闪烁

时间:2013-01-25 10:05:12

标签: java windows java-2d game-development

好的,我理解你需要一个SSCCE,所以我创建了(我的第一个)。

我设法用200行代码复制问题。在我的系统上,这个演示编译并完美运行(当然只有闪烁仍在那里)。 我剥夺了与它无关的所有东西。所以基本上我们现在有两个源文件:屏幕管理器和游戏管理器。

屏幕管理员: http://pastebin.com/WeKpxEXW

游戏经理: http://pastebin.com/p3C5m8UN

您可以使用此make文件编译此代码(我使用移植版本的Linux'make for 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 $@ [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变量取决于您自己的屏幕设置,并且您必须更改它,以便以适合您屏幕的分辨率显示游戏。

6 个答案:

答案 0 :(得分:5)

我明白为什么它会闪烁----

BufferStrategy正在使用Component的paint()方法执行单独的绘制作业,它们似乎使用不同的Graphics对象,并且它们以不同的速率刷新 -

paint()之前调用show()时,没关系。但

paint()之后调用show()时,它会将组件重新绘制为其初始空白外观 - 因此闪烁发生。


消除闪烁非常容易:覆盖paint()JFrame)的GameMain方法,因为您不需要它做任何事情(BufferStrategy可以给出你可以更精确地控制绘画内容):

@Override
public void paint (Graphics g) {}

这就是全部。 (我已经测试过,它运行正常,希望这可能会有所帮助:))


=====更新=====

而不是覆盖paint()方法,更好的方法是为setIgnoreRepaint(true)JFrame)调用GameMain - 此方法仅用于此类目的! 使用IT

private GameMain(String ... args)
{
    setIgnoreRepaint(true);
    .....
}

答案 1 :(得分:1)

当您使用自己的方法设置hwnd.createBufferStrategy(2)时,它可能适合您。

答案 2 :(得分:1)

这是我实现双缓冲的方式,可能会帮助你获得这个概念。 请注意,它是在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);
    }
}

希望这会有所帮助,祝你好运。

答案 3 :(得分:1)

我有一个基于Java AWT的跨平台程序,带有动画。在我严格遵循in the Java BufferStrategy documentation的示例代码之前,它有闪烁的问题。但是我使用的是嵌入在Swing层次结构中的AWT Canvas,而不是全屏幕。如果感兴趣,你可以see the code here

另外需要注意的是,AWT管道使用OpenGL原语以获得良好的性能,并且OpenGL支持在许多视频驱动程序中都存在错误。尝试为您的平台安装最新版本的驱动程序。

答案 4 :(得分:1)

Java渲染透明背景GIF图像时出现问题。这可能是问题所在。

答案 5 :(得分:0)

我发现没有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
  ...
}

如果这没有帮助,请提供代码的工作示例,以便人们可以重现问题。