Java Swing Paint Performance

52 views Asked by At

I'm developing a game using Java Swing and because of high responsive notion of the game, it has to have a high FPS. Yet after optimizing my program in any way I knew, it still takes a lot of time to simply paint images on the JPanel. (about 20ms per each entity) Here's my custom paint method in paintComponent:

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (GeoShapeView shapeView: shapeViews) {
            Point location = getRelativeLocation(getCornerAnchorLocation(shapeView.getViewId()));
            shapeView.rotatedIcon.paintIcon(this, g, location.x, location.y);
        }
    }

where rotatedIcon is a class implementing Icon:

package view;

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

import static view.Utils.rotatedInfo;

public class RotatedIcon implements Icon {

    private final Icon icon;

    @SuppressWarnings("FieldMayBeFinal")
    private Point rotationAnchor;
    private double degrees;
    private final boolean isCircular;
    private int width;
    private int height;
    public RotatedIcon(BufferedImage image, Point rotationAnchor, double degrees, boolean isCircular) {
        this.icon=new ImageIcon(image);
        this.rotationAnchor=rotationAnchor;
        this.degrees=degrees;
        this.isCircular = isCircular;
    }
    @Override
    public int getIconWidth() {
        if (isCircular) return icon.getIconWidth();
        else return width;
    }
    @Override
    public int getIconHeight() {
        if (isCircular) return icon.getIconHeight();
        else return height;
    }
    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2d = (Graphics2D) g.create();

        Dimension viewSizeSave=new Dimension(icon.getIconWidth(),icon.getIconHeight());
        Point[] rotatedInfo= rotatedInfo(viewSizeSave,rotationAnchor,degrees,isCircular);
        width=rotatedInfo[0].x;
        height=rotatedInfo[0].y;

        int lowerX=Math.max(x-rotatedInfo[1].x,0);
        int lowerY=Math.max(y-rotatedInfo[1].y,0);
        int upperX=Math.min(lowerX+getIconWidth(),c.getWidth());
        int upperY=Math.min(lowerY+getIconHeight(),c.getHeight());
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setClip(lowerX,lowerY, upperX-lowerX, upperY-lowerY);
        g2d.rotate(Math.toRadians(degrees), x+rotationAnchor.x,y+rotationAnchor.y);
        icon.paintIcon(c, g2d, x, y);
        g2d.dispose();
    }

Finally, I don't think it might be of importance but here's the rotatedInfo method:

    public static Point[] rotatedInfo(Dimension viewSize,Point relativeAnchor,double angle,boolean isCircular){
        //Returns an array of 2 points containing newSize, Offset

        if (isCircular) return new Point[]{new Point(viewSize.width,viewSize.height),new Point(0,0)};
        Point[] corners=new Point[]{new Point(0,0),new Point(viewSize.width,0),new Point(0,viewSize.height),new Point(viewSize.width,viewSize.height)};
        Point[] rotatedCorners=new Point[4];
        for (int i=0;i<corners.length;i++) rotatedCorners[i]=rotateAbout(relativeAnchor,corners[i],angle);
        ArrayList<Integer> rotatedCornersX=new ArrayList<>();
        ArrayList<Integer> rotatedCornersY=new ArrayList<>();
        for (Point point: rotatedCorners){
            rotatedCornersX.add(point.x);
            rotatedCornersY.add(point.y);
        }
        int xLower= Collections.min(rotatedCornersX);
        int yLower= Collections.min(rotatedCornersY);
        int xUpper= Collections.max(rotatedCornersX);
        int yUpper= Collections.max(rotatedCornersY);

        return new Point[]{new Point(xUpper-xLower,yUpper-yLower),new Point(-xLower,-yLower)};
    }

I did everything I knew and noticed to speed up the custom painting but as I mentioned, it's still too slow.

I tried using a SwingWorker to do the computations of the graphics in another thread but it turned out to take twice the time it currently takes to paint entities. I'm pretty sure the thing causing to the low speed of painting is in the code snippets I included. Any help/clue/reference would be much appreciated.

0

There are 0 answers