3
\$\begingroup\$

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);
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 16, 2014 at 6:33
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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

answered Jan 16, 2014 at 9:25
\$\endgroup\$
3
  • \$\begingroup\$ Shouldn't the declaration of yloc be inside the first loop? \$\endgroup\$ Commented Jan 16, 2014 at 9:51
  • \$\begingroup\$ 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 \$\endgroup\$ Commented Jan 16, 2014 at 9:54
  • 1
    \$\begingroup\$ Ahh that is some good advice there. Thank you. I want to try and flesh out as much performance as I can. \$\endgroup\$ Commented Jan 16, 2014 at 10:17

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.