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);
    }

}
\$\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

\$\endgroup\$
3
  • \$\begingroup\$ Shouldn't the declaration of yloc be inside the first loop? \$\endgroup\$
    – Bobby
    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\$
    – Ross Drew
    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\$
    – Hayden
    Jan 16, 2014 at 10:17

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.