Search code examples
javamultithreadingperformanceframe-ratepaintcomponent

Java: Speed up my code


I have been coding an application which renders tiles and GUI and all that. I seem to have come across a problem where my paintComponent seems to hog too much CPU and can no longer run much higher than 10 FPS on my small computer. I was wondering if there was any more efficient way of running this code or threading it or anything to enhance the calculation speed. Here is my code:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class M1 extends JPanel implements Runnable {
public static double zoom = 1.25;
public static double charZoom = 1;
public static boolean breaking = false;

public void run() {

}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if(zoom <= 0.03) zoom = 1.25;

    for(int cy = 0; cy < 3; cy++) {
        for(int cx = 0; cx < 3; cx++) {
            for(int y = 0; y < 16; y++) {
                for(int x = 0; x < 16; x++) {
                    g.drawImage(Tiles.tileImages.get(C0.chunk[x][y][cx][cy]), 
                            (int)((C0.cX[cx][cy] * C0.chunkWidth) * zoom) + ((int)(32 * zoom) * x) + 
                                ((M0.gameFrame.getWidth() / 2)) - (int)(PEntity.x.getValue() * zoom),
                            (int)((C0.cY[cx][cy] * C0.chunkHeight) * zoom) + ((int)(32 * zoom) * y) + 
                                ((M0.gameFrame.getHeight() / 2)) - (int)(PEntity.y.getValue() * zoom) + (int)(24.25 * zoom),// <-- 24.25 used to correctly position  charatcter
                            (int)(32 * zoom), (int)(32 * zoom), this);
                    if(C0.chunk[x][y][cx][cy].equals("a05")) {
                        g.drawImage(Tiles.treetop, 
                                (int)((C0.cX[cx][cy] * C0.chunkWidth) * zoom) + ((int)(32 * zoom) * x) + 
                                    ((M0.gameFrame.getWidth() / 2)) - (int)(PEntity.x.getValue() * zoom),
                                (int)((C0.cY[cx][cy] * C0.chunkHeight) * zoom) + ((int)(32 * zoom) * y) + 
                                    ((M0.gameFrame.getHeight() / 2)) - (int)(PEntity.y.getValue() * zoom) + (int)(24.25 * zoom)
                                    - (int) (32 * zoom),// <-- 24.25 used to correctly position  charatcter
                                (int)(32 * zoom), (int)(32 * zoom), this);
                    }
                }
            }
        }
    }

    if(breaking) {
        g.drawImage(M3.currentBreak, (int)((C0.cX[M3.cx][M3.cy] * C0.chunkWidth) * zoom) + ((int)(32 * zoom) * M3.x) + 
                ((M0.gameFrame.getWidth() / 2)) - (int)(PEntity.x.getValue() * zoom),
                (int)((C0.cY[M3.cx][M3.cy] * C0.chunkHeight) * zoom) + ((int)(32 * zoom) * M3.y) + 
                ((M0.gameFrame.getHeight() / 2)) - (int)(PEntity.y.getValue() * zoom) + (int)(24.25 * zoom),
                (int)(32 * zoom), (int)(32 * zoom), this);
    }

    M3.placeX = (48 * zoom);
    M3.placeY = (48 * zoom);

    if(M0.HUDenabled) {
        g.drawImage(PEntity.currentChar, 
                (M0.gameFrame.getWidth() / 2) - (int)((16 * charZoom) * zoom), 
                (M0.gameFrame.getHeight() / 2) - (int)((32 * charZoom) * zoom),
                (int)((32 * charZoom) * zoom), (int)((64 * charZoom) * zoom), this);

        g.setColor(Color.BLACK);
        g.setFont(new Font("Dialog", 1, 12));
        g.drawString("Terrem" + " By Tyler D :)", 5, 15);
        g.drawString("X: " + PEntity.x.getValue(), 5, 28);
        g.drawString("Y: " + PEntity.y.getValue(), 5, 41);
        g.drawString("ChunkX: " + C0.currentChunkX.getValue(), 5, 54);
        g.drawString("ChunkY: " + C0.currentChunkY.getValue(), 5, 67);
        g.drawString("BlockX: " + C0.currentBlockX.getValue(), 5, 80);
        g.drawString("BlockY: " + C0.currentBlockY.getValue(), 5, 93);
        g.drawString("Zoom: " + zoom, 5, 106);
        g.drawString(M4.tileArea[0][0] + "_" + M4.tileArea[1][0] + "_" + M4.tileArea[2][0], 5, 126);
        g.drawString(M4.tileArea[0][1] + "_" + M4.tileArea[1][1] + "_" + M4.tileArea[2][1], 5, 139);
        g.drawString(M4.tileArea[0][2] + "_" + M4.tileArea[1][2] + "_" + M4.tileArea[2][2], 5, 152);
        g.drawString("FPS: " + (int) FPS.currentFPS, 5, 172);

        //GUI
        g.drawImage(M0.GUIbar, (M0.gameFrame.getWidth() - (624)) / 2, (M0.gameFrame.getHeight() - 80), 624, 40, this);
        for(int i = 0; i < 9; i++) {
            g.drawImage(Item.Item_Img.get(PEntity.PInv[i]), ((M0.gameFrame.getWidth() - (624)) / 2) + 6 + (36 * i), 
                    (M0.gameFrame.getHeight() - 74), 28, 28, this);
            if(Item.Item_Img.get(PEntity.PInv[i]) != null) {
                g.drawString("" + (PEntity.stk[i] + 1), ((M0.gameFrame.getWidth() - (624)) / 2) + 6 + (36 * i), 
                        (M0.gameFrame.getHeight() - 47));
            }
        }
    }

    repaint();
    FPS.calculateFrameRate();
}

public M1() {
    M0.gameFrame.setVisible(true);
    Clock.Start();
    setBackground(new Color(242, 220, 121));
    System.out.println("M1 loaded...");
}
}

Also I can tell it is the large loop which kills off about 200 FPS at this point because I commented that part off and my FPS shot up to about 250.


Solution

  • Seems like you could multi-thread some of your outer for-loops at the top of the method, if the Graphics2D instance you are using is thread-safe. Might be worthwhile to keep a ThreadPoolExecutor around for this and then break up your outer for-loops into instances of Runnable. This totally depends on whether or not the order of the draw matters to you - it's hard to tell just from the code you've posted.

    One other thing that jumps out at me is how you're accessing your 4-D image array. Recall that multi-dimensional Java arrays are actually arrays of references to other arrays. You'd probably be better off getting a reference to a specific sub-array at the top of each loop, and accessing the sub-array reference that you've saved, rather than indexing the original array directly. This will save you a lot of unnecessary memory fetches.