你如何在Java中为游戏加倍缓冲?

Posted

技术标签:

【中文标题】你如何在Java中为游戏加倍缓冲?【英文标题】:How do you double buffer in java for a game? 【发布时间】:2012-05-17 11:50:22 【问题描述】:

所以在我正在开发的游戏中,我有一个弹珠跟随鼠标,但是当它这样做时屏幕会闪烁。

背景包括两个 jpeg 和 9 个矩形。我将如何进行双重缓冲呢?这是主窗口的代码。

/**
 * Write a description of class Window here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Window extends JApplet implements MouseMotionListener

    private BufferedImage image; 
    private BufferedImage side;
    private int mouseX;
    private int mouseY;

    public Window()
        try 
            image = ImageIO.read(new File("Backgrounds/violet.jpg"));
            side = ImageIO.read(new File("Backgrounds/side margin.jpg"));
         catch (IOException ex)      
       

    private void delay(int delay)
    
        try 
            Thread.sleep(delay);
         catch (InterruptedException e) 
    

    public void init()
    
        this.addMouseMotionListener(this);
    

    public void paint (Graphics page)
    
        page.drawImage(image, 0, 0, null);
        page.setColor(Color.blue);
        page.fillRect(0, 0, 160, 160);
        page.setColor(Color.black);
        page.fillRect(15, 15, 130, 130);
        page.setColor(Color.green);
        page.fillRect(340, 0, 160, 160);
        page.setColor(Color.black);
        page.fillRect(355, 15, 130, 130);
        page.setColor(Color.yellow);
        page.fillRect(0, 340, 160, 160);
        page.setColor(Color.black);
        page.fillRect(15, 355, 130, 130);
        page.setColor(Color.red);
        page.fillRect(340, 340, 160, 160);
        page.setColor(Color.black);
        page.fillRect(355, 355, 130, 130);
        page.drawImage(side, 500, 0, null);
        page.drawString(Score.getScore(), 560, 110);
        //conveyors
        page.setColor(Color.gray);
        page.fillRect(235, 0, 30, 160);

        //marble
        delay(100);

        page.fillOval(mouseX, mouseY , 40, 40);          
    

    public void mouseMoved(MouseEvent e)
    
        mouseX = e.getX();
        mouseY = e.getY();
        repaint();
    

    public void mouseDragged(MouseEvent e)
    

    

【问题讨论】:

【参考方案1】:

双缓冲在概念上非常简单,不是一个一个地绘制对象,而是将它们绘制在图像上,然后告诉渲染器绘制整个图像。这消除了闪烁。

这是一个示例,说明您可以如何执行此操作 (source)

class DoubleBufferedCanvas extends Canvas 

    public void update(Graphics g) 
    Graphics offgc;
    Image offscreen = null;
    Dimension d = size();

    // create the offscreen buffer and associated Graphics
    offscreen = createImage(d.width, d.height);
    offgc = offscreen.getGraphics();
    // clear the exposed area
    offgc.setColor(getBackground());
    offgc.fillRect(0, 0, d.width, d.height);
    offgc.setColor(getForeground());
    // do normal redraw
    paint(offgc);
    // transfer offscreen to window
    g.drawImage(offscreen, 0, 0, this);
    

现在,您不必自己实现,您可以使用 BufferStrategy 和相关类。请参阅 lakam99 的答案以获取该示例。

【讨论】:

很好的答案,但您不需要这样做,因为 Swing 已经提供了双缓冲。有关详细信息,请参阅我的答案.... @dfb 在你'paint(offgc);'之后屏幕外的图像如何更新?我没有看到屏幕外变量在任何地方发生变化。 offgc = offscreen.getGraphics();一行【参考方案2】:

我认为您的问题不在于双缓冲。您必须在您的绘制方法的第一行添加super.paint(page);

【讨论】:

【参考方案3】:

Swing 自动支持双缓冲,因此您无需编写任何代码。

只需在您的***组件(通常是 JPanel)上调用 setDoubleBuffered(true),它就可以正常工作了。

见:setDoubleBuffered

【讨论】:

【参考方案4】:

另一种解决方案是使用可以为您提供双倍缓冲的库。由于您使用的是 Java2D,我假设您希望保持一切都非常轻量级和较低级别。我认为 Slick2D 在提供简单的 2d 绘图和输入功能方面做得很好,而且不会妨碍您。它感觉像是一个更优雅的 Java2D 版本,但它是在 OpenGL 上编写的。一旦你用纯 Java 制作了一些应用程序,我认为转向 Slick2D 是一个好主意。这不是您的问题的直接解决方案,但由于它已经解决,我认为 Id 提供了一些建议,可以让您的 Java 游戏开发生活更轻松。有机会就去看看http://slick.cokeandcode.com/

【讨论】:

以上是关于你如何在Java中为游戏加倍缓冲?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中为 Web 套接字客户端(Jetty)设置最大缓冲区大小

求教如何在Unity中为2D游戏制作技能特效

如何在andengine中为游戏场景添加背景音乐

如何在 gRPC 中为 Java 手动生成客户端和服务器代码?

每次出现在 pygame 中时,动画的持续时间都会加倍

在 Java 中为 JOGL 释放直接缓冲区本机内存