Improving rendering performance of 2D Tile Game I want to see if I can make any improvements to the rendering methods that are currently written. I've noticed when profiling this project that the CPU was allocating a fair percentage of the time towards rendering and was wondering if there were any improvements that I can make towards it.

Note: Below is my somewhat simple rendering method. I am rendering an ArrayList of tiles, few of these are transparent. This function (y*map.getMapWidth())+x) will return the index in the ArrayList to be rendered.

ImageManager is a class that stores cropped images from a spritesheet as a BufferedImage.

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;


public class Game extends Canvas implements Runnable{

    private void renderTiles(Graphics g) {
        // the overlay variable determines if I need to render anything off screen
        // (True if player is moving)    
        int overlay = 0;
        if (moving) {
            overlay = 1;
        }

        // the four variables below determine the starting/finishing x/y variables 
        // to begin rendering
        int startX = -((xOffset/(Tile.TILESIZE*SCALE))+overlay);
        int finishX = -(((xOffset-(WIDTH*SCALE))/(Tile.TILESIZE*SCALE))-overlay);
        int startY = -((yOffset/(Tile.TILESIZE*SCALE))+overlay);
        int finishY = -(((yOffset-(HEIGHT*SCALE))/(Tile.TILESIZE*SCALE))-overlay);

        // to avoid crashes, the variables can't render what isn't there in the list
        if (startX &lt; 0) {
            startX = 0;                
        } if (finishX &gt; map.getMapWidth()) {
            finishX = map.getMapWidth();                
        } if (startY &lt; 0) {
            startY = 0;
        } if (finishY &gt; map.getMapHeight()) {
            finishY = map.getMapHeight();
        } 


        // where the tiles are render. tiles are stored in an ArrayList so that 
        // switching between maps is easier
        for (int y = startY; y &lt; finishY; y++) {
            for (int x = startX; x &lt; finishX; x++) {
                map.tile.get((y*map.getMapWidth())+x).render(g);
            }
        }
    }


    public void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs ==  null){
            createBufferStrategy(2);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        // start rendering

        g.fillRect(0, 0, WIDTH * SCALE, HEIGHT * SCALE);            
        renderTiles(g);
        player.render(g);
        g.dispose();
        bs.show();

    }
}


import java.awt.Graphics;
import java.awt.image.BufferedImage;

public abstract class Tile {

    public static final int TILESIZE = 16;  

    protected BufferedImage bi;
    protected ImageManager im;
    protected int x, y, oX, oY;
    protected Game game;

    public Tile(int x, int y, ImageManager im, Game game, BufferedImage bi){
        this.oX = x;
        this.oY = y;
        this.im = im;
        this.game = game;
        this.bi = bi;
    }

    public abstract void tick();
    public abstract void render(Graphics g);

}

import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class WalkableTerrainTile extends Tile{     

    public WalkableTerrainTile(int x, int y, ImageManager im, Game game, BufferedImage bi) {
        super(x, y, im, game, bi);
    }

    public void tick() {
        this.game  = game;
        x = oX + game.xOffset;
        y = oY + game.yOffset;
    }

    public void render(Graphics g) {
        g.drawImage(bi, x, y, Tile.TILESIZE * Game.SCALE, Tile.TILESIZE * Game.SCALE, null);
    }

}
I'm not sure if these would be optimized out by the compiler but

Tile.TILESIZE * SCALE
Tile.TILESIZE * Game.SCALE


are done more than once, why not just keep them as variables and...

for (int y = startY; y &lt; finishY; y++) {
 for (int x = startX; x &lt; finishX; x++) {
   map.tile.get((y*map.getMapWidth())+x).render(g);


...why do a multiplication for every y? you could just have a variable and increment it

int yLoc = startY * map.getWidth();
for (int y = startY; y &lt; finishY; y++) {
 for (int x = startX; x &lt; finishX; x++) {
   map.tile.get(yLoc+x).render(g);
 }
 yLoc += map.getMapWidth();
}


then you only need to do one multiplication and one addition for each y step instead of a multiplication for every y