【问题标题】:java image appears and disappears when using game loop使用游戏循环时java图像出现和消失
【发布时间】:2016-03-19 22:17:28
【问题描述】:

游戏循环:

private int FPS = 25;
private int targetTime = 1000 / FPS;

public void run(){

    init();

    long start;
    long elapsed;
    long wait;

    while (running){

        start = System.nanoTime();
        init();
        repaint();
        elapsed = System.nanoTime()  - start;

        wait = targetTime - elapsed / 1000000;

        try {

            Thread.sleep(wait);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

绘制方法:

/**draws the game graphics*/
public void paint(Graphics g){
    super.paint(g);
    Graphics2D g2 = (Graphics2D)g;

    gameStateHandler.draw(g2);

}

paint方法也指的方法:

private static  Image image = resourceLoader.getImage("/background/menu_background.png");
/**draws the menu state*/
public static void draw(Graphics2D g){

    g.drawImage(image, 0, 0, null);
}

我通过这个方法调用图像,它位于图像的同一文件夹中

static resourceLoader rl = new resourceLoader();

public static Image getImage(String image){

    return Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource(image));
}

我有一个游戏循环,它将每秒调用repaint(); 60 次,在paint 方法中它指的是该方法绘制图像的方法。一切看起来都很好,很流畅,当我运行程序时,图像会很快出现和消失,有时图像会出现并且没有发生任何不好的事情,但是在随机发生的时间之后,我将 fps 从低到高再从高在这个项目中使用 jpanel 来降低仍然相同的 im

【问题讨论】:

  • 您的image 是如何/在哪里创建/操作的?
  • 听起来好像缺少双缓冲content.gpwiki.org/index.php/…
  • @weston 也是这么想的,但是将图像blitting到画布应该尽可能快地更新显示。
  • 对于双缓冲,你也可以看看这里:stackoverflow.com/questions/10508042/…
  • @HannoBinder 我也发现了,但是关于这个问题并没有很好的答案。

标签: java image paint game-loop


【解决方案1】:

好的,这里有一个建议,很可能是您需要的解决方法:

使用paintComponent() 而不是paint()

// draws the game graphics

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;    
    gameStateHandler.draw(g2);    
}

paintComponentrecommended way to use JPanels to paint in Java - 另见a more detailed explanation of custom painting in Swing。很可能是您对paint() 的使用导致您的视觉不一致。

如果做不到这一点,我建议你看看你是如何加载资源的,但这应该可以工作,所以我认为这不是问题。

【讨论】:

  • 好的,谢谢,但你如何在游戏循环中调用它?对不起,我是一个新程序员@Gorbles
  • 这应该在你调用repaint() 时由 Swing 调用 - 它应该自动完成。
【解决方案2】:

在你的游戏循环中,之后

 wait = targetTime - elapsed / 1000000;

添加行

 wait = Math.max(5L, wait);

以防止您的等待时间过短或变为负数。

【讨论】:

  • 它没有解决问题@Gilbert le blanc
【解决方案3】:

不要使用 Thread.sleep()。如果在EDT 上调用它可能会导致卡顿。

对于 swing,你应该使用 javax.swing.Timer:
1. 使用所需的延迟(您的 targetTime)初始化 Timer。
2. 在计时器 actionPerformed() 上调用 repaint()。

【讨论】:

  • Thread.sleep() 可以导致卡顿,但不会假定您的目标帧率是可以接受的。当然,在您的屏幕上绘制一张图像不会对现代硬件造成不必要的延迟,尤其是在 25FPS 的目标速率下。不幸的是,我不确定您的建议是否会有所帮助。
猜你喜欢
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多