Fast Image Rendering in Slick

Hi guys,

I recently started using Slick earlier today and I have found it extremely useful. I managed to get a working game prototype up and running in only a few hours (that includes the time it took me to draw and animate sprites).

The game uses a 20 x 20 grid of tiles. When the game initializes, it draws all the tiles onto one image, which takes about 2 - 3 seconds. During that time it displays a black screen, but that’s fine I’m sure I can put a loading screen or something there.
During the game, it is very smooth and I have no problems because I only draw the one image with all the tiles drawn onto it.

When the player presses space bar, the tile under them changes. To make change visible I redrew all the tiles onto the image, but this freezes the game for about a second. I tried only drawing the changed tile onto the image, but it had the same effect.

I also tried to draw the tiles directly, instead of onto an image first. I get a FPS of only 2 or 3 then. So I tried drawing only those within 5 tiles of the character and got a FPS of 14 or 15. An improvement, but the game still wasn’t smooth.

Is there a better way of drawing all the tiles onto the screen so that they can be changed on the fly without the game freezing?

A 20x20 grid shouldn’t be a problem when your images aren’t very big.
Could you post some code, especially the render and update method ( stripped down ) ?

Alright, he’s a very dumbed-down version of my code.
I tried to take out everything unnecessary.

The tiles are all in one png file, which I load into an Animation and turn auto update off so it doesn’t cycle through.
Then when I change the tile, I simply change the frame of the animation.

When I recall drawTiles() in the grid class, that’s when the game freezes for a bit.

Thanks for your help!


/* Grid Class */
Image img;
Graphics g;
int width = 20;
int height = 20;
Animation[][] tiles = new Animation[height][width];

init(){
    img = new Image(width*60, height*60); //tile size is 60x60
    g = tiledImage.getGraphics();

    for(int i=0; i<height; i++){
	for(int j=0; j<width; j++){
            Image tileImg = new Image("tiles.png");
	    SpriteSheet sheet = new SpriteSheet(tileImg, 60, 60);
            tiles[i][j] = new Animation(sheet, 1);
            tiles[i][j].setAutoUpdate(false);
        }
    }
}

drawTiles(){
    for(int i=0; i<height; i++){
	for(int j=0; j<width; j++){
	    try{
	        g.drawImage(tiles[i][j].getImage(), j*60, i*60);
	    }catch(SlickException e){}
        }
    }
    g.flush();
}

/* Main game class */
Grid grid = new Grid();
update(){
   if(user presses spacebar){
        //tile changes
        grid.drawTiles();
   }
}

render(){
    grid.img.drawImage(0, 0);
}


My knowledge is very very limited but I think the problem is the lack of buffered images.(imagebuffer) (search slick and buffered
I think what might be happening is that its pulling from the image file each time. I could be wrong but its my guess.

Slick only has Images, but that’s fine. :slight_smile:

I can’t really figure out why you chose to store images in an animation, and other stuff… I’m just going to give
you my way of drawing a tilemap that can be changed on the fly.

I usually create a tile object, holding it’s own position and an image perhaps.
If I ALL the tiled, I use a Tile[][]-array, and load all the tiles into it on initialization.
When I need to change something about it I can just do something like this:


public Tile getTile(x, y) {
     return tiles[x][y];
}

getTile(1,1).changeImage(Art.getBrick(4));

Where my art class contains this:


private static Image[] bricks = new Image[8];

    public static void loadBricks()
    {
        try {
            SpriteSheet sheet = new SpriteSheet(ART_PATH + "bricks.png", 20, 20);
            for (int i = 0; i < 8; i++)
            {
                bricks[i] = sheet.getSubImage(i, 0);
            }
        } catch (SlickException ex) {
            Logger.getLogger(Art.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static Image getBrickImage(int id)
    {
        return bricks[id];
    }

This way images are only loaded once into different image-objects, saving that CPU usage.

It depends how much you need to change, and how often… With the imformation you gave, this approach should be fast though :slight_smile:

Good luck! :smiley: