Game is lagging when drawing buffered image

Viewed 88

I am making a game and I want to add the option to fullscreen so it scales all graphics to the new expanded JFrame. Code works great and does exactly what I want, but now I have a problem and I'm assuming it's a memory problem or something because what I am doing is drawing everything to a buffered image and then drawing the buffered image scaled to the JFrame's size. Before, when I just drew everything directly to the frame, I would get ~900 frames constant. But when I implement my new method it drops right away to 120 frames and freezes for about half a second every few seconds.

This is the current method:

private void render() {
    BufferStrategy bs = this.getBufferStrategy();
    if (bs == null) {
        this.createBufferStrategy(3);
        return;
    }
    
    Graphics g = bs.getDrawGraphics();
    
    BufferedImage screen = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = (Graphics2D) screen.getGraphics();
    
    g2d.translate(-Camera.getX(), -Camera.getY());
    
    level.render(g2d);
    handler.render(g2d);
    
    g2d.translate(Camera.getX(), Camera.getY());
    
    g.drawImage(screen, 0, 0, fullWidth, fullHeight, null);
    
    bs.show();
    g2d.dispose();
    g.dispose();
}

And this is what the method looked like before that was giving 900 or more frames with no freezing:

private void render() {
    BufferStrategy bs = this.getBufferStrategy();
    if (bs == null) {
        this.createBufferStrategy(3);
        return;
    }
    Graphics g = bs.getDrawGraphics();
    Graphics2D g2d = (Graphics2D) g;
    
    g2d.translate(-Camera.getX(), -Camera.getY());
    
    level.render(g);
    handler.render(g);
    
    g2d.translate(Camera.getX(), Camera.getY());
    
    bs.show();
    g.dispose();
}
1 Answers

Get e.g. the height of the image and make that the loop counter stop quantity, then paint a line at a time in a method. The JVM "stack" is supposedly max assigned on the startup command line flags total 1 megabyte for -Xss. You also should reserve around 1gb space for an image in the heap eden e.t.c. https://www.baeldung.com/jvm-configure-stack-sizes see also garbage collector docs

"dispose" on graphics only nulls the reference.

System.gc();

This will call the garbage collector to clean up the RAM. With imaging programs invariably they require reserving some RAM for the JVM on the startup command line. Too it is possible to pass flags to the JVM on how to handle garbage, usually System.gc is fine but with heavy server usage they require garbage collector schemes put in as flags. See G1 garbage collector if you need a scheme (900 frames - seems you definitely require a garbage collection scheme too). https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

The "show" method of a top level window such as Frame or Window is to initialize onto the screen once only NOT for the image painting itself, images you need to repaint its matrix (Raster) of the image by getting a Graphics object from a method of the exact e.g. Buffered image you want to paint and do not need to dispose of it for the next image pixel setting (it belongs to that image) but may need to put it somewhere permanent such as global reference so it is not destroyed when a method finishes, and then call the Window,Frame,panel "repaint" method after setting all the pixel values. With java.swing J system you do not use "show" , you feed a boolean true to method "setVisible" , It also requires to wrap setVisible in SwingUtilities.invokeLater , nothing too difficult to google. If anything solves it well download the Sun Microsystems Java tutorials (now Oracle) URL example: https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html get yourself a copy after sign up its free to devs.

Related