# 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 < 0) {
startX = 0;
} if (finishX > map.getMapWidth()) {
finishX = map.getMapWidth();
} if (startY < 0) {
startY = 0;
} if (finishY > 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 < finishY; y++) {
for (int x = startX; x < 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 < finishY; y++) {
for (int x = startX; x < 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 < finishY; y++) {
for (int x = startX; x < 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

• Shouldn't the declaration of yloc be inside the first loop? – Bobby Jan 16 '14 at 9:51
• I think you mean the increment of yLoc. If the declaration was inside, then it would always be equal to the map width. I've fixed it – Ross Drew Jan 16 '14 at 9:54
• Ahh that is some good advice there. Thank you. I want to try and flesh out as much performance as I can. – Hayden Jan 16 '14 at 10:17